diff --git a/.gitattributes b/.gitattributes index 3272fb7dd6..8fada5fede 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -* text=auto +* text eol=auto *.png binary *.ico binary diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/modules/client/src/com/haulmont/cuba/client/ClientConfig.java b/modules/client/src/com/haulmont/cuba/client/ClientConfig.java index 97336e2e0d..c77622694f 100644 --- a/modules/client/src/com/haulmont/cuba/client/ClientConfig.java +++ b/modules/client/src/com/haulmont/cuba/client/ClientConfig.java @@ -1,385 +1,385 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.*; -import com.haulmont.cuba.core.config.type.CommaSeparatedStringListTypeFactory; -import com.haulmont.cuba.core.config.type.Factory; - -import java.util.List; -import java.util.regex.Pattern; - -/** - * Configuration parameters interface used by the WEB and DESKTOP layers. - */ -@Source(type = SourceType.APP) -public interface ClientConfig extends Config { - - /** - * @return middleware connection URL list - */ - @Property("cuba.connectionUrlList") - @Factory(factory = CommaSeparatedStringListTypeFactory.class) - List getConnectionUrlList(); - - /** - * @return Context of the middleware file download controller. - */ - @Property("cuba.fileDownloadContext") - @DefaultString("/download") - String getFileDownloadContext(); - - /** - * @return Context of the middleware file upload controller. - */ - @Property("cuba.fileUploadContext") - @DefaultString("/upload") - String getFileUploadContext(); - - /** - * @return Maximum size of uploaded file in megabytes. - */ - @Property("cuba.maxUploadSizeMb") - @Source(type = SourceType.DATABASE) - @DefaultInt(20) - int getMaxUploadSizeMb(); - void setMaxUploadSizeMb(int value); - - @Factory(factory = UniqueConstraintViolationPatternFactory.class) - @Source(type = SourceType.DATABASE) - @Property("cuba.uniqueConstraintViolationPattern") - Pattern getUniqueConstraintViolationPattern(); - - /** - * @return Whether to enable sorting of datasource data on DB (using separate SELECT with ORDER BY clause). - */ - @Property("cuba.collectionDatasourceDbSortEnabled") - @DefaultBoolean(true) - boolean getCollectionDatasourceDbSortEnabled(); - - /** - * @return If true, client will try to find missing localized messages on the server. - */ - @Property("cuba.remoteMessagesSearchEnabled") - @DefaultBoolean(false) - boolean getRemoteMessagesSearchEnabled(); - - /** - * List of screen aliases for which saving screen history is enabled. - *

Obsolete. Recommended way to specify this information is entity annotations - * in {@code *-metadata.xml}

- * @return comma-separated list of screen aliases - */ - @Property("cuba.screenIdsToSaveHistory") - String getScreenIdsToSaveHistory(); - - /** - * @return Whether to enable password policy. If true, all new passwords will be checked for the compliance with - * {@code cuba.passwordPolicyRegExp} - */ - @Property("cuba.passwordPolicyEnabled") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getPasswordPolicyEnabled(); - - /** - * @return The regular expression which is used by password policy (see also {@code cuba.passwordPolicyEnabled}). - */ - @Property("cuba.passwordPolicyRegExp") - @Source(type = SourceType.DATABASE) - @DefaultString("((?=.*\\d)(?=.*\\p{javaLowerCase})(?=.*\\p{javaUpperCase}).{6,20})") - String getPasswordPolicyRegExp(); - - /** - * @return If true, all generic filters will require explicit Apply after screen opening. Empty connected table - * is shown.
- * If false, the filter will be applied automatically, refreshing the table immediately after the screen opening. - */ - @Property("cuba.gui.genericFilterManualApplyRequired") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getGenericFilterManualApplyRequired(); - - /** - * @return If true, then check filter conditions (empty or not) before applying filter. If all conditions are empty - * (no parameters entered), the filter doesn't apply and special message to user is shown.
- * If false, no checks are performed and the filter applyes, refreshing connected table. - */ - @Property("cuba.gui.genericFilterChecking") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getGenericFilterChecking(); - - /** - * @return If true, all generic text filters will trim value.
- * If false, the text filter will not be trim value. - */ - @Property("cuba.gui.genericFilterTrimParamValues") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getGenericFilterTrimParamValues(); - - /** - * @return Number of columns with conditions in generic filter UI component. - */ - @Property("cuba.gui.genericFilterColumnsCount") - @Source(type = SourceType.DATABASE) - @DefaultInt(3) - int getGenericFilterColumnsCount(); - - /** - * @return location of panel with conditions in generic filter component. - * If {@code top} then conditions will be placed above filter control elements - * or below them if {@code bottom}. - */ - @Property("cuba.gui.genericFilterConditionsLocation") - @Source(type = SourceType.DATABASE) - @Default("top") - String getGenericFilterConditionsLocation(); - - /** - * Returns a number of items to be displayed in popup list near the 'Search' button. If number of filter - * entities exceeds this value then 'Show more..' action is added to the popup list. The action - * will show new dialog window with all possible filter entities for selecting a desired one. - */ - @Property("cuba.gui.genericFilterPopupListSize") - @Source(type = SourceType.DATABASE) - @DefaultInt(10) - int getGenericFilterPopupListSize(); - - /** - * Returns a template for filter controls layout. Each component has the following format: - * [component_name | options-comma-separated], e.g. [pin | no-caption, no-icon]. - *

Available component names:

- * - * The following components can be used as options for {@code settings} component. They also can be used as - * independent components if for example you want to display a Pin button: - * - * Action components can have the following options: - * - * @return a template for filter controls layout - */ - @Property("cuba.gui.genericFilterControlsLayout") - @Source(type = SourceType.DATABASE) - @Default("[filters_popup] [add_condition] [spacer] [settings | save, save_as, edit, remove, make_default, pin, save_search_folder, save_app_folder] [max_results] [fts_switch]") - String getGenericFilterControlsLayout(); - - /** - * Returns a comma-separated list of values that are used as options for "Show rows" lookup field - * of generic filter component. Add NULL option to the list if the lookup field should contain an empty value. - */ - @Property("cuba.gui.genericFilterMaxResultsOptions") - @Source(type = SourceType.DATABASE) - @Default("NULL, 20, 50, 100, 500, 1000, 5000") - String getGenericFilterMaxResultsOptions(); - - /** - * Support e-mail. Exception report emails are sent to this address. - */ - @Property("cuba.supportEmail") - @Source(type = SourceType.DATABASE) - String getSupportEmail(); - - /** - * @return System ID. Use for identification (support emails). - */ - @Property("cuba.systemId") - @DefaultString("CUBA") - @Source(type = SourceType.DATABASE) - String getSystemID(); - - @Property("cuba.gui.tableShortcut.insert") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-BACKSLASH") - String getTableInsertShortcut(); - - @Property("cuba.gui.tableShortcut.add") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ALT-BACKSLASH") - String getTableAddShortcut(); - - @Property("cuba.gui.tableShortcut.remove") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-DELETE") - String getTableRemoveShortcut(); - - @Property("cuba.gui.tableShortcut.edit") - @Source(type = SourceType.DATABASE) - @DefaultString("ENTER") - String getTableEditShortcut(); - - @Property("cuba.gui.commitShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ENTER") - String getCommitShortcut(); - - @Property("cuba.gui.closeShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("ESCAPE") - String getCloseShortcut(); - - @Property("cuba.gui.filterApplyShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("SHIFT-ENTER") - String getFilterApplyShortcut(); - - @Property("cuba.gui.filterSelectShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("SHIFT-BACKSPACE") - String getFilterSelectShortcut(); - - @Property("cuba.gui.nextTabShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-SHIFT-PAGE_DOWN") - String getNextTabShortcut(); - - @Property("cuba.gui.previousTabShortcut") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-SHIFT-PAGE_UP") - String getPreviousTabShortcut(); - - @Property("cuba.gui.pickerShortcut.modifiers") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ALT") - String getPickerShortcutModifiers(); - - @Property("cuba.gui.pickerShortcut.lookup") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ALT-L") - String getPickerLookupShortcut(); - - @Property("cuba.gui.pickerShortcut.open") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ALT-O") - String getPickerOpenShortcut(); - - @Property("cuba.gui.pickerShortcut.clear") - @Source(type = SourceType.DATABASE) - @DefaultString("CTRL-ALT-C") - String getPickerClearShortcut(); - - @Property("cuba.gui.useSaveConfirmation") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getUseSaveConfirmation(); - - @Property("cuba.gui.loadObsoleteSettingsForTable") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getLoadObsoleteSettingsForTable(); - - @Property("cuba.gui.layoutAnalyzerEnabled") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getLayoutAnalyzerEnabled(); - - @Property("cuba.gui.systemInfoScriptsEnabled") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getSystemInfoScriptsEnabled(); - void setSystemInfoScriptsEnabled(boolean enabled); - - @Property("cuba.gui.manualScreenSettingsSaving") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getManualScreenSettingsSaving(); - - @Property("cuba.gui.showIconsForPopupMenuActions") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getShowIconsForPopupMenuActions(); - - @Property("cuba.gui.lookupFieldPageLength") - @Source(type = SourceType.DATABASE) - @DefaultInt(10) - int getLookupFieldPageLength(); - void setLookupFieldPageLength(int pageLength); - - /** - * Interval for checking timeout of a BackgroundTask. - * - * @return Timeout in ms - */ - @Property("cuba.backgroundWorker.timeoutCheckInterval") - @DefaultInteger(5000) - Integer getBackgroundTaskTimeoutCheckInterval(); - - /** - * @return true if Table will ignore unfetched attribute read errors - */ - @Property("cuba.gui.ignoreUnfetchedAttributesInTable") - @DefaultBoolean(false) - boolean getIgnoreUnfetchedAttributesInTable(); - - @Property("cuba.gui.dynamicAttributesTableColumnMaxTextLength") - @Source(type = SourceType.DATABASE) - @DefaultInt(50) - int getDynamicAttributesTableColumnMaxTextLength(); - void setDynamicAttributesTableColumnMaxTextLength(int maxTextLength); - - /** - * Defines default behaviour of {@code CreateAction}: whether it will add a new item to the beginning or to the - * end of datasource's collection. Affects only standalone datasources, for nested datasources new items are always - * added to the end. - */ - @Property("cuba.gui.createActionAddsFirst") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getCreateActionAddsFirst(); - - @Property("cuba.gui.suggestionField.asyncSearchDelayMs") - @DefaultInt(300) - int getSuggestionFieldAsyncSearchDelayMs(); - - /** - * Standard Window validation error notification type. - * - * @return one of com.haulmont.cuba.gui.components.Frame.NotificationType values - */ - @Property("cuba.gui.validationNotificationType") - @Default("TRAY") - String getValidationNotificationType(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.*; +import com.haulmont.cuba.core.config.type.CommaSeparatedStringListTypeFactory; +import com.haulmont.cuba.core.config.type.Factory; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * Configuration parameters interface used by the WEB and DESKTOP layers. + */ +@Source(type = SourceType.APP) +public interface ClientConfig extends Config { + + /** + * @return middleware connection URL list + */ + @Property("cuba.connectionUrlList") + @Factory(factory = CommaSeparatedStringListTypeFactory.class) + List getConnectionUrlList(); + + /** + * @return Context of the middleware file download controller. + */ + @Property("cuba.fileDownloadContext") + @DefaultString("/download") + String getFileDownloadContext(); + + /** + * @return Context of the middleware file upload controller. + */ + @Property("cuba.fileUploadContext") + @DefaultString("/upload") + String getFileUploadContext(); + + /** + * @return Maximum size of uploaded file in megabytes. + */ + @Property("cuba.maxUploadSizeMb") + @Source(type = SourceType.DATABASE) + @DefaultInt(20) + int getMaxUploadSizeMb(); + void setMaxUploadSizeMb(int value); + + @Factory(factory = UniqueConstraintViolationPatternFactory.class) + @Source(type = SourceType.DATABASE) + @Property("cuba.uniqueConstraintViolationPattern") + Pattern getUniqueConstraintViolationPattern(); + + /** + * @return Whether to enable sorting of datasource data on DB (using separate SELECT with ORDER BY clause). + */ + @Property("cuba.collectionDatasourceDbSortEnabled") + @DefaultBoolean(true) + boolean getCollectionDatasourceDbSortEnabled(); + + /** + * @return If true, client will try to find missing localized messages on the server. + */ + @Property("cuba.remoteMessagesSearchEnabled") + @DefaultBoolean(false) + boolean getRemoteMessagesSearchEnabled(); + + /** + * List of screen aliases for which saving screen history is enabled. + *

Obsolete. Recommended way to specify this information is entity annotations + * in {@code *-metadata.xml}

+ * @return comma-separated list of screen aliases + */ + @Property("cuba.screenIdsToSaveHistory") + String getScreenIdsToSaveHistory(); + + /** + * @return Whether to enable password policy. If true, all new passwords will be checked for the compliance with + * {@code cuba.passwordPolicyRegExp} + */ + @Property("cuba.passwordPolicyEnabled") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getPasswordPolicyEnabled(); + + /** + * @return The regular expression which is used by password policy (see also {@code cuba.passwordPolicyEnabled}). + */ + @Property("cuba.passwordPolicyRegExp") + @Source(type = SourceType.DATABASE) + @DefaultString("((?=.*\\d)(?=.*\\p{javaLowerCase})(?=.*\\p{javaUpperCase}).{6,20})") + String getPasswordPolicyRegExp(); + + /** + * @return If true, all generic filters will require explicit Apply after screen opening. Empty connected table + * is shown.
+ * If false, the filter will be applied automatically, refreshing the table immediately after the screen opening. + */ + @Property("cuba.gui.genericFilterManualApplyRequired") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getGenericFilterManualApplyRequired(); + + /** + * @return If true, then check filter conditions (empty or not) before applying filter. If all conditions are empty + * (no parameters entered), the filter doesn't apply and special message to user is shown.
+ * If false, no checks are performed and the filter applyes, refreshing connected table. + */ + @Property("cuba.gui.genericFilterChecking") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getGenericFilterChecking(); + + /** + * @return If true, all generic text filters will trim value.
+ * If false, the text filter will not be trim value. + */ + @Property("cuba.gui.genericFilterTrimParamValues") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getGenericFilterTrimParamValues(); + + /** + * @return Number of columns with conditions in generic filter UI component. + */ + @Property("cuba.gui.genericFilterColumnsCount") + @Source(type = SourceType.DATABASE) + @DefaultInt(3) + int getGenericFilterColumnsCount(); + + /** + * @return location of panel with conditions in generic filter component. + * If {@code top} then conditions will be placed above filter control elements + * or below them if {@code bottom}. + */ + @Property("cuba.gui.genericFilterConditionsLocation") + @Source(type = SourceType.DATABASE) + @Default("top") + String getGenericFilterConditionsLocation(); + + /** + * Returns a number of items to be displayed in popup list near the 'Search' button. If number of filter + * entities exceeds this value then 'Show more..' action is added to the popup list. The action + * will show new dialog window with all possible filter entities for selecting a desired one. + */ + @Property("cuba.gui.genericFilterPopupListSize") + @Source(type = SourceType.DATABASE) + @DefaultInt(10) + int getGenericFilterPopupListSize(); + + /** + * Returns a template for filter controls layout. Each component has the following format: + * [component_name | options-comma-separated], e.g. [pin | no-caption, no-icon]. + *

Available component names:

+ * + * The following components can be used as options for {@code settings} component. They also can be used as + * independent components if for example you want to display a Pin button: + * + * Action components can have the following options: + * + * @return a template for filter controls layout + */ + @Property("cuba.gui.genericFilterControlsLayout") + @Source(type = SourceType.DATABASE) + @Default("[filters_popup] [add_condition] [spacer] [settings | save, save_as, edit, remove, make_default, pin, save_search_folder, save_app_folder] [max_results] [fts_switch]") + String getGenericFilterControlsLayout(); + + /** + * Returns a comma-separated list of values that are used as options for "Show rows" lookup field + * of generic filter component. Add NULL option to the list if the lookup field should contain an empty value. + */ + @Property("cuba.gui.genericFilterMaxResultsOptions") + @Source(type = SourceType.DATABASE) + @Default("NULL, 20, 50, 100, 500, 1000, 5000") + String getGenericFilterMaxResultsOptions(); + + /** + * Support e-mail. Exception report emails are sent to this address. + */ + @Property("cuba.supportEmail") + @Source(type = SourceType.DATABASE) + String getSupportEmail(); + + /** + * @return System ID. Use for identification (support emails). + */ + @Property("cuba.systemId") + @DefaultString("CUBA") + @Source(type = SourceType.DATABASE) + String getSystemID(); + + @Property("cuba.gui.tableShortcut.insert") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-BACKSLASH") + String getTableInsertShortcut(); + + @Property("cuba.gui.tableShortcut.add") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ALT-BACKSLASH") + String getTableAddShortcut(); + + @Property("cuba.gui.tableShortcut.remove") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-DELETE") + String getTableRemoveShortcut(); + + @Property("cuba.gui.tableShortcut.edit") + @Source(type = SourceType.DATABASE) + @DefaultString("ENTER") + String getTableEditShortcut(); + + @Property("cuba.gui.commitShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ENTER") + String getCommitShortcut(); + + @Property("cuba.gui.closeShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("ESCAPE") + String getCloseShortcut(); + + @Property("cuba.gui.filterApplyShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("SHIFT-ENTER") + String getFilterApplyShortcut(); + + @Property("cuba.gui.filterSelectShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("SHIFT-BACKSPACE") + String getFilterSelectShortcut(); + + @Property("cuba.gui.nextTabShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-SHIFT-PAGE_DOWN") + String getNextTabShortcut(); + + @Property("cuba.gui.previousTabShortcut") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-SHIFT-PAGE_UP") + String getPreviousTabShortcut(); + + @Property("cuba.gui.pickerShortcut.modifiers") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ALT") + String getPickerShortcutModifiers(); + + @Property("cuba.gui.pickerShortcut.lookup") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ALT-L") + String getPickerLookupShortcut(); + + @Property("cuba.gui.pickerShortcut.open") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ALT-O") + String getPickerOpenShortcut(); + + @Property("cuba.gui.pickerShortcut.clear") + @Source(type = SourceType.DATABASE) + @DefaultString("CTRL-ALT-C") + String getPickerClearShortcut(); + + @Property("cuba.gui.useSaveConfirmation") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getUseSaveConfirmation(); + + @Property("cuba.gui.loadObsoleteSettingsForTable") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getLoadObsoleteSettingsForTable(); + + @Property("cuba.gui.layoutAnalyzerEnabled") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getLayoutAnalyzerEnabled(); + + @Property("cuba.gui.systemInfoScriptsEnabled") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getSystemInfoScriptsEnabled(); + void setSystemInfoScriptsEnabled(boolean enabled); + + @Property("cuba.gui.manualScreenSettingsSaving") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getManualScreenSettingsSaving(); + + @Property("cuba.gui.showIconsForPopupMenuActions") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getShowIconsForPopupMenuActions(); + + @Property("cuba.gui.lookupFieldPageLength") + @Source(type = SourceType.DATABASE) + @DefaultInt(10) + int getLookupFieldPageLength(); + void setLookupFieldPageLength(int pageLength); + + /** + * Interval for checking timeout of a BackgroundTask. + * + * @return Timeout in ms + */ + @Property("cuba.backgroundWorker.timeoutCheckInterval") + @DefaultInteger(5000) + Integer getBackgroundTaskTimeoutCheckInterval(); + + /** + * @return true if Table will ignore unfetched attribute read errors + */ + @Property("cuba.gui.ignoreUnfetchedAttributesInTable") + @DefaultBoolean(false) + boolean getIgnoreUnfetchedAttributesInTable(); + + @Property("cuba.gui.dynamicAttributesTableColumnMaxTextLength") + @Source(type = SourceType.DATABASE) + @DefaultInt(50) + int getDynamicAttributesTableColumnMaxTextLength(); + void setDynamicAttributesTableColumnMaxTextLength(int maxTextLength); + + /** + * Defines default behaviour of {@code CreateAction}: whether it will add a new item to the beginning or to the + * end of datasource's collection. Affects only standalone datasources, for nested datasources new items are always + * added to the end. + */ + @Property("cuba.gui.createActionAddsFirst") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getCreateActionAddsFirst(); + + @Property("cuba.gui.suggestionField.asyncSearchDelayMs") + @DefaultInt(300) + int getSuggestionFieldAsyncSearchDelayMs(); + + /** + * Standard Window validation error notification type. + * + * @return one of com.haulmont.cuba.gui.components.Frame.NotificationType values + */ + @Property("cuba.gui.validationNotificationType") + @Default("TRAY") + String getValidationNotificationType(); } \ No newline at end of file diff --git a/modules/client/src/com/haulmont/cuba/client/sys/cache/CachingStrategy.java b/modules/client/src/com/haulmont/cuba/client/sys/cache/CachingStrategy.java index 9fc789e4b6..700cbe5b2d 100644 --- a/modules/client/src/com/haulmont/cuba/client/sys/cache/CachingStrategy.java +++ b/modules/client/src/com/haulmont/cuba/client/sys/cache/CachingStrategy.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client.sys.cache; - -import java.util.concurrent.locks.ReadWriteLock; - -/** - * Describes cache storage and invalidation policy -*/ -public interface CachingStrategy { - /** - * Method for strategy initialization - * Invoked at first login, so security context is available - */ - default void init() { - } - - /** - * Return cached object - */ - Object getObject(); - - /** - * Refresh cached object - */ - Object loadObject(); - - /** - * Return lock used to provide caching thread safety - */ - ReadWriteLock lock(); - - /** - * Indicate whether cached object should be refreshed or not - */ - boolean needToReload(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client.sys.cache; + +import java.util.concurrent.locks.ReadWriteLock; + +/** + * Describes cache storage and invalidation policy +*/ +public interface CachingStrategy { + /** + * Method for strategy initialization + * Invoked at first login, so security context is available + */ + default void init() { + } + + /** + * Return cached object + */ + Object getObject(); + + /** + * Refresh cached object + */ + Object loadObject(); + + /** + * Return lock used to provide caching thread safety + */ + ReadWriteLock lock(); + + /** + * Indicate whether cached object should be refreshed or not + */ + boolean needToReload(); } \ No newline at end of file diff --git a/modules/client/src/com/haulmont/cuba/client/sys/cache/ClientCacheManager.java b/modules/client/src/com/haulmont/cuba/client/sys/cache/ClientCacheManager.java index 680ecdf872..b4f3479946 100644 --- a/modules/client/src/com/haulmont/cuba/client/sys/cache/ClientCacheManager.java +++ b/modules/client/src/com/haulmont/cuba/client/sys/cache/ClientCacheManager.java @@ -1,166 +1,166 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client.sys.cache; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.sys.AppContext; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.locks.Lock; - -/** - * Provides ability to cache any abstract object in client application - */ -@Component(ClientCacheManager.NAME) -public class ClientCacheManager implements AppContext.Listener, Ordered { - - public static final String NAME = "cuba_ClientCacheManager"; - - private static final Logger log = LoggerFactory.getLogger(ClientCacheManager.class); - - protected final Object initializationLock = new Object(); - protected volatile boolean initialized = false; - - protected ConcurrentHashMap cache = new ConcurrentHashMap<>(); - protected ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() { - final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); - - @Override - public Thread newThread(@Nonnull Runnable r) { - Thread thread = defaultFactory.newThread(r); - thread.setName("ClientCacheManager-" + thread.getName()); - thread.setUncaughtExceptionHandler((t, e) -> - log.error("Unhandled exception", t) - ); - return thread; - } - }); - - public ClientCacheManager() { - AppContext.addListener(this); - } - - public void initialize() { - if (!initialized) { - synchronized (initializationLock) { - Map cachingStrategyMap = AppBeans.getAll(CachingStrategy.class); - for (Map.Entry entry : cachingStrategyMap.entrySet()) { - addCachedObject(entry.getKey(), entry.getValue()); - } - } - initialized = true; - } - } - - /** - * Get cached object by its name - */ - @Nullable - @SuppressWarnings("unchecked") - public T getCached(String name) { - CachingStrategy cachingStrategy = cache.get(name); - if (cachingStrategy != null) { - Lock readLock = cachingStrategy.lock().readLock(); - Lock writeLock = cachingStrategy.lock().writeLock(); - try { - readLock.lock(); - if (!cachingStrategy.needToReload()) { - return (T) cachingStrategy.getObject(); - } else { - try { - readLock.unlock(); - writeLock.lock(); - if (cachingStrategy.needToReload()) {//re-check condition - return (T) cachingStrategy.loadObject(); - } else { - return (T) cachingStrategy.getObject(); - } - } finally { - readLock.lock();//downgrade lock to read-only - writeLock.unlock(); - } - } - } finally { - readLock.unlock(); - } - } - - return null; - } - - public void refreshCached(String name) { - CachingStrategy cachingStrategy = cache.get(name); - if (cachingStrategy != null) { - Lock writeLock = cachingStrategy.lock().writeLock(); - try { - writeLock.lock(); - cachingStrategy.loadObject(); - } finally { - writeLock.unlock(); - } - } - } - - /** - * Add new cached object (described in cachingStrategy) - */ - public void addCachedObject(String key, CachingStrategy cachingStrategy) { - Lock writeLock = cachingStrategy.lock().writeLock(); - try { - writeLock.lock(); - cachingStrategy.init(); - } finally { - writeLock.unlock(); - } - - cache.put(key, cachingStrategy); - } - - public ScheduledExecutorService getExecutorService() { - return executorService; - } - - @Override - public void applicationStarted() { - } - - @Override - public void applicationStopped() { - try { - executorService.shutdownNow(); - } catch (Exception e) { - //do nothing - } - } - - @Override - public int getOrder() { - return LOWEST_PLATFORM_PRECEDENCE - 120; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client.sys.cache; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.sys.AppContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.locks.Lock; + +/** + * Provides ability to cache any abstract object in client application + */ +@Component(ClientCacheManager.NAME) +public class ClientCacheManager implements AppContext.Listener, Ordered { + + public static final String NAME = "cuba_ClientCacheManager"; + + private static final Logger log = LoggerFactory.getLogger(ClientCacheManager.class); + + protected final Object initializationLock = new Object(); + protected volatile boolean initialized = false; + + protected ConcurrentHashMap cache = new ConcurrentHashMap<>(); + protected ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() { + final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + + @Override + public Thread newThread(@Nonnull Runnable r) { + Thread thread = defaultFactory.newThread(r); + thread.setName("ClientCacheManager-" + thread.getName()); + thread.setUncaughtExceptionHandler((t, e) -> + log.error("Unhandled exception", t) + ); + return thread; + } + }); + + public ClientCacheManager() { + AppContext.addListener(this); + } + + public void initialize() { + if (!initialized) { + synchronized (initializationLock) { + Map cachingStrategyMap = AppBeans.getAll(CachingStrategy.class); + for (Map.Entry entry : cachingStrategyMap.entrySet()) { + addCachedObject(entry.getKey(), entry.getValue()); + } + } + initialized = true; + } + } + + /** + * Get cached object by its name + */ + @Nullable + @SuppressWarnings("unchecked") + public T getCached(String name) { + CachingStrategy cachingStrategy = cache.get(name); + if (cachingStrategy != null) { + Lock readLock = cachingStrategy.lock().readLock(); + Lock writeLock = cachingStrategy.lock().writeLock(); + try { + readLock.lock(); + if (!cachingStrategy.needToReload()) { + return (T) cachingStrategy.getObject(); + } else { + try { + readLock.unlock(); + writeLock.lock(); + if (cachingStrategy.needToReload()) {//re-check condition + return (T) cachingStrategy.loadObject(); + } else { + return (T) cachingStrategy.getObject(); + } + } finally { + readLock.lock();//downgrade lock to read-only + writeLock.unlock(); + } + } + } finally { + readLock.unlock(); + } + } + + return null; + } + + public void refreshCached(String name) { + CachingStrategy cachingStrategy = cache.get(name); + if (cachingStrategy != null) { + Lock writeLock = cachingStrategy.lock().writeLock(); + try { + writeLock.lock(); + cachingStrategy.loadObject(); + } finally { + writeLock.unlock(); + } + } + } + + /** + * Add new cached object (described in cachingStrategy) + */ + public void addCachedObject(String key, CachingStrategy cachingStrategy) { + Lock writeLock = cachingStrategy.lock().writeLock(); + try { + writeLock.lock(); + cachingStrategy.init(); + } finally { + writeLock.unlock(); + } + + cache.put(key, cachingStrategy); + } + + public ScheduledExecutorService getExecutorService() { + return executorService; + } + + @Override + public void applicationStarted() { + } + + @Override + public void applicationStopped() { + try { + executorService.shutdownNow(); + } catch (Exception e) { + //do nothing + } + } + + @Override + public int getOrder() { + return LOWEST_PLATFORM_PRECEDENCE - 120; + } } \ No newline at end of file diff --git a/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesCacheStrategy.java b/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesCacheStrategy.java index 6aec795398..fdb17fa1c3 100644 --- a/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesCacheStrategy.java +++ b/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesCacheStrategy.java @@ -1,108 +1,108 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client.sys.cache; - -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCache; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCacheService; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.global.NoUserSessionException; -import com.haulmont.cuba.security.global.UserSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Each time dynamic attributes cache is used, the strategy initiate check of cache validity - * The check is performed in separate thread - * So applied changes in dynamic attributes structure will be visible after 10 seconds - */ -@Component(DynamicAttributesCacheStrategy.NAME) -public class DynamicAttributesCacheStrategy implements CachingStrategy { - public static final String NAME = "cuba_DynamicAttributesCacheStrategy"; - - private final Logger log = LoggerFactory.getLogger(DynamicAttributesCacheStrategy.class); - - @Inject - protected ClientCacheManager clientCacheManager; - @Inject - protected CacheUserSessionProvider cacheUserSessionProvider; - - protected ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - protected DynamicAttributesCache dynamicAttributesCache; - - //there is no need for atomicity when change needToValidateCache or lastRequestedSessionId - protected volatile boolean needToValidateCache; - - @Override - public void init() { - clientCacheManager.getExecutorService().scheduleWithFixedDelay(() -> { - if (needToValidateCache) { - UserSession userSession = cacheUserSessionProvider.getUserSession(); - if (userSession == null) { - // cache user session unavailable - return; - } - - try { - AppContext.setSecurityContext(new SecurityContext(userSession)); - - loadObject(); - } catch (NoUserSessionException e) { - log.warn("Cache user session expired", e); - } catch (Exception e) { - log.error("Unable to update dynamic attributes cache", e); - } - } - }, 0, 10, TimeUnit.SECONDS); - } - - @Override - public Object getObject() { - needToValidateCache = true; - return dynamicAttributesCache; - } - - @Override - public Object loadObject() { - DynamicAttributesCache cacheFromServer = AppBeans.get(DynamicAttributesCacheService.NAME, DynamicAttributesCacheService.class) - .getCacheIfNewer(dynamicAttributesCache != null ? dynamicAttributesCache.getCreationDate() : null); - if (cacheFromServer != null) { - dynamicAttributesCache = cacheFromServer; - } - - needToValidateCache = false; - return dynamicAttributesCache; - } - - @Override - public boolean needToReload() { - return dynamicAttributesCache == null; - } - - @Override - public ReadWriteLock lock() { - return readWriteLock; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client.sys.cache; + +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCache; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCacheService; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.global.NoUserSessionException; +import com.haulmont.cuba.security.global.UserSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Each time dynamic attributes cache is used, the strategy initiate check of cache validity + * The check is performed in separate thread + * So applied changes in dynamic attributes structure will be visible after 10 seconds + */ +@Component(DynamicAttributesCacheStrategy.NAME) +public class DynamicAttributesCacheStrategy implements CachingStrategy { + public static final String NAME = "cuba_DynamicAttributesCacheStrategy"; + + private final Logger log = LoggerFactory.getLogger(DynamicAttributesCacheStrategy.class); + + @Inject + protected ClientCacheManager clientCacheManager; + @Inject + protected CacheUserSessionProvider cacheUserSessionProvider; + + protected ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + protected DynamicAttributesCache dynamicAttributesCache; + + //there is no need for atomicity when change needToValidateCache or lastRequestedSessionId + protected volatile boolean needToValidateCache; + + @Override + public void init() { + clientCacheManager.getExecutorService().scheduleWithFixedDelay(() -> { + if (needToValidateCache) { + UserSession userSession = cacheUserSessionProvider.getUserSession(); + if (userSession == null) { + // cache user session unavailable + return; + } + + try { + AppContext.setSecurityContext(new SecurityContext(userSession)); + + loadObject(); + } catch (NoUserSessionException e) { + log.warn("Cache user session expired", e); + } catch (Exception e) { + log.error("Unable to update dynamic attributes cache", e); + } + } + }, 0, 10, TimeUnit.SECONDS); + } + + @Override + public Object getObject() { + needToValidateCache = true; + return dynamicAttributesCache; + } + + @Override + public Object loadObject() { + DynamicAttributesCache cacheFromServer = AppBeans.get(DynamicAttributesCacheService.NAME, DynamicAttributesCacheService.class) + .getCacheIfNewer(dynamicAttributesCache != null ? dynamicAttributesCache.getCreationDate() : null); + if (cacheFromServer != null) { + dynamicAttributesCache = cacheFromServer; + } + + needToValidateCache = false; + return dynamicAttributesCache; + } + + @Override + public boolean needToReload() { + return dynamicAttributesCache == null; + } + + @Override + public ReadWriteLock lock() { + return readWriteLock; + } } \ No newline at end of file diff --git a/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesClientImpl.java b/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesClientImpl.java index 0d51e5b249..953e2c7e2e 100644 --- a/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesClientImpl.java +++ b/modules/client/src/com/haulmont/cuba/client/sys/cache/DynamicAttributesClientImpl.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client.sys.cache; - -import com.google.common.base.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCache; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; - -import org.springframework.stereotype.Component; -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.Collection; - -@Component(DynamicAttributes.NAME) -public class DynamicAttributesClientImpl implements DynamicAttributes { - @Inject - protected ClientCacheManager clientCacheManager; - - @Override - public Collection getCategoriesForMetaClass(MetaClass metaClass) { - return cache().getCategoriesForMetaClass(metaClass); - } - - @Override - public Collection getAttributesForMetaClass(MetaClass metaClass) { - return cache().getAttributesForMetaClass(metaClass); - } - - @Nullable - @Override - public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { - return cache().getAttributeForMetaClass(metaClass, code); - } - - protected DynamicAttributesCache cache() { - DynamicAttributesCache cache = clientCacheManager.getCached(DynamicAttributesCacheStrategy.NAME); - Preconditions.checkState(cache != null, "Dynamic attributes cache is not available"); - return cache; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client.sys.cache; + +import com.google.common.base.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCache; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; + +import org.springframework.stereotype.Component; +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.Collection; + +@Component(DynamicAttributes.NAME) +public class DynamicAttributesClientImpl implements DynamicAttributes { + @Inject + protected ClientCacheManager clientCacheManager; + + @Override + public Collection getCategoriesForMetaClass(MetaClass metaClass) { + return cache().getCategoriesForMetaClass(metaClass); + } + + @Override + public Collection getAttributesForMetaClass(MetaClass metaClass) { + return cache().getAttributesForMetaClass(metaClass); + } + + @Nullable + @Override + public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { + return cache().getAttributeForMetaClass(metaClass, code); + } + + protected DynamicAttributesCache cache() { + DynamicAttributesCache cache = clientCacheManager.getCached(DynamicAttributesCacheStrategy.NAME); + Preconditions.checkState(cache != null, "Dynamic attributes cache is not available"); + return cache; + } } \ No newline at end of file diff --git a/modules/client/src/com/haulmont/cuba/client/sys/config/ConfigPersisterClientImpl.java b/modules/client/src/com/haulmont/cuba/client/sys/config/ConfigPersisterClientImpl.java index 45c266a13f..e07389a69b 100644 --- a/modules/client/src/com/haulmont/cuba/client/sys/config/ConfigPersisterClientImpl.java +++ b/modules/client/src/com/haulmont/cuba/client/sys/config/ConfigPersisterClientImpl.java @@ -1,112 +1,112 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.client.sys.config; - -import com.haulmont.cuba.core.app.ConfigStorageService; -import com.haulmont.cuba.core.config.ConfigPersister; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.sys.AppContext; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class ConfigPersisterClientImpl implements ConfigPersister { - private static final Logger log = LoggerFactory.getLogger(ConfigPersisterClientImpl.class); - - protected Map cache = new ConcurrentHashMap<>(); - - protected volatile boolean cacheLoaded; - protected boolean caching; - - protected ConfigStorageService configStorageService; - - public ConfigPersisterClientImpl(ConfigStorageService configStorageService, boolean caching) { - this.caching = caching; - this.configStorageService = configStorageService; - } - - @Override - public String getProperty(SourceType sourceType, String name) { - log.trace("Getting property '{}', source={}", name, sourceType.name()); - String value; - switch (sourceType) { - case SYSTEM: - value = System.getProperty(name); - break; - case APP: - value = AppContext.getProperty(name); - break; - case DATABASE: - value = AppContext.getProperty(name); - if (StringUtils.isEmpty(value)) { - if (caching) { - loadCache(); - value = cache.get(name); - } else { - return getConfigStorage().getDbProperty(name); - } - } - break; - default: - throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); - } - return value; - } - - protected void loadCache() { - if (!cacheLoaded) { - synchronized (this) { - if (!cacheLoaded) { - Map properties = getConfigStorage().getDbProperties(); - cache.clear(); - cache.putAll(properties); - cacheLoaded = true; - } - } - } - } - - @Override - public void setProperty(SourceType sourceType, String name, String value) { - log.debug("Setting property '{}' to '{}', source={}", name, value, sourceType.name()); - switch (sourceType) { - case SYSTEM: - System.setProperty(name, value); - break; - case APP: - AppContext.setProperty(name, value); - break; - case DATABASE: - if (value != null) { - cache.put(name, value); - } else { - cache.remove(name); - } - getConfigStorage().setDbProperty(name, value); - break; - default: - throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); - } - } - - protected ConfigStorageService getConfigStorage() { - return configStorageService; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.client.sys.config; + +import com.haulmont.cuba.core.app.ConfigStorageService; +import com.haulmont.cuba.core.config.ConfigPersister; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.sys.AppContext; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ConfigPersisterClientImpl implements ConfigPersister { + private static final Logger log = LoggerFactory.getLogger(ConfigPersisterClientImpl.class); + + protected Map cache = new ConcurrentHashMap<>(); + + protected volatile boolean cacheLoaded; + protected boolean caching; + + protected ConfigStorageService configStorageService; + + public ConfigPersisterClientImpl(ConfigStorageService configStorageService, boolean caching) { + this.caching = caching; + this.configStorageService = configStorageService; + } + + @Override + public String getProperty(SourceType sourceType, String name) { + log.trace("Getting property '{}', source={}", name, sourceType.name()); + String value; + switch (sourceType) { + case SYSTEM: + value = System.getProperty(name); + break; + case APP: + value = AppContext.getProperty(name); + break; + case DATABASE: + value = AppContext.getProperty(name); + if (StringUtils.isEmpty(value)) { + if (caching) { + loadCache(); + value = cache.get(name); + } else { + return getConfigStorage().getDbProperty(name); + } + } + break; + default: + throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); + } + return value; + } + + protected void loadCache() { + if (!cacheLoaded) { + synchronized (this) { + if (!cacheLoaded) { + Map properties = getConfigStorage().getDbProperties(); + cache.clear(); + cache.putAll(properties); + cacheLoaded = true; + } + } + } + } + + @Override + public void setProperty(SourceType sourceType, String name, String value) { + log.debug("Setting property '{}' to '{}', source={}", name, value, sourceType.name()); + switch (sourceType) { + case SYSTEM: + System.setProperty(name, value); + break; + case APP: + AppContext.setProperty(name, value); + break; + case DATABASE: + if (value != null) { + cache.put(name, value); + } else { + cache.remove(name); + } + getConfigStorage().setDbProperty(name, value); + break; + default: + throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); + } + } + + protected ConfigStorageService getConfigStorage() { + return configStorageService; + } } \ No newline at end of file diff --git a/modules/client/test/com/haulmont/cuba/client/testsupport/TestUuidSource.java b/modules/client/test/com/haulmont/cuba/client/testsupport/TestUuidSource.java index 24e295a7dd..efb06c1836 100644 --- a/modules/client/test/com/haulmont/cuba/client/testsupport/TestUuidSource.java +++ b/modules/client/test/com/haulmont/cuba/client/testsupport/TestUuidSource.java @@ -1,29 +1,29 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.client.testsupport; - -import com.haulmont.cuba.core.global.UuidSource; - -import java.util.UUID; - -public class TestUuidSource implements UuidSource { - @Override - public UUID createUuid() { - return UUID.randomUUID(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.client.testsupport; + +import com.haulmont.cuba.core.global.UuidSource; + +import java.util.UUID; + +public class TestUuidSource implements UuidSource { + @Override + public UUID createUuid() { + return UUID.randomUUID(); + } } \ No newline at end of file diff --git a/modules/core/db/init/hsql/create-db.sql b/modules/core/db/init/hsql/create-db.sql index 26ac1b5a19..1c089316a6 100644 --- a/modules/core/db/init/hsql/create-db.sql +++ b/modules/core/db/init/hsql/create-db.sql @@ -1,914 +1,914 @@ ------------------------------------------------------------------------------------------------------------- --- table for selecting sequence values in HSQL -create table DUAL (ID integer)^ -insert into DUAL (ID) values (0)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SERVER ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(255), - IS_RUNNING boolean, - DATA longvarchar, - -- - primary key (ID), - constraint IDX_SYS_SERVER_UNIQ_NAME unique (NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_CONFIG ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(255), - VALUE longvarchar, - -- - primary key (ID), - constraint IDX_SYS_CONFIG_UNIQ_NAME unique (NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FILE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(500) not null, - EXT varchar(20), - FILE_SIZE bigint, - CREATE_DATE timestamp, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_LOCK_CONFIG ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - NAME varchar(100), - TIMEOUT_SEC integer, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_STATISTICS ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(50), - INSTANCE_COUNT bigint, - FETCH_UI integer, - MAX_FETCH_UI integer, - LAZY_COLLECTION_THRESHOLD integer, - LOOKUP_SCREEN_THRESHOLD integer, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_TASK ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - BEAN_NAME varchar(50), - METHOD_NAME varchar(50), - METHOD_PARAMS varchar(1000), - DEFINED_BY varchar(1) default 'B', - CLASS_NAME varchar(500), - SCRIPT_NAME varchar(500), - USER_NAME varchar(50), - IS_SINGLETON boolean, - IS_ACTIVE boolean, - PERIOD integer, - TIMEOUT integer, - START_DATE timestamp, - TIME_FRAME integer, - START_DELAY integer, - PERMITTED_SERVERS varchar(4096), - LOG_START boolean, - LOG_FINISH boolean, - LAST_START_TIME timestamp, - LAST_START_SERVER varchar(512), - DESCRIPTION varchar(1000), - CRON varchar(100), - SCHEDULING_TYPE varchar(1) default 'P', - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_EXECUTION ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - TASK_ID varchar(36), - SERVER varchar(512), - START_TIME timestamp, - FINISH_TIME timestamp, - RESULT longvarchar, - -- - primary key (ID), - constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) -)^ - -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ROLE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - LOC_NAME varchar(255), - DESCRIPTION varchar(1000), - IS_DEFAULT_ROLE boolean, - ROLE_TYPE integer, - -- - primary key (ID) -)^ - --- Trigger example, HSQL throws NPE on constraint violation ---create trigger SEC_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_ROLE ---referencing NEW as newrow OLD AS oldrow ---for each row begin atomic --- if newrow.DELETE_TS != oldrow.DELETE_TS then --- if newrow.DELETE_TS is null then --- set newrow.DELETE_TS_NN = '1000-01-01 00:00:00.000'; --- else --- set newrow.DELETE_TS_NN = newrow.DELETE_TS; --- end if; --- end if; ---end;^ - -alter table SEC_ROLE add constraint IDX_SEC_ROLE_UNIQ_NAME unique (NAME, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - PARENT_ID varchar(36), - -- - primary key (ID), - constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - -alter table SEC_GROUP add constraint IDX_SEC_GROUP_UNIQ_NAME unique (NAME, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP_HIERARCHY ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - GROUP_ID varchar(36), - PARENT_ID varchar(36), - HIERARCHY_LEVEL integer, - -- - primary key (ID), - constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), - constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - LOGIN varchar(50) not null, - LOGIN_LC varchar(50) not null, - PASSWORD varchar(255), - NAME varchar(255), - FIRST_NAME varchar(255), - LAST_NAME varchar(255), - MIDDLE_NAME varchar(255), - POSITION_ varchar(255), - EMAIL varchar(100), - LANGUAGE_ varchar(20), - TIME_ZONE varchar(50), - TIME_ZONE_AUTO boolean, - ACTIVE boolean, - GROUP_ID varchar(36) not null, - IP_MASK varchar(200), - CHANGE_PASSWORD_AT_LOGON boolean, - -- - primary key (ID), - constraint IDX_SEC_USER_UNIQ_LOGIN unique (LOGIN_LC, DELETE_TS), - constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_ROLE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - USER_ID varchar(36), - ROLE_ID varchar(36), - -- - primary key (ID), - constraint SEC_USER_ROLE_USER foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID), - constraint IDX_SEC_USER_ROLE_UNIQ_ROLE unique (USER_ID, ROLE_ID, DELETE_TS) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PERMISSION ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - PERMISSION_TYPE integer, - TARGET varchar(100), - VALUE integer, - ROLE_ID varchar(36), - -- - primary key (ID), - constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID), - constraint IDX_SEC_PERMISSION_UNIQUE unique (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_CONSTRAINT ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CODE varchar(255), - CHECK_TYPE varchar(50) default 'db', - OPERATION_TYPE varchar(50) default 'read', - ENTITY_NAME varchar(255) not null, - JOIN_CLAUSE varchar(500), - WHERE_CLAUSE varchar(1000), - GROOVY_SCRIPT longvarchar, - FILTER_XML longvarchar, - IS_ACTIVE boolean default true, - GROUP_ID varchar(36), - -- - primary key (ID), - constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOCALIZED_CONSTRAINT_MSG ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - ENTITY_NAME varchar(255) not null, - OPERATION_TYPE varchar(50) not null, - VALUES_ longvarchar, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE - on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_ATTR ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(50), - STR_VALUE varchar(1000), - DATATYPE varchar(20), - GROUP_ID varchar(36), - -- - primary key (ID), - constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SETTING ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - USER_ID varchar(36), - CLIENT_TYPE char(1), - NAME varchar(255), - VALUE longvarchar, - -- - primary key (ID), - constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SUBSTITUTION ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - USER_ID varchar(36) not null, - SUBSTITUTED_USER_ID varchar(36) not null, - START_DATE timestamp, - END_DATE timestamp, - -- - primary key (ID), - constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) - references SEC_USER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ENTITY ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - NAME varchar(100), - AUTO boolean, - MANUAL boolean, - -- - primary key (ID), - constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ATTR ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ENTITY_ID varchar(36), - NAME varchar(50), - -- - primary key (ID), - constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), - constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ENTITY_LOG ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - EVENT_TS timestamp, - USER_ID varchar(36), - CHANGE_TYPE char(1), - ENTITY varchar(100), - ENTITY_ID varchar(36), - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - CHANGES longvarchar, - -- - primary key (ID), - constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_FILTER ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - CODE varchar(200), - XML longvarchar, - USER_ID varchar(36), - -- - primary key (ID), - constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FOLDER ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - FOLDER_TYPE char(1), - PARENT_ID varchar(36), - NAME varchar(100), - TAB_NAME varchar(100), - SORT_ORDER integer, - -- - primary key (ID), - constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_APP_FOLDER ( - FOLDER_ID varchar(36) not null, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - VISIBILITY_SCRIPT longvarchar, - QUANTITY_SCRIPT longvarchar, - APPLY_DEFAULT boolean, - -- - primary key (FOLDER_ID), - constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PRESENTATION ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - XML varchar(7000), - USER_ID varchar(36), - IS_AUTO_SAVE boolean, - -- - primary key (ID), - constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SEARCH_FOLDER ( - FOLDER_ID varchar(36) not null, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - USER_ID varchar(36), - PRESENTATION_ID varchar(36), - APPLY_DEFAULT boolean, - IS_SET boolean, - ENTITY_TYPE varchar(50), - -- - primary key (FOLDER_ID), - constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), - constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) - references SEC_PRESENTATION(ID) - on delete set null -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FTS_QUEUE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ENTITY_ID varchar(36), - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - ENTITY_NAME varchar(200), - CHANGE_TYPE char(1), - SOURCE_HOST varchar(255), - INDEXING_HOST varchar(255), - FAKE boolean, - -- - primary key (ID) -)^ - -create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ - --------------------------------------------------------------------------------------------------------------- - -create table SEC_SCREEN_HISTORY ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - USER_ID varchar(36), - CAPTION varchar(255), - URL varchar(4000), - ENTITY_ID varchar(36), - SUBSTITUTED_USER_ID varchar(36), - -- - primary key (ID), - constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), - constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) -)^ - -create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SENDING_MESSAGE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - ADDRESS_TO longvarchar, - ADDRESS_FROM varchar(100), - CAPTION varchar(500), - EMAIL_HEADERS varchar(500), - CONTENT_TEXT longvarchar, - CONTENT_TEXT_FILE_ID varchar(36), - DEADLINE timestamp, - STATUS integer, - DATE_SENT timestamp, - ATTEMPTS_COUNT integer, - ATTEMPTS_MADE integer, - ATTACHMENTS_NAME longvarchar, - -- - primary key (ID) -)^ - -alter table SYS_SENDING_MESSAGE add constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID)^ - -create table SYS_SENDING_ATTACHMENT ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - MESSAGE_ID varchar(36), - CONTENT longvarbinary, - CONTENT_FILE_ID varchar(36), - CONTENT_ID varchar(50), - NAME varchar(500), - DISPOSITION varchar(50), - TEXT_ENCODING varchar(50), - - -- - primary key (ID) -)^ - -alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID)^ -alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID)^ - -CREATE INDEX SYS_SENDING_ATTACHMENT_MESSAGE_IDX - ON SYS_SENDING_ATTACHMENT(MESSAGE_ID )^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_SNAPSHOT ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ENTITY_META_CLASS varchar(50), - ENTITY_ID varchar(36), - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - AUTHOR_ID varchar(36) not null, - VIEW_XML longvarchar, - SNAPSHOT_XML longvarchar, - SNAPSHOT_DATE timestamp, - -- - primary key (ID), - constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) -)^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_CATEGORY( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - SPECIAL varchar(50), - ENTITY_TYPE varchar(100) not null, - IS_DEFAULT boolean, - DISCRIMINATOR integer, - LOCALE_NAMES varchar(1000), - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS)^ - -create table SYS_CATEGORY_ATTR( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CATEGORY_ENTITY_TYPE varchar(4000), - NAME varchar(255), - CODE varchar(100) not null, - CATEGORY_ID varchar(36) not null, - ENTITY_CLASS varchar(500), - DATA_TYPE varchar(200), - DEFAULT_STRING varchar(4000), - DEFAULT_INT integer, - DEFAULT_DOUBLE numeric, - DEFAULT_DATE date, - DEFAULT_DATE_IS_CURRENT boolean, - DEFAULT_BOOLEAN boolean, - DEFAULT_ENTITY_VALUE varchar(36), - DEFAULT_STR_ENTITY_VALUE varchar(255), - DEFAULT_INT_ENTITY_VALUE integer, - DEFAULT_LONG_ENTITY_VALUE bigint, - ENUMERATION varchar(500), - ORDER_NO integer, - SCREEN varchar(255), - REQUIRED boolean, - LOOKUP boolean, - TARGET_SCREENS varchar(4000), - WIDTH varchar(20), - ROWS_COUNT integer, - IS_COLLECTION boolean, - JOIN_CLAUSE varchar(4000), - WHERE_CLAUSE varchar(4000), - FILTER_XML longvarchar, - LOCALE_NAMES varchar(1000), - ENUMERATION_LOCALES varchar(5000), - -- - primary key (ID) -)^ - -create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE); - -alter table SYS_CATEGORY_ATTR add constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID)^ - -create table SYS_ATTR_VALUE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CATEGORY_ATTR_ID varchar(36) not null, - ENTITY_ID varchar(36), - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - STRING_VALUE varchar(4000), - INTEGER_VALUE integer, - DOUBLE_VALUE numeric, - DATE_VALUE date, - BOOLEAN_VALUE boolean, - ENTITY_VALUE varchar(36), - STRING_ENTITY_VALUE varchar(255), - INT_ENTITY_VALUE integer, - LONG_ENTITY_VALUE bigint, - PARENT_ID varchar(36), - CODE varchar(100), - -- - primary key (ID) -)^ - -alter table SYS_ATTR_VALUE add constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID)^ - -alter table SYS_ATTR_VALUE add constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID)^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_QUERY_RESULT ( - ID identity not null, - SESSION_ID varchar(36) not null, - QUERY_KEY integer not null, - ENTITY_ID varchar(36), - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, -)^ - --------------------------------------------------------------------------------------------------------------- - -create table SYS_JMX_INSTANCE ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NODE_NAME varchar(255), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_REMEMBER_ME ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - -- - USER_ID varchar(36) not null, - TOKEN varchar(32) not null, - -- - primary key (ID), - constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_REST_API_TOKEN ( - ID varchar(36) not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ACCESS_TOKEN_VALUE varchar(255), - ACCESS_TOKEN_BYTES longvarbinary, - AUTHENTICATION_KEY varchar(255), - AUTHENTICATION_BYTES longvarbinary, - EXPIRY timestamp, - USER_LOGIN varchar(50), - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_LOG ( - ID varchar(36) not null, - VERSION integer not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - SESSION_ID varchar(36) not null, - SUBSTITUTED_USER_ID varchar(36), - USER_ID varchar(36) not null, - USER_DATA longvarchar, - LAST_ACTION integer not null, - CLIENT_INFO varchar(512), - ADDRESS varchar(255), - STARTED_TS timestamp, - FINISHED_TS timestamp, - CLIENT_TYPE varchar(10), - SERVER_ID varchar(128), - -- - primary key (ID) -)^ - -alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_USER foreign key (USER_ID) references SEC_USER(ID)^ -create index IDX_SEC_SESSION_LOG_USER on SEC_SESSION_LOG (USER_ID)^ -alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID)^ -create index IDX_SEC_SESSION_LOG_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ - - ------------------------------------------------------------------------------------------------------------- - -create function NEWID() returns varchar(36) - return uuid(uuid()); - ------------------------------------------------------------------------------------------------------------- - -insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) -values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', current_timestamp, 0, 'Company', null)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('60885987-1b61-4247-94c7-dff348347f93', current_timestamp, 0, 'admin', 'admin', -'cc2229d1b8a052423d9e1c9ef0113b850086586a', -'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('a405db59-e674-4f63-8afe-269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, -'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ - -insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) -values ('0c018061-b26f-4de2-a5be-dff348347f93', current_timestamp, 0, 'Administrators', 10)^ - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', current_timestamp, 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ - -INSERT INTO sec_filter (id,create_ts,created_by,version,update_ts,updated_by,delete_ts,deleted_by,component,name,xml,user_id) VALUES ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', -' - - - ur.role.id = :component$genericFilter.UrMxpkfMGn32565 - NULL - - -', -'60885987-1b61-4247-94c7-dff348347f93')^ +------------------------------------------------------------------------------------------------------------ +-- table for selecting sequence values in HSQL +create table DUAL (ID integer)^ +insert into DUAL (ID) values (0)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SERVER ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(255), + IS_RUNNING boolean, + DATA longvarchar, + -- + primary key (ID), + constraint IDX_SYS_SERVER_UNIQ_NAME unique (NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_CONFIG ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(255), + VALUE longvarchar, + -- + primary key (ID), + constraint IDX_SYS_CONFIG_UNIQ_NAME unique (NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FILE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(500) not null, + EXT varchar(20), + FILE_SIZE bigint, + CREATE_DATE timestamp, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_LOCK_CONFIG ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + NAME varchar(100), + TIMEOUT_SEC integer, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_STATISTICS ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(50), + INSTANCE_COUNT bigint, + FETCH_UI integer, + MAX_FETCH_UI integer, + LAZY_COLLECTION_THRESHOLD integer, + LOOKUP_SCREEN_THRESHOLD integer, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_TASK ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + BEAN_NAME varchar(50), + METHOD_NAME varchar(50), + METHOD_PARAMS varchar(1000), + DEFINED_BY varchar(1) default 'B', + CLASS_NAME varchar(500), + SCRIPT_NAME varchar(500), + USER_NAME varchar(50), + IS_SINGLETON boolean, + IS_ACTIVE boolean, + PERIOD integer, + TIMEOUT integer, + START_DATE timestamp, + TIME_FRAME integer, + START_DELAY integer, + PERMITTED_SERVERS varchar(4096), + LOG_START boolean, + LOG_FINISH boolean, + LAST_START_TIME timestamp, + LAST_START_SERVER varchar(512), + DESCRIPTION varchar(1000), + CRON varchar(100), + SCHEDULING_TYPE varchar(1) default 'P', + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_EXECUTION ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + TASK_ID varchar(36), + SERVER varchar(512), + START_TIME timestamp, + FINISH_TIME timestamp, + RESULT longvarchar, + -- + primary key (ID), + constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) +)^ + +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ROLE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + LOC_NAME varchar(255), + DESCRIPTION varchar(1000), + IS_DEFAULT_ROLE boolean, + ROLE_TYPE integer, + -- + primary key (ID) +)^ + +-- Trigger example, HSQL throws NPE on constraint violation +--create trigger SEC_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_ROLE +--referencing NEW as newrow OLD AS oldrow +--for each row begin atomic +-- if newrow.DELETE_TS != oldrow.DELETE_TS then +-- if newrow.DELETE_TS is null then +-- set newrow.DELETE_TS_NN = '1000-01-01 00:00:00.000'; +-- else +-- set newrow.DELETE_TS_NN = newrow.DELETE_TS; +-- end if; +-- end if; +--end;^ + +alter table SEC_ROLE add constraint IDX_SEC_ROLE_UNIQ_NAME unique (NAME, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + PARENT_ID varchar(36), + -- + primary key (ID), + constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +alter table SEC_GROUP add constraint IDX_SEC_GROUP_UNIQ_NAME unique (NAME, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP_HIERARCHY ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + GROUP_ID varchar(36), + PARENT_ID varchar(36), + HIERARCHY_LEVEL integer, + -- + primary key (ID), + constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), + constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + LOGIN varchar(50) not null, + LOGIN_LC varchar(50) not null, + PASSWORD varchar(255), + NAME varchar(255), + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + MIDDLE_NAME varchar(255), + POSITION_ varchar(255), + EMAIL varchar(100), + LANGUAGE_ varchar(20), + TIME_ZONE varchar(50), + TIME_ZONE_AUTO boolean, + ACTIVE boolean, + GROUP_ID varchar(36) not null, + IP_MASK varchar(200), + CHANGE_PASSWORD_AT_LOGON boolean, + -- + primary key (ID), + constraint IDX_SEC_USER_UNIQ_LOGIN unique (LOGIN_LC, DELETE_TS), + constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_ROLE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + USER_ID varchar(36), + ROLE_ID varchar(36), + -- + primary key (ID), + constraint SEC_USER_ROLE_USER foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID), + constraint IDX_SEC_USER_ROLE_UNIQ_ROLE unique (USER_ID, ROLE_ID, DELETE_TS) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PERMISSION ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + PERMISSION_TYPE integer, + TARGET varchar(100), + VALUE integer, + ROLE_ID varchar(36), + -- + primary key (ID), + constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID), + constraint IDX_SEC_PERMISSION_UNIQUE unique (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_CONSTRAINT ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CODE varchar(255), + CHECK_TYPE varchar(50) default 'db', + OPERATION_TYPE varchar(50) default 'read', + ENTITY_NAME varchar(255) not null, + JOIN_CLAUSE varchar(500), + WHERE_CLAUSE varchar(1000), + GROOVY_SCRIPT longvarchar, + FILTER_XML longvarchar, + IS_ACTIVE boolean default true, + GROUP_ID varchar(36), + -- + primary key (ID), + constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOCALIZED_CONSTRAINT_MSG ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + ENTITY_NAME varchar(255) not null, + OPERATION_TYPE varchar(50) not null, + VALUES_ longvarchar, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE + on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SESSION_ATTR ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(50), + STR_VALUE varchar(1000), + DATATYPE varchar(20), + GROUP_ID varchar(36), + -- + primary key (ID), + constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SETTING ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + USER_ID varchar(36), + CLIENT_TYPE char(1), + NAME varchar(255), + VALUE longvarchar, + -- + primary key (ID), + constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SUBSTITUTION ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + USER_ID varchar(36) not null, + SUBSTITUTED_USER_ID varchar(36) not null, + START_DATE timestamp, + END_DATE timestamp, + -- + primary key (ID), + constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) + references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ENTITY ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + NAME varchar(100), + AUTO boolean, + MANUAL boolean, + -- + primary key (ID), + constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ATTR ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ENTITY_ID varchar(36), + NAME varchar(50), + -- + primary key (ID), + constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), + constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ENTITY_LOG ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + EVENT_TS timestamp, + USER_ID varchar(36), + CHANGE_TYPE char(1), + ENTITY varchar(100), + ENTITY_ID varchar(36), + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + CHANGES longvarchar, + -- + primary key (ID), + constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_FILTER ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + CODE varchar(200), + XML longvarchar, + USER_ID varchar(36), + -- + primary key (ID), + constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FOLDER ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + FOLDER_TYPE char(1), + PARENT_ID varchar(36), + NAME varchar(100), + TAB_NAME varchar(100), + SORT_ORDER integer, + -- + primary key (ID), + constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_APP_FOLDER ( + FOLDER_ID varchar(36) not null, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + VISIBILITY_SCRIPT longvarchar, + QUANTITY_SCRIPT longvarchar, + APPLY_DEFAULT boolean, + -- + primary key (FOLDER_ID), + constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PRESENTATION ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + XML varchar(7000), + USER_ID varchar(36), + IS_AUTO_SAVE boolean, + -- + primary key (ID), + constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SEARCH_FOLDER ( + FOLDER_ID varchar(36) not null, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + USER_ID varchar(36), + PRESENTATION_ID varchar(36), + APPLY_DEFAULT boolean, + IS_SET boolean, + ENTITY_TYPE varchar(50), + -- + primary key (FOLDER_ID), + constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), + constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) + references SEC_PRESENTATION(ID) + on delete set null +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FTS_QUEUE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ENTITY_ID varchar(36), + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + ENTITY_NAME varchar(200), + CHANGE_TYPE char(1), + SOURCE_HOST varchar(255), + INDEXING_HOST varchar(255), + FAKE boolean, + -- + primary key (ID) +)^ + +create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SEC_SCREEN_HISTORY ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + USER_ID varchar(36), + CAPTION varchar(255), + URL varchar(4000), + ENTITY_ID varchar(36), + SUBSTITUTED_USER_ID varchar(36), + -- + primary key (ID), + constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), + constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) +)^ + +create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_MESSAGE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + ADDRESS_TO longvarchar, + ADDRESS_FROM varchar(100), + CAPTION varchar(500), + EMAIL_HEADERS varchar(500), + CONTENT_TEXT longvarchar, + CONTENT_TEXT_FILE_ID varchar(36), + DEADLINE timestamp, + STATUS integer, + DATE_SENT timestamp, + ATTEMPTS_COUNT integer, + ATTEMPTS_MADE integer, + ATTACHMENTS_NAME longvarchar, + -- + primary key (ID) +)^ + +alter table SYS_SENDING_MESSAGE add constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID)^ + +create table SYS_SENDING_ATTACHMENT ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + MESSAGE_ID varchar(36), + CONTENT longvarbinary, + CONTENT_FILE_ID varchar(36), + CONTENT_ID varchar(50), + NAME varchar(500), + DISPOSITION varchar(50), + TEXT_ENCODING varchar(50), + + -- + primary key (ID) +)^ + +alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID)^ +alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID)^ + +CREATE INDEX SYS_SENDING_ATTACHMENT_MESSAGE_IDX + ON SYS_SENDING_ATTACHMENT(MESSAGE_ID )^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_SNAPSHOT ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ENTITY_META_CLASS varchar(50), + ENTITY_ID varchar(36), + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + AUTHOR_ID varchar(36) not null, + VIEW_XML longvarchar, + SNAPSHOT_XML longvarchar, + SNAPSHOT_DATE timestamp, + -- + primary key (ID), + constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_CATEGORY( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + SPECIAL varchar(50), + ENTITY_TYPE varchar(100) not null, + IS_DEFAULT boolean, + DISCRIMINATOR integer, + LOCALE_NAMES varchar(1000), + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS)^ + +create table SYS_CATEGORY_ATTR( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CATEGORY_ENTITY_TYPE varchar(4000), + NAME varchar(255), + CODE varchar(100) not null, + CATEGORY_ID varchar(36) not null, + ENTITY_CLASS varchar(500), + DATA_TYPE varchar(200), + DEFAULT_STRING varchar(4000), + DEFAULT_INT integer, + DEFAULT_DOUBLE numeric, + DEFAULT_DATE date, + DEFAULT_DATE_IS_CURRENT boolean, + DEFAULT_BOOLEAN boolean, + DEFAULT_ENTITY_VALUE varchar(36), + DEFAULT_STR_ENTITY_VALUE varchar(255), + DEFAULT_INT_ENTITY_VALUE integer, + DEFAULT_LONG_ENTITY_VALUE bigint, + ENUMERATION varchar(500), + ORDER_NO integer, + SCREEN varchar(255), + REQUIRED boolean, + LOOKUP boolean, + TARGET_SCREENS varchar(4000), + WIDTH varchar(20), + ROWS_COUNT integer, + IS_COLLECTION boolean, + JOIN_CLAUSE varchar(4000), + WHERE_CLAUSE varchar(4000), + FILTER_XML longvarchar, + LOCALE_NAMES varchar(1000), + ENUMERATION_LOCALES varchar(5000), + -- + primary key (ID) +)^ + +create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE); + +alter table SYS_CATEGORY_ATTR add constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID)^ + +create table SYS_ATTR_VALUE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CATEGORY_ATTR_ID varchar(36) not null, + ENTITY_ID varchar(36), + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + STRING_VALUE varchar(4000), + INTEGER_VALUE integer, + DOUBLE_VALUE numeric, + DATE_VALUE date, + BOOLEAN_VALUE boolean, + ENTITY_VALUE varchar(36), + STRING_ENTITY_VALUE varchar(255), + INT_ENTITY_VALUE integer, + LONG_ENTITY_VALUE bigint, + PARENT_ID varchar(36), + CODE varchar(100), + -- + primary key (ID) +)^ + +alter table SYS_ATTR_VALUE add constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID)^ + +alter table SYS_ATTR_VALUE add constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID)^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_QUERY_RESULT ( + ID identity not null, + SESSION_ID varchar(36) not null, + QUERY_KEY integer not null, + ENTITY_ID varchar(36), + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, +)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SYS_JMX_INSTANCE ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NODE_NAME varchar(255), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_REMEMBER_ME ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + -- + USER_ID varchar(36) not null, + TOKEN varchar(32) not null, + -- + primary key (ID), + constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_REST_API_TOKEN ( + ID varchar(36) not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ACCESS_TOKEN_VALUE varchar(255), + ACCESS_TOKEN_BYTES longvarbinary, + AUTHENTICATION_KEY varchar(255), + AUTHENTICATION_BYTES longvarbinary, + EXPIRY timestamp, + USER_LOGIN varchar(50), + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SESSION_LOG ( + ID varchar(36) not null, + VERSION integer not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + SESSION_ID varchar(36) not null, + SUBSTITUTED_USER_ID varchar(36), + USER_ID varchar(36) not null, + USER_DATA longvarchar, + LAST_ACTION integer not null, + CLIENT_INFO varchar(512), + ADDRESS varchar(255), + STARTED_TS timestamp, + FINISHED_TS timestamp, + CLIENT_TYPE varchar(10), + SERVER_ID varchar(128), + -- + primary key (ID) +)^ + +alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_USER foreign key (USER_ID) references SEC_USER(ID)^ +create index IDX_SEC_SESSION_LOG_USER on SEC_SESSION_LOG (USER_ID)^ +alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID)^ +create index IDX_SEC_SESSION_LOG_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ + + +------------------------------------------------------------------------------------------------------------ + +create function NEWID() returns varchar(36) + return uuid(uuid()); + +------------------------------------------------------------------------------------------------------------ + +insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) +values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', current_timestamp, 0, 'Company', null)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('60885987-1b61-4247-94c7-dff348347f93', current_timestamp, 0, 'admin', 'admin', +'cc2229d1b8a052423d9e1c9ef0113b850086586a', +'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('a405db59-e674-4f63-8afe-269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, +'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ + +insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) +values ('0c018061-b26f-4de2-a5be-dff348347f93', current_timestamp, 0, 'Administrators', 10)^ + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', current_timestamp, 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ + +INSERT INTO sec_filter (id,create_ts,created_by,version,update_ts,updated_by,delete_ts,deleted_by,component,name,xml,user_id) VALUES ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', +' + + + ur.role.id = :component$genericFilter.UrMxpkfMGn32565 + NULL + + +', +'60885987-1b61-4247-94c7-dff348347f93')^ diff --git a/modules/core/db/init/hsql/create-sample-data.sql b/modules/core/db/init/hsql/create-sample-data.sql index 9ad27b7f70..c4c55fad6e 100644 --- a/modules/core/db/init/hsql/create-sample-data.sql +++ b/modules/core/db/init/hsql/create-sample-data.sql @@ -1,43 +1,43 @@ -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID) -values ('40288137-1ef4-11c8-011e-f41247370001', current_timestamp, 0, 'abramov', 'abramov', '402881371ef411c8011ef411c8c50000', 'Dmitry Abramov', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93'); - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID) -values ('01e37691-1a9b-11de-b900-da881aea47a6', current_timestamp, 0, 'krivopustov', 'krivopustov', null, 'Konstantin Krivopustov', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93'); - -insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, TYPE) -values ('40288137-1ef4-11c8-011e-f416e4150005', current_timestamp, 0, 'Users', 10); - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('40288137-1ef4-11c8-011e-f41aaa740006', current_timestamp, 0, '40288137-1ef4-11c8-011e-f41247370001', '40288137-1ef4-11c8-011e-f416e4150005'); - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('40288137-1ef4-11c8-011e-f41aaa740007', current_timestamp, 0, '40288137-1ef4-11c8-011e-f41247370001', '0c018061-b26f-4de2-a5be-dff348347f93'); - - --- AppFolders - -insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) -values ('2ce5dc9a-e628-11de-849e-4f2ee1f9724a', current_timestamp, 0, 'A', null, 'Haulmont employees'); - -insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) -values ('2ce5dc9a-e628-11de-849e-4f2ee1f9724a', '[sec$User.browse].genericFilter', 'u.email like :component$genericFilter.email90138@haulmont.comu.group.id = :component$genericFilter.group461660fa2b1a5-1d68-4d69-9fbd-dff348347f93', 'cuba/test/appfolders/IAmAdmin.groovy', 'cuba/test/appfolders/AppFolder1Qty.groovy'); - ---insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) ---values ('5a5ac474-e628-11de-b314-ab16b614416f', current_timestamp, 0, 'A', null, 'App Folder 2'); --- ---insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) ---values ('5a5ac474-e628-11de-b314-ab16b614416f', null, null, null, null); --- ---insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) ---values ('6e8c5a0c-e628-11de-8e1e-37fa218351d5', current_timestamp, 0, 'A', '2ce5dc9a-e628-11de-849e-4f2ee1f9724a', 'App Folder 3'); --- ---insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) ---values ('6e8c5a0c-e628-11de-8e1e-37fa218351d5', null, null, null, null); - --- SearchFolders - -insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) -values ('6904a2ac-e62c-11de-8571-c79ad48b2687', current_timestamp, 0, 'S', null, 'Search Folder 1'); - -insert into SEC_SEARCH_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, USER_ID) -values ('6904a2ac-e62c-11de-8571-c79ad48b2687', null, null, '60885987-1b61-4247-94c7-dff348347f93'); +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID) +values ('40288137-1ef4-11c8-011e-f41247370001', current_timestamp, 0, 'abramov', 'abramov', '402881371ef411c8011ef411c8c50000', 'Dmitry Abramov', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93'); + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID) +values ('01e37691-1a9b-11de-b900-da881aea47a6', current_timestamp, 0, 'krivopustov', 'krivopustov', null, 'Konstantin Krivopustov', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93'); + +insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, TYPE) +values ('40288137-1ef4-11c8-011e-f416e4150005', current_timestamp, 0, 'Users', 10); + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('40288137-1ef4-11c8-011e-f41aaa740006', current_timestamp, 0, '40288137-1ef4-11c8-011e-f41247370001', '40288137-1ef4-11c8-011e-f416e4150005'); + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('40288137-1ef4-11c8-011e-f41aaa740007', current_timestamp, 0, '40288137-1ef4-11c8-011e-f41247370001', '0c018061-b26f-4de2-a5be-dff348347f93'); + + +-- AppFolders + +insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) +values ('2ce5dc9a-e628-11de-849e-4f2ee1f9724a', current_timestamp, 0, 'A', null, 'Haulmont employees'); + +insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) +values ('2ce5dc9a-e628-11de-849e-4f2ee1f9724a', '[sec$User.browse].genericFilter', 'u.email like :component$genericFilter.email90138@haulmont.comu.group.id = :component$genericFilter.group461660fa2b1a5-1d68-4d69-9fbd-dff348347f93', 'cuba/test/appfolders/IAmAdmin.groovy', 'cuba/test/appfolders/AppFolder1Qty.groovy'); + +--insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) +--values ('5a5ac474-e628-11de-b314-ab16b614416f', current_timestamp, 0, 'A', null, 'App Folder 2'); +-- +--insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) +--values ('5a5ac474-e628-11de-b314-ab16b614416f', null, null, null, null); +-- +--insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) +--values ('6e8c5a0c-e628-11de-8e1e-37fa218351d5', current_timestamp, 0, 'A', '2ce5dc9a-e628-11de-849e-4f2ee1f9724a', 'App Folder 3'); +-- +--insert into SYS_APP_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, VISIBILITY_SCRIPT, QUANTITY_SCRIPT) +--values ('6e8c5a0c-e628-11de-8e1e-37fa218351d5', null, null, null, null); + +-- SearchFolders + +insert into SYS_FOLDER (ID, CREATE_TS, VERSION, TYPE, PARENT_ID, NAME) +values ('6904a2ac-e62c-11de-8571-c79ad48b2687', current_timestamp, 0, 'S', null, 'Search Folder 1'); + +insert into SEC_SEARCH_FOLDER (FOLDER_ID, FILTER_COMPONENT, FILTER_XML, USER_ID) +values ('6904a2ac-e62c-11de-8571-c79ad48b2687', null, null, '60885987-1b61-4247-94c7-dff348347f93'); diff --git a/modules/core/db/init/mssql/create-db.sql b/modules/core/db/init/mssql/create-db.sql index 33eb88d1aa..57ad03bd76 100644 --- a/modules/core/db/init/mssql/create-db.sql +++ b/modules/core/db/init/mssql/create-db.sql @@ -1,969 +1,969 @@ - -create table SYS_SERVER ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - UPDATE_TS datetime, - UPDATED_BY varchar(50), - NAME varchar(255), - IS_RUNNING tinyint, - DATA varchar(max), - primary key nonclustered (ID) -)^ - -create unique clustered index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_CONFIG ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - -- - NAME varchar(255), - VALUE varchar(max), - -- - primary key nonclustered (ID) -)^ - -create unique clustered index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FILE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NAME varchar(500) not null, - EXT varchar(20), - FILE_SIZE bigint, - CREATE_DATE datetime, - -- - primary key nonclustered (ID) -)^ - -create clustered index IDX_SYS_FILE_CREATE_DATE on SYS_FILE (CREATE_DATE)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_LOCK_CONFIG ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - NAME varchar(100), - TIMEOUT_SEC integer, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_STATISTICS ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - UPDATE_TS datetime, - UPDATED_BY varchar(50), - -- - NAME varchar(50), - INSTANCE_COUNT bigint, - FETCH_UI integer, - MAX_FETCH_UI integer, - LAZY_COLLECTION_THRESHOLD integer, - LOOKUP_SCREEN_THRESHOLD integer, - -- - primary key nonclustered (ID) -)^ - -create unique clustered index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_TASK ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - DEFINED_BY varchar(1) default 'B', - CLASS_NAME varchar(500), - SCRIPT_NAME varchar(500), - BEAN_NAME varchar(50), - METHOD_NAME varchar(50), - METHOD_PARAMS varchar(1000), - USER_NAME varchar(50), - IS_SINGLETON tinyint, - IS_ACTIVE tinyint, - PERIOD integer, - TIMEOUT integer, - START_DATE datetime, - TIME_FRAME integer, - START_DELAY integer, - PERMITTED_SERVERS varchar(4096), - LOG_START tinyint, - LOG_FINISH tinyint, - LAST_START_TIME datetime, - LAST_START_SERVER varchar(512), - DESCRIPTION varchar(1000), - CRON varchar(100), - SCHEDULING_TYPE varchar(1) default 'P', - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_EXECUTION ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - TASK_ID uniqueidentifier, - SERVER varchar(512), - START_TIME datetime, - FINISH_TIME datetime, - RESULT varchar(max), - -- - primary key nonclustered (ID), - constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) -)^ - -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ - -create clustered index IDX_SYS_SCHEDULED_EXECUTION_CREATE_TS on SYS_SCHEDULED_EXECUTION (CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ROLE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - LOC_NAME varchar(255), - DESCRIPTION varchar(1000), - IS_DEFAULT_ROLE tinyint, - ROLE_TYPE integer, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - PARENT_ID uniqueidentifier, - -- - primary key (ID), - constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - -create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP_HIERARCHY ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - GROUP_ID uniqueidentifier, - PARENT_ID uniqueidentifier, - HIERARCHY_LEVEL integer, - -- - primary key nonclustered (ID), - constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), - constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - -create clustered index IDX_SEC_GROUP_HIERARCHY_GROUP_ID on SEC_GROUP_HIERARCHY (GROUP_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - LOGIN varchar(50) not null, - LOGIN_LC varchar(50) not null, - PASSWORD varchar(255), - NAME varchar(255), - FIRST_NAME varchar(255), - LAST_NAME varchar(255), - MIDDLE_NAME varchar(255), - POSITION_ varchar(255), - EMAIL varchar(100), - LANGUAGE_ varchar(20), - TIME_ZONE varchar(50), - TIME_ZONE_AUTO tinyint, - ACTIVE tinyint, - GROUP_ID uniqueidentifier not null, - IP_MASK varchar(200), - CHANGE_PASSWORD_AT_LOGON tinyint, - -- - primary key nonclustered (ID), - constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS)^ - -create clustered index IDX_SEC_USER_LOGIN on SEC_USER (LOGIN_LC)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_ROLE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - USER_ID uniqueidentifier, - ROLE_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID, DELETE_TS)^ - -create clustered index IDX_SEC_USER_ROLE_USER on SEC_USER_ROLE (USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PERMISSION ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - PERMISSION_TYPE integer, - TARGET varchar(100), - VALUE integer, - ROLE_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS)^ - -create clustered index IDX_SEC_PERMISSION_ROLE on SEC_PERMISSION (ROLE_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_CONSTRAINT ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - CODE varchar(255), - CHECK_TYPE varchar(50) default 'db', - OPERATION_TYPE varchar(50) default 'read', - ENTITY_NAME varchar(255) not null, - JOIN_CLAUSE varchar(500), - WHERE_CLAUSE varchar(1000), - GROOVY_SCRIPT varchar(max), - FILTER_XML varchar(max), - IS_ACTIVE tinyint default 1, - GROUP_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create clustered index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOCALIZED_CONSTRAINT_MSG ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - ENTITY_NAME varchar(255) not null, - OPERATION_TYPE varchar(50) not null, - VALUES_ varchar(max), - -- - primary key (ID) -)^ - -create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE - on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_ATTR ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NAME varchar(50), - STR_VALUE varchar(1000), - DATATYPE varchar(20), - GROUP_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create clustered index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SETTING ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - USER_ID uniqueidentifier, - CLIENT_TYPE char(1), - NAME varchar(255), - VALUE varchar(max), - -- - primary key nonclustered (ID), - constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) -)^ - -create clustered index IDX_SEC_USER_SETTING_CREATE_TS on SEC_USER_SETTING (CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SUBSTITUTION ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - USER_ID uniqueidentifier not null, - SUBSTITUTED_USER_ID uniqueidentifier not null, - START_DATE datetime, - END_DATE datetime, - -- - primary key nonclustered (ID), - constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) -)^ - -create clustered index IDX_SEC_USER_SUBSTITUTION_USER on SEC_USER_SUBSTITUTION (USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ENTITY ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - NAME varchar(100), - AUTO tinyint, - MANUAL tinyint, - -- - primary key (ID), - constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ATTR ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - ENTITY_ID uniqueidentifier, - NAME varchar(50), - -- - primary key nonclustered (ID), - constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), - constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) -)^ - -create clustered index IDX_SEC_LOGGED_ATTR_ENTITY on SEC_LOGGED_ATTR (ENTITY_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ENTITY_LOG ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - EVENT_TS datetime, - USER_ID uniqueidentifier, - CHANGE_TYPE char(1), - ENTITY varchar(100), - ENTITY_ID uniqueidentifier, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - CHANGES varchar(max), - -- - primary key nonclustered (ID), - constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create clustered index IDX_SEC_ENTITY_LOG_EVENT_TS on SEC_ENTITY_LOG (EVENT_TS)^ - -create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_FILTER ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - CODE varchar(200), - XML varchar(max), - USER_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create clustered index IDX_SEC_FILTER_COMPONENT_USER on SEC_FILTER (COMPONENT, USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FOLDER ( - ID uniqueidentifier, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - FOLDER_TYPE char(1), - PARENT_ID uniqueidentifier, - NAME varchar(100), - TAB_NAME varchar(100), - SORT_ORDER integer, - -- - primary key (ID), - constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_APP_FOLDER ( - FOLDER_ID uniqueidentifier, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - VISIBILITY_SCRIPT varchar(max), - QUANTITY_SCRIPT varchar(max), - APPLY_DEFAULT tinyint, - -- - primary key (FOLDER_ID), - constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PRESENTATION ( - ID uniqueidentifier, - CREATE_TS datetime, - CREATED_BY varchar(50), - UPDATE_TS datetime, - UPDATED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - XML varchar(7000), - USER_ID uniqueidentifier, - IS_AUTO_SAVE tinyint, - -- - primary key nonclustered (ID), - constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create clustered index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SEARCH_FOLDER ( - FOLDER_ID uniqueidentifier, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - USER_ID uniqueidentifier, - PRESENTATION_ID uniqueidentifier, - APPLY_DEFAULT tinyint, - IS_SET tinyint, - ENTITY_TYPE varchar(50), - -- - primary key (FOLDER_ID), - constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), - constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) - references SEC_PRESENTATION(ID) - on delete set null -)^ - -create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FTS_QUEUE ( - ID uniqueidentifier, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - ENTITY_ID uniqueidentifier, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - ENTITY_NAME varchar(200), - CHANGE_TYPE char(1), - SOURCE_HOST varchar(255), - INDEXING_HOST varchar(255), - FAKE tinyint, - -- - primary key nonclustered (ID) -)^ - -create clustered index IDX_SYS_FTS_QUEUE_CREATE_TS on SYS_FTS_QUEUE (CREATE_TS)^ - -create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SCREEN_HISTORY ( - ID uniqueidentifier, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - USER_ID uniqueidentifier, - CAPTION varchar(255), - URL varchar(max), - ENTITY_ID uniqueidentifier, - SUBSTITUTED_USER_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), - constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) -)^ - -create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ -create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ - -create clustered index IDX_SEC_SCREEN_HISTORY_CREATE_TS on SEC_SCREEN_HISTORY (CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SENDING_MESSAGE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - ADDRESS_TO varchar(max), - ADDRESS_FROM varchar(100), - CAPTION varchar(500), - EMAIL_HEADERS varchar(500), - CONTENT_TEXT varchar(max), - CONTENT_TEXT_FILE_ID uniqueidentifier, - DEADLINE datetime, - STATUS int, - DATE_SENT datetime, - ATTEMPTS_COUNT int, - ATTEMPTS_MADE int, - ATTACHMENTS_NAME varchar(max), - -- - primary key nonclustered (ID), - constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) -)^ - -create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ - -create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ - -create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ - -create clustered index IDX_SYS_SENDING_MESSAGE_CREATE_TS on SYS_SENDING_MESSAGE (CREATE_TS)^ - - ------------------------------------------------------------------------------------------------------------ - -create table SYS_SENDING_ATTACHMENT ( - ID uniqueidentifier, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - MESSAGE_ID uniqueidentifier, - CONTENT image, - CONTENT_FILE_ID uniqueidentifier, - CONTENT_ID varchar(50), - NAME varchar(500), - DISPOSITION varchar(50), - TEXT_ENCODING varchar(50), - - -- - primary key nonclustered (ID), - constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), - constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) -)^ - -create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ - -create clustered index IDX_SYS_SENDING_ATTACHMENT_CREATE_TS on SYS_SENDING_ATTACHMENT (CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_SNAPSHOT ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - ENTITY_META_CLASS varchar(50) not null, - ENTITY_ID uniqueidentifier, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - AUTHOR_ID uniqueidentifier not null, - VIEW_XML varchar(max) not null, - SNAPSHOT_XML varchar(max) not null, - SNAPSHOT_DATE datetime not null, - -- - primary key nonclustered (ID), - constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) -)^ - -create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ - -create clustered index IDX_SYS_ENTITY_SNAPSHOT_CREATE_TS on SYS_ENTITY_SNAPSHOT (CREATE_TS)^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_CATEGORY( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - SPECIAL varchar(50), - ENTITY_TYPE varchar(100) not null, - IS_DEFAULT tinyint, - DISCRIMINATOR integer, - LOCALE_NAMES varchar(1000), - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS)^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_CATEGORY_ATTR ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - CATEGORY_ENTITY_TYPE varchar(4000), - NAME varchar(255), - CODE varchar(100) not null, - CATEGORY_ID uniqueidentifier not null, - ENTITY_CLASS varchar(500), - DATA_TYPE varchar(200), - DEFAULT_STRING varchar(max), - DEFAULT_INT integer, - DEFAULT_DOUBLE numeric, - DEFAULT_DATE datetime, - DEFAULT_DATE_IS_CURRENT tinyint, - DEFAULT_BOOLEAN tinyint, - DEFAULT_ENTITY_VALUE uniqueidentifier, - DEFAULT_STR_ENTITY_VALUE varchar(255), - DEFAULT_INT_ENTITY_VALUE integer, - DEFAULT_LONG_ENTITY_VALUE bigint, - ENUMERATION varchar(500), - ORDER_NO integer, - SCREEN varchar(255), - REQUIRED tinyint, - LOOKUP tinyint, - TARGET_SCREENS varchar(4000), - WIDTH varchar(20), - ROWS_COUNT integer, - IS_COLLECTION tinyint, - JOIN_CLAUSE varchar(4000), - WHERE_CLAUSE varchar(4000), - FILTER_XML varchar(max), - LOCALE_NAMES varchar(1000), - ENUMERATION_LOCALES varchar(5000), - -- - primary key nonclustered (ID), - constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) -)^ - -create clustered index IDX_SYS_CATEGORY_ATTR_CATEGORY on SYS_CATEGORY_ATTR (CATEGORY_ID)^ -create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE, DELETE_TS); -------------------------------------------------------------------------------------------------------------- - -create table SYS_ATTR_VALUE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - CATEGORY_ATTR_ID uniqueidentifier not null, - ENTITY_ID uniqueidentifier, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - STRING_VALUE varchar(max), - INTEGER_VALUE integer, - DOUBLE_VALUE numeric, - DATE_VALUE datetime, - BOOLEAN_VALUE tinyint, - ENTITY_VALUE uniqueidentifier, - STRING_ENTITY_VALUE varchar(255), - INT_ENTITY_VALUE integer, - LONG_ENTITY_VALUE bigint, - CODE varchar(100), - PARENT_ID uniqueidentifier, - -- - primary key nonclustered (ID), - constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), - constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) -)^ - -create clustered index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE (ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ - --------------------------------------------------------------------------------------------------------------- - -create table SYS_JMX_INSTANCE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - NODE_NAME varchar(255), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) -)^ - --------------------------------------------------------------------------------------------------------------- - -create table SYS_QUERY_RESULT ( - ID bigint identity not null, - SESSION_ID uniqueidentifier not null, - QUERY_KEY integer not null, - ENTITY_ID uniqueidentifier, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - -- - primary key (ID) -)^ - -create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ - -create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ - ------------------------------------------------------------------------------------------------------------------- - -create table SEC_REMEMBER_ME ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - -- - USER_ID uniqueidentifier not null, - TOKEN varchar(32) not null, - -- - primary key (ID), - constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) -)^ -create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ -create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ - ------------------------------------------------------------------------------------------------------------------- - -create table SYS_REST_API_TOKEN ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - -- - ACCESS_TOKEN_VALUE varchar(255), - ACCESS_TOKEN_BYTES image, - AUTHENTICATION_KEY varchar(255), - AUTHENTICATION_BYTES image, - EXPIRY datetime, - USER_LOGIN varchar(50), - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_LOG ( - ID uniqueidentifier not null, - VERSION integer not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - SESSION_ID uniqueidentifier not null, - USER_ID uniqueidentifier not null, - SUBSTITUTED_USER_ID uniqueidentifier, - USER_DATA varchar(max), - LAST_ACTION integer not null, - CLIENT_INFO varchar(512), - CLIENT_TYPE varchar(10), - ADDRESS varchar(255), - STARTED_TS datetime, - FINISHED_TS datetime, - SERVER_ID varchar(128), - -- - primary key (ID), - constraint FK_SESSION_LOG_ENTRY_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SESSION_LOG_ENTRY_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SESSION_LOG_ENTRY_USER on SEC_SESSION_LOG (USER_ID)^ -create index IDX_SESSION_LOG_ENTRY_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ -create index IDX_SESSION_LOG_ENTRY_SESSION on SEC_SESSION_LOG (SESSION_ID)^ - ------------------------------------------------------------------------------------------------------------------- - -insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) -values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', current_timestamp, 0, 'Company', null)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('60885987-1b61-4247-94c7-dff348347f93', current_timestamp, 0, 'admin', 'admin', -'cc2229d1b8a052423d9e1c9ef0113b850086586a', -'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', 1)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('a405db59-e674-4f63-8afe-269dda788fe8', current_timestamp, 0, 'anonymous', 'anonymous', null, -'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', 1)^ - -insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) -values ('0c018061-b26f-4de2-a5be-dff348347f93', current_timestamp, 0, 'Administrators', 10)^ - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', current_timestamp, 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ - -insert into SEC_FILTER (ID,CREATE_TS,CREATED_BY,VERSION,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,COMPONENT,NAME,XML,USER_ID) -values ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', -' - - - ur.role.id = :component$genericFilter.UrMxpkfMGn32565 - NULL - - -', -'60885987-1b61-4247-94c7-dff348347f93')^ + +create table SYS_SERVER ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + UPDATE_TS datetime, + UPDATED_BY varchar(50), + NAME varchar(255), + IS_RUNNING tinyint, + DATA varchar(max), + primary key nonclustered (ID) +)^ + +create unique clustered index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_CONFIG ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + -- + NAME varchar(255), + VALUE varchar(max), + -- + primary key nonclustered (ID) +)^ + +create unique clustered index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FILE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NAME varchar(500) not null, + EXT varchar(20), + FILE_SIZE bigint, + CREATE_DATE datetime, + -- + primary key nonclustered (ID) +)^ + +create clustered index IDX_SYS_FILE_CREATE_DATE on SYS_FILE (CREATE_DATE)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_LOCK_CONFIG ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + NAME varchar(100), + TIMEOUT_SEC integer, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_STATISTICS ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + UPDATE_TS datetime, + UPDATED_BY varchar(50), + -- + NAME varchar(50), + INSTANCE_COUNT bigint, + FETCH_UI integer, + MAX_FETCH_UI integer, + LAZY_COLLECTION_THRESHOLD integer, + LOOKUP_SCREEN_THRESHOLD integer, + -- + primary key nonclustered (ID) +)^ + +create unique clustered index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_TASK ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + DEFINED_BY varchar(1) default 'B', + CLASS_NAME varchar(500), + SCRIPT_NAME varchar(500), + BEAN_NAME varchar(50), + METHOD_NAME varchar(50), + METHOD_PARAMS varchar(1000), + USER_NAME varchar(50), + IS_SINGLETON tinyint, + IS_ACTIVE tinyint, + PERIOD integer, + TIMEOUT integer, + START_DATE datetime, + TIME_FRAME integer, + START_DELAY integer, + PERMITTED_SERVERS varchar(4096), + LOG_START tinyint, + LOG_FINISH tinyint, + LAST_START_TIME datetime, + LAST_START_SERVER varchar(512), + DESCRIPTION varchar(1000), + CRON varchar(100), + SCHEDULING_TYPE varchar(1) default 'P', + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_EXECUTION ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + TASK_ID uniqueidentifier, + SERVER varchar(512), + START_TIME datetime, + FINISH_TIME datetime, + RESULT varchar(max), + -- + primary key nonclustered (ID), + constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) +)^ + +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ + +create clustered index IDX_SYS_SCHEDULED_EXECUTION_CREATE_TS on SYS_SCHEDULED_EXECUTION (CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ROLE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + LOC_NAME varchar(255), + DESCRIPTION varchar(1000), + IS_DEFAULT_ROLE tinyint, + ROLE_TYPE integer, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + PARENT_ID uniqueidentifier, + -- + primary key (ID), + constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP_HIERARCHY ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + GROUP_ID uniqueidentifier, + PARENT_ID uniqueidentifier, + HIERARCHY_LEVEL integer, + -- + primary key nonclustered (ID), + constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), + constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +create clustered index IDX_SEC_GROUP_HIERARCHY_GROUP_ID on SEC_GROUP_HIERARCHY (GROUP_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + LOGIN varchar(50) not null, + LOGIN_LC varchar(50) not null, + PASSWORD varchar(255), + NAME varchar(255), + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + MIDDLE_NAME varchar(255), + POSITION_ varchar(255), + EMAIL varchar(100), + LANGUAGE_ varchar(20), + TIME_ZONE varchar(50), + TIME_ZONE_AUTO tinyint, + ACTIVE tinyint, + GROUP_ID uniqueidentifier not null, + IP_MASK varchar(200), + CHANGE_PASSWORD_AT_LOGON tinyint, + -- + primary key nonclustered (ID), + constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS)^ + +create clustered index IDX_SEC_USER_LOGIN on SEC_USER (LOGIN_LC)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_ROLE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + USER_ID uniqueidentifier, + ROLE_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID, DELETE_TS)^ + +create clustered index IDX_SEC_USER_ROLE_USER on SEC_USER_ROLE (USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PERMISSION ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + PERMISSION_TYPE integer, + TARGET varchar(100), + VALUE integer, + ROLE_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS)^ + +create clustered index IDX_SEC_PERMISSION_ROLE on SEC_PERMISSION (ROLE_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_CONSTRAINT ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + CODE varchar(255), + CHECK_TYPE varchar(50) default 'db', + OPERATION_TYPE varchar(50) default 'read', + ENTITY_NAME varchar(255) not null, + JOIN_CLAUSE varchar(500), + WHERE_CLAUSE varchar(1000), + GROOVY_SCRIPT varchar(max), + FILTER_XML varchar(max), + IS_ACTIVE tinyint default 1, + GROUP_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create clustered index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOCALIZED_CONSTRAINT_MSG ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + ENTITY_NAME varchar(255) not null, + OPERATION_TYPE varchar(50) not null, + VALUES_ varchar(max), + -- + primary key (ID) +)^ + +create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE + on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SESSION_ATTR ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NAME varchar(50), + STR_VALUE varchar(1000), + DATATYPE varchar(20), + GROUP_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create clustered index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SETTING ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + USER_ID uniqueidentifier, + CLIENT_TYPE char(1), + NAME varchar(255), + VALUE varchar(max), + -- + primary key nonclustered (ID), + constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) +)^ + +create clustered index IDX_SEC_USER_SETTING_CREATE_TS on SEC_USER_SETTING (CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SUBSTITUTION ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + USER_ID uniqueidentifier not null, + SUBSTITUTED_USER_ID uniqueidentifier not null, + START_DATE datetime, + END_DATE datetime, + -- + primary key nonclustered (ID), + constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) +)^ + +create clustered index IDX_SEC_USER_SUBSTITUTION_USER on SEC_USER_SUBSTITUTION (USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ENTITY ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + NAME varchar(100), + AUTO tinyint, + MANUAL tinyint, + -- + primary key (ID), + constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ATTR ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + ENTITY_ID uniqueidentifier, + NAME varchar(50), + -- + primary key nonclustered (ID), + constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), + constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) +)^ + +create clustered index IDX_SEC_LOGGED_ATTR_ENTITY on SEC_LOGGED_ATTR (ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ENTITY_LOG ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + EVENT_TS datetime, + USER_ID uniqueidentifier, + CHANGE_TYPE char(1), + ENTITY varchar(100), + ENTITY_ID uniqueidentifier, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + CHANGES varchar(max), + -- + primary key nonclustered (ID), + constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create clustered index IDX_SEC_ENTITY_LOG_EVENT_TS on SEC_ENTITY_LOG (EVENT_TS)^ + +create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_FILTER ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + CODE varchar(200), + XML varchar(max), + USER_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create clustered index IDX_SEC_FILTER_COMPONENT_USER on SEC_FILTER (COMPONENT, USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FOLDER ( + ID uniqueidentifier, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + FOLDER_TYPE char(1), + PARENT_ID uniqueidentifier, + NAME varchar(100), + TAB_NAME varchar(100), + SORT_ORDER integer, + -- + primary key (ID), + constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_APP_FOLDER ( + FOLDER_ID uniqueidentifier, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + VISIBILITY_SCRIPT varchar(max), + QUANTITY_SCRIPT varchar(max), + APPLY_DEFAULT tinyint, + -- + primary key (FOLDER_ID), + constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PRESENTATION ( + ID uniqueidentifier, + CREATE_TS datetime, + CREATED_BY varchar(50), + UPDATE_TS datetime, + UPDATED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + XML varchar(7000), + USER_ID uniqueidentifier, + IS_AUTO_SAVE tinyint, + -- + primary key nonclustered (ID), + constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create clustered index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SEARCH_FOLDER ( + FOLDER_ID uniqueidentifier, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + USER_ID uniqueidentifier, + PRESENTATION_ID uniqueidentifier, + APPLY_DEFAULT tinyint, + IS_SET tinyint, + ENTITY_TYPE varchar(50), + -- + primary key (FOLDER_ID), + constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), + constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) + references SEC_PRESENTATION(ID) + on delete set null +)^ + +create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FTS_QUEUE ( + ID uniqueidentifier, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + ENTITY_ID uniqueidentifier, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + ENTITY_NAME varchar(200), + CHANGE_TYPE char(1), + SOURCE_HOST varchar(255), + INDEXING_HOST varchar(255), + FAKE tinyint, + -- + primary key nonclustered (ID) +)^ + +create clustered index IDX_SYS_FTS_QUEUE_CREATE_TS on SYS_FTS_QUEUE (CREATE_TS)^ + +create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SCREEN_HISTORY ( + ID uniqueidentifier, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + USER_ID uniqueidentifier, + CAPTION varchar(255), + URL varchar(max), + ENTITY_ID uniqueidentifier, + SUBSTITUTED_USER_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), + constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) +)^ + +create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ +create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ + +create clustered index IDX_SEC_SCREEN_HISTORY_CREATE_TS on SEC_SCREEN_HISTORY (CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_MESSAGE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + ADDRESS_TO varchar(max), + ADDRESS_FROM varchar(100), + CAPTION varchar(500), + EMAIL_HEADERS varchar(500), + CONTENT_TEXT varchar(max), + CONTENT_TEXT_FILE_ID uniqueidentifier, + DEADLINE datetime, + STATUS int, + DATE_SENT datetime, + ATTEMPTS_COUNT int, + ATTEMPTS_MADE int, + ATTACHMENTS_NAME varchar(max), + -- + primary key nonclustered (ID), + constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) +)^ + +create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ + +create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ + +create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ + +create clustered index IDX_SYS_SENDING_MESSAGE_CREATE_TS on SYS_SENDING_MESSAGE (CREATE_TS)^ + + ------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_ATTACHMENT ( + ID uniqueidentifier, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + MESSAGE_ID uniqueidentifier, + CONTENT image, + CONTENT_FILE_ID uniqueidentifier, + CONTENT_ID varchar(50), + NAME varchar(500), + DISPOSITION varchar(50), + TEXT_ENCODING varchar(50), + + -- + primary key nonclustered (ID), + constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), + constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) +)^ + +create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ + +create clustered index IDX_SYS_SENDING_ATTACHMENT_CREATE_TS on SYS_SENDING_ATTACHMENT (CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_SNAPSHOT ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + ENTITY_META_CLASS varchar(50) not null, + ENTITY_ID uniqueidentifier, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + AUTHOR_ID uniqueidentifier not null, + VIEW_XML varchar(max) not null, + SNAPSHOT_XML varchar(max) not null, + SNAPSHOT_DATE datetime not null, + -- + primary key nonclustered (ID), + constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) +)^ + +create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ + +create clustered index IDX_SYS_ENTITY_SNAPSHOT_CREATE_TS on SYS_ENTITY_SNAPSHOT (CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_CATEGORY( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + SPECIAL varchar(50), + ENTITY_TYPE varchar(100) not null, + IS_DEFAULT tinyint, + DISCRIMINATOR integer, + LOCALE_NAMES varchar(1000), + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS)^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_CATEGORY_ATTR ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + CATEGORY_ENTITY_TYPE varchar(4000), + NAME varchar(255), + CODE varchar(100) not null, + CATEGORY_ID uniqueidentifier not null, + ENTITY_CLASS varchar(500), + DATA_TYPE varchar(200), + DEFAULT_STRING varchar(max), + DEFAULT_INT integer, + DEFAULT_DOUBLE numeric, + DEFAULT_DATE datetime, + DEFAULT_DATE_IS_CURRENT tinyint, + DEFAULT_BOOLEAN tinyint, + DEFAULT_ENTITY_VALUE uniqueidentifier, + DEFAULT_STR_ENTITY_VALUE varchar(255), + DEFAULT_INT_ENTITY_VALUE integer, + DEFAULT_LONG_ENTITY_VALUE bigint, + ENUMERATION varchar(500), + ORDER_NO integer, + SCREEN varchar(255), + REQUIRED tinyint, + LOOKUP tinyint, + TARGET_SCREENS varchar(4000), + WIDTH varchar(20), + ROWS_COUNT integer, + IS_COLLECTION tinyint, + JOIN_CLAUSE varchar(4000), + WHERE_CLAUSE varchar(4000), + FILTER_XML varchar(max), + LOCALE_NAMES varchar(1000), + ENUMERATION_LOCALES varchar(5000), + -- + primary key nonclustered (ID), + constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) +)^ + +create clustered index IDX_SYS_CATEGORY_ATTR_CATEGORY on SYS_CATEGORY_ATTR (CATEGORY_ID)^ +create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE, DELETE_TS); +------------------------------------------------------------------------------------------------------------- + +create table SYS_ATTR_VALUE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + CATEGORY_ATTR_ID uniqueidentifier not null, + ENTITY_ID uniqueidentifier, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + STRING_VALUE varchar(max), + INTEGER_VALUE integer, + DOUBLE_VALUE numeric, + DATE_VALUE datetime, + BOOLEAN_VALUE tinyint, + ENTITY_VALUE uniqueidentifier, + STRING_ENTITY_VALUE varchar(255), + INT_ENTITY_VALUE integer, + LONG_ENTITY_VALUE bigint, + CODE varchar(100), + PARENT_ID uniqueidentifier, + -- + primary key nonclustered (ID), + constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), + constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) +)^ + +create clustered index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE (ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SYS_JMX_INSTANCE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + NODE_NAME varchar(255), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) +)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SYS_QUERY_RESULT ( + ID bigint identity not null, + SESSION_ID uniqueidentifier not null, + QUERY_KEY integer not null, + ENTITY_ID uniqueidentifier, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + -- + primary key (ID) +)^ + +create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ + +create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ + +------------------------------------------------------------------------------------------------------------------ + +create table SEC_REMEMBER_ME ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + -- + USER_ID uniqueidentifier not null, + TOKEN varchar(32) not null, + -- + primary key (ID), + constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) +)^ +create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ +create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ + +------------------------------------------------------------------------------------------------------------------ + +create table SYS_REST_API_TOKEN ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + -- + ACCESS_TOKEN_VALUE varchar(255), + ACCESS_TOKEN_BYTES image, + AUTHENTICATION_KEY varchar(255), + AUTHENTICATION_BYTES image, + EXPIRY datetime, + USER_LOGIN varchar(50), + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------------ + +create table SEC_SESSION_LOG ( + ID uniqueidentifier not null, + VERSION integer not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + SESSION_ID uniqueidentifier not null, + USER_ID uniqueidentifier not null, + SUBSTITUTED_USER_ID uniqueidentifier, + USER_DATA varchar(max), + LAST_ACTION integer not null, + CLIENT_INFO varchar(512), + CLIENT_TYPE varchar(10), + ADDRESS varchar(255), + STARTED_TS datetime, + FINISHED_TS datetime, + SERVER_ID varchar(128), + -- + primary key (ID), + constraint FK_SESSION_LOG_ENTRY_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SESSION_LOG_ENTRY_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SESSION_LOG_ENTRY_USER on SEC_SESSION_LOG (USER_ID)^ +create index IDX_SESSION_LOG_ENTRY_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ +create index IDX_SESSION_LOG_ENTRY_SESSION on SEC_SESSION_LOG (SESSION_ID)^ + +------------------------------------------------------------------------------------------------------------------ + +insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) +values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', current_timestamp, 0, 'Company', null)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('60885987-1b61-4247-94c7-dff348347f93', current_timestamp, 0, 'admin', 'admin', +'cc2229d1b8a052423d9e1c9ef0113b850086586a', +'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', 1)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('a405db59-e674-4f63-8afe-269dda788fe8', current_timestamp, 0, 'anonymous', 'anonymous', null, +'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', 1)^ + +insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) +values ('0c018061-b26f-4de2-a5be-dff348347f93', current_timestamp, 0, 'Administrators', 10)^ + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', current_timestamp, 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ + +insert into SEC_FILTER (ID,CREATE_TS,CREATED_BY,VERSION,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,COMPONENT,NAME,XML,USER_ID) +values ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', +' + + + ur.role.id = :component$genericFilter.UrMxpkfMGn32565 + NULL + + +', +'60885987-1b61-4247-94c7-dff348347f93')^ diff --git a/modules/core/db/init/mysql/create-db.sql b/modules/core/db/init/mysql/create-db.sql index 72b0c962c8..d0e5321fde 100644 --- a/modules/core/db/init/mysql/create-db.sql +++ b/modules/core/db/init/mysql/create-db.sql @@ -1,1000 +1,1000 @@ -create table SYS_SERVER ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - NAME varchar(190), - IS_RUNNING boolean, - DATA text, - primary key (ID) -)^ - -create unique index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ - -/***************************************************************************************************/ - -create table SYS_CONFIG ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - -- - NAME varchar(190), - VALUE text, - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ - -/**********************************************************************************************/ - -create table SYS_FILE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - NAME varchar(500) not null, - EXT varchar(20), - FILE_SIZE bigint, - CREATE_DATE datetime(3), - -- - primary key (ID) -)^ - -/**********************************************************************************************/ - -create table SYS_LOCK_CONFIG ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - NAME varchar(100), - TIMEOUT_SEC integer, - -- - primary key (ID) -)^ - -/**********************************************************************************************/ - -create table SYS_ENTITY_STATISTICS ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - -- - NAME varchar(50), - INSTANCE_COUNT bigint, - FETCH_UI integer, - MAX_FETCH_UI integer, - LAZY_COLLECTION_THRESHOLD integer, - LOOKUP_SCREEN_THRESHOLD integer, - -- - primary key (ID) -)^ - -create unique index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ - -/**********************************************************************************************/ - -create table SYS_SCHEDULED_TASK ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - DEFINED_BY varchar(1) default 'B', - CLASS_NAME varchar(500), - SCRIPT_NAME varchar(500), - BEAN_NAME varchar(50), - METHOD_NAME varchar(50), - METHOD_PARAMS varchar(1000), - USER_NAME varchar(50), - IS_SINGLETON boolean, - IS_ACTIVE boolean, - PERIOD integer, - TIMEOUT integer, - START_DATE datetime(3), - TIME_FRAME integer, - START_DELAY integer, - PERMITTED_SERVERS varchar(4096), - LOG_START boolean, - LOG_FINISH boolean, - LAST_START_TIME datetime(3), - LAST_START_SERVER varchar(512), - DESCRIPTION varchar(1000), - CRON varchar(100), - SCHEDULING_TYPE varchar(1) default 'P', - -- - primary key (ID) -)^ - --- create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME, METHOD_PARAMS, DELETE_TS)^ - -/**********************************************************************************************/ - -create table SYS_SCHEDULED_EXECUTION ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - TASK_ID varchar(32), - SERVER varchar(512), - START_TIME datetime(3), - FINISH_TIME datetime(3), - RESULT text, - -- - primary key (ID), - constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) -)^ - -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ - -/**********************************************************************************************/ - -create table SEC_ROLE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - NAME varchar(190) not null, - LOC_NAME varchar(255), - DESCRIPTION varchar(1000), - IS_DEFAULT_ROLE boolean, - ROLE_TYPE integer, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME, DELETE_TS_NN)^ - -create trigger SEC_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_ROLE -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - -/**********************************************************************************************/ - -create table SEC_GROUP ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - NAME varchar(190) not null, - PARENT_ID varchar(32), - -- - primary key (ID), - constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - -create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME, DELETE_TS_NN)^ - -create trigger SEC_GROUP_DELETE_TS_NN_TRIGGER before update on SEC_GROUP -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - -/**********************************************************************************************/ - -create table SEC_GROUP_HIERARCHY ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - GROUP_ID varchar(32), - PARENT_ID varchar(32), - HIERARCHY_LEVEL integer, - -- - primary key (ID), - constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), - constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_USER ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - LOGIN varchar(50) not null, - LOGIN_LC varchar(50) not null, - PASSWORD varchar(255), - NAME varchar(255), - FIRST_NAME varchar(255), - LAST_NAME varchar(255), - MIDDLE_NAME varchar(255), - POSITION_ varchar(255), - EMAIL varchar(100), - LANGUAGE_ varchar(20), - TIME_ZONE varchar(50), - TIME_ZONE_AUTO boolean, - ACTIVE boolean, - GROUP_ID varchar(32) not null, - IP_MASK varchar(200), - CHANGE_PASSWORD_AT_LOGON boolean, - -- - primary key (ID), - constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS_NN)^ - -create trigger SEC_USER_DELETE_TS_NN_TRIGGER before update on SEC_USER -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - -/**********************************************************************************************/ - -create table SEC_USER_ROLE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - USER_ID varchar(32), - ROLE_ID varchar(32), - -- - primary key (ID), - constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID, DELETE_TS_NN)^ - -create trigger SEC_USER_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_USER_ROLE -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - - - -/**********************************************************************************************/ - -create table SEC_PERMISSION ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - PERMISSION_TYPE integer, - TARGET varchar(100), - VALUE integer, - ROLE_ID varchar(32), - -- - primary key (ID), - constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS_NN)^ - -create trigger SEC_PERMISSION_DELETE_TS_NN_TRIGGER before update on SEC_PERMISSION -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - - -/**********************************************************************************************/ - -create table SEC_CONSTRAINT ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - CODE varchar(255), - CHECK_TYPE varchar(50) default 'db', - OPERATION_TYPE varchar(50) default 'read', - ENTITY_NAME varchar(255) not null, - JOIN_CLAUSE varchar(500), - WHERE_CLAUSE varchar(1000), - GROOVY_SCRIPT text, - FILTER_XML text, - IS_ACTIVE boolean default true, - GROUP_ID varchar(32), - -- - primary key (ID), - constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_LOCALIZED_CONSTRAINT_MSG ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - ENTITY_NAME varchar(255) not null, - OPERATION_TYPE varchar(50) not null, - VALUES_ text, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE - on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS_NN)^ - -create trigger SEC_LOCALIZED_CONSTRAINT_MSG_DELETE_TS_NN_TRIGGER before update on SEC_LOCALIZED_CONSTRAINT_MSG -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - -/**********************************************************************************************/ - -create table SEC_SESSION_ATTR ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - NAME varchar(50), - STR_VALUE varchar(1000), - DATATYPE varchar(20), - GROUP_ID varchar(32), - -- - primary key (ID), - constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_USER_SETTING ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - USER_ID varchar(32), - CLIENT_TYPE char(1), - NAME varchar(190), - VALUE text, - -- - primary key (ID), - constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) -)^ - -/**********************************************************************************************/ - -create table SEC_USER_SUBSTITUTION ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - USER_ID varchar(32) not null, - SUBSTITUTED_USER_ID varchar(32) not null, - START_DATE datetime(3), - END_DATE datetime(3), - -- - primary key (ID), - constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_LOGGED_ENTITY ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - NAME varchar(100), - AUTO boolean, - MANUAL boolean, - -- - primary key (ID), - constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) -)^ - -/**********************************************************************************************/ - -create table SEC_LOGGED_ATTR ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - ENTITY_ID varchar(32), - NAME varchar(50), - -- - primary key (ID), - constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), - constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) -)^ - -/**********************************************************************************************/ - -create table SEC_ENTITY_LOG ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - EVENT_TS datetime(3), - USER_ID varchar(32), - CHANGE_TYPE char(1), - ENTITY varchar(100), - ENTITY_ID varchar(32), - STRING_ENTITY_ID varchar(190), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - CHANGES text, - -- - primary key (ID), - constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ - -/**********************************************************************************************/ - -create table SEC_FILTER ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - CODE varchar(200), - XML text, - USER_ID varchar(32), - -- - primary key (ID), - constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -/**********************************************************************************************/ - -create table SYS_FOLDER ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - FOLDER_TYPE char(1), - PARENT_ID varchar(32), - NAME varchar(100), - TAB_NAME varchar(100), - SORT_ORDER integer, - -- - primary key (ID), - constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) -)^ - -/**********************************************************************************************/ - -create table SYS_APP_FOLDER ( - FOLDER_ID varchar(32), - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - VISIBILITY_SCRIPT text, - QUANTITY_SCRIPT text, - APPLY_DEFAULT boolean, - -- - primary key (FOLDER_ID), - constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_PRESENTATION ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - XML varchar(7000), - USER_ID varchar(32), - IS_AUTO_SAVE boolean, - -- - primary key (ID), - constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -/**********************************************************************************************/ - -create table SEC_SEARCH_FOLDER ( - FOLDER_ID varchar(32), - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - USER_ID varchar(32), - PRESENTATION_ID varchar(32), - APPLY_DEFAULT boolean, - IS_SET boolean, - ENTITY_TYPE varchar(50), - -- - primary key (FOLDER_ID), - constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), - constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) - references SEC_PRESENTATION(ID) - on delete set null -)^ - -create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ - -/**********************************************************************************************/ - -create table SYS_FTS_QUEUE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - ENTITY_ID varchar(32), - STRING_ENTITY_ID varchar(190), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - ENTITY_NAME varchar(200), - CHANGE_TYPE char(1), - SOURCE_HOST varchar(255), - INDEXING_HOST varchar(190), - FAKE boolean, - -- - primary key (ID) -)^ - -create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ - -/**********************************************************************************************/ - -create table SEC_SCREEN_HISTORY ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - USER_ID varchar(32), - CAPTION varchar(255), - URL text, - ENTITY_ID varchar(32), - SUBSTITUTED_USER_ID varchar(32), - -- - primary key (ID), - constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), - constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) -)^ - -create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ -create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ - -/**********************************************************************************************/ - -create table SYS_SENDING_MESSAGE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - ADDRESS_TO text, - ADDRESS_FROM varchar(100), - CAPTION varchar(500), - EMAIL_HEADERS varchar(500), - CONTENT_TEXT text, - CONTENT_TEXT_FILE_ID varchar(32), - DEADLINE datetime(3), - STATUS int, - DATE_SENT datetime(3), - ATTEMPTS_COUNT int, - ATTEMPTS_MADE int, - ATTACHMENTS_NAME text, - -- - primary key (ID), - constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) -)^ - -create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ - -create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ - -create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ - - #------------------------------------------------------------------------------------------------------------ - -create table SYS_SENDING_ATTACHMENT ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - MESSAGE_ID varchar(32), - CONTENT blob, - CONTENT_FILE_ID varchar(32), - CONTENT_ID varchar(50), - NAME varchar(500), - DISPOSITION varchar(50), - TEXT_ENCODING varchar(50), - - -- - primary key (ID), - constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), - constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) -)^ - -create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ - -/**********************************************************************************************/ - -create table SYS_ENTITY_SNAPSHOT ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - ENTITY_META_CLASS varchar(50) not null, - ENTITY_ID varchar(32), - STRING_ENTITY_ID varchar(190), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - AUTHOR_ID varchar(32) not null, - VIEW_XML text not null, - SNAPSHOT_XML text not null, - SNAPSHOT_DATE datetime(3) not null, - -- - primary key (ID), - constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) -)^ - -create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ - -/**********************************************************************************************/ - -create table SYS_CATEGORY( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', - -- - NAME varchar(190) not null, - SPECIAL varchar(50), - ENTITY_TYPE varchar(100) not null, - IS_DEFAULT boolean, - DISCRIMINATOR integer, - LOCALE_NAMES varchar(1000), - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS_NN)^ - -create trigger SYS_CATEGORY_DELETE_TS_NN_TRIGGER before update on SYS_CATEGORY -for each row - if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then - set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); - end if^ - -/**********************************************************************************************/ - -create table SYS_CATEGORY_ATTR ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - CATEGORY_ENTITY_TYPE text, - NAME varchar(255), - CODE varchar(100) not null, - CATEGORY_ID varchar(32) not null, - ENTITY_CLASS varchar(500), - DATA_TYPE varchar(200), - DEFAULT_STRING text, - DEFAULT_INT integer, - DEFAULT_DOUBLE numeric, - DEFAULT_DATE datetime(3), - DEFAULT_DATE_IS_CURRENT boolean, - DEFAULT_BOOLEAN boolean, - DEFAULT_ENTITY_VALUE varchar(36), - DEFAULT_STR_ENTITY_VALUE varchar(255), - DEFAULT_INT_ENTITY_VALUE integer, - DEFAULT_LONG_ENTITY_VALUE bigint, - ENUMERATION varchar(500), - ORDER_NO integer, - SCREEN varchar(255), - REQUIRED boolean, - LOOKUP boolean, - TARGET_SCREENS text, - WIDTH varchar(20), - ROWS_COUNT integer, - IS_COLLECTION boolean, - JOIN_CLAUSE text, - WHERE_CLAUSE text, - FILTER_XML longtext, - LOCALE_NAMES varchar(1000), - ENUMERATION_LOCALES text, - -- - primary key (ID), - constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) -)^ - -/**********************************************************************************************/ - -create table SYS_ATTR_VALUE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - CATEGORY_ATTR_ID varchar(32) not null, - ENTITY_ID varchar(32), - STRING_ENTITY_ID varchar(190), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - STRING_VALUE text, - INTEGER_VALUE integer, - DOUBLE_VALUE numeric, - DATE_VALUE datetime(3), - BOOLEAN_VALUE boolean, - ENTITY_VALUE varchar(36), - STRING_ENTITY_VALUE varchar(190), - INT_ENTITY_VALUE integer, - LONG_ENTITY_VALUE bigint, - CODE varchar(100), - PARENT_ID varchar(32), - -- - primary key (ID), - constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), - constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) - -)^ - -create index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE(ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ - -/**********************************************************************************************/ - -create table SYS_JMX_INSTANCE ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - NODE_NAME varchar(255), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) -)^ - -/**********************************************************************************************/ - -create table SYS_QUERY_RESULT ( - ID bigint auto_increment not null, - SESSION_ID varchar(32) not null, - QUERY_KEY integer not null, - ENTITY_ID varchar(32), - STRING_ENTITY_ID varchar(190), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - -- - primary key (ID) -)^ - -create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ - -create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ - -/**********************************************************************************************/ - -create table SEC_REMEMBER_ME ( - ID varchar(32), - CREATE_TS datetime(3), - CREATED_BY varchar(50), - VERSION integer, - -- - USER_ID varchar(32) not null, - TOKEN varchar(32) not null, - -- - primary key (ID), - constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) -)^ -create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ -create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ - -/**********************************************************************************************/ - -create table SYS_REST_API_TOKEN ( - ID varchar(32) not null, - CREATE_TS datetime(3), - CREATED_BY varchar(50), - -- - ACCESS_TOKEN_VALUE varchar(255), - ACCESS_TOKEN_BYTES longblob, - AUTHENTICATION_KEY varchar(255), - AUTHENTICATION_BYTES longblob, - EXPIRY datetime(3), - USER_LOGIN varchar(50), - -- - primary key (ID) -)^ - -/**********************************************************************************************/ - -create table SEC_SESSION_LOG ( - ID varchar(32) not null, - VERSION integer not null, - CREATE_TS datetime(3), - CREATED_BY varchar(50), - UPDATE_TS datetime(3), - UPDATED_BY varchar(50), - DELETE_TS datetime(3), - DELETED_BY varchar(50), - -- - SESSION_ID varchar(32) not null, - USER_ID varchar(32) not null, - SUBSTITUTED_USER_ID varchar(32), - USER_DATA text, - LAST_ACTION integer not null, - CLIENT_INFO varchar(512), - CLIENT_TYPE varchar(10), - ADDRESS varchar(255), - STARTED_TS datetime(3), - FINISHED_TS datetime(3), - SERVER_ID varchar(128), - -- - primary key (ID), - constraint FK_SESSION_LOG_ENTRY_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SESSION_LOG_ENTRY_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SESSION_LOG_ENTRY_USER on SEC_SESSION_LOG (USER_ID)^ -create index IDX_SESSION_LOG_ENTRY_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ -create index IDX_SESSION_LOG_ENTRY_SESSION on SEC_SESSION_LOG (SESSION_ID)^ - -/**********************************************************************************************/ - -drop function if exists newid^ -create function newid() returns varchar(32) not deterministic -return replace(uuid(), '-', '')^ - -/**********************************************************************************************/ - -insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) -values ('0fa2b1a51d684d699fbddff348347f93', current_timestamp, 0, 'Company', null)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('608859871b61424794c7dff348347f93', current_timestamp, 0, 'admin', 'admin', -'cc2229d1b8a052423d9e1c9ef0113b850086586a', -'Administrator', '0fa2b1a51d684d699fbddff348347f93', 1)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('a405db59e6744f638afe269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, -'Anonymous', '0fa2b1a51d684d699fbddff348347f93', true)^ - -insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) -values ('0c018061b26f4de2a5bedff348347f93', current_timestamp, 0, 'Administrators', 10)^ - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('c838be0a96d04ef4a7c0dff348347f93', current_timestamp, 0, '608859871b61424794c7dff348347f93', '0c018061b26f4de2a5bedff348347f93')^ - -insert into SEC_FILTER (ID,CREATE_TS,CREATED_BY,VERSION,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,COMPONENT,NAME,XML,USER_ID) -values ('b61d18cbe79a46f3b16deaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', -' - - - ur.role.id = :component$genericFilter.UrMxpkfMGn32565 - NULL - - -', -'608859871b61424794c7dff348347f93')^ - -/**********************************************************************************************/ - -create table IF NOT EXISTS SYS_SEQUENCE ( - NAME varchar(100) not null, - INCREMENT int unsigned not null default 1, - CURR_VALUE bigint unsigned default 0, - primary key (NAME) -)^ - +create table SYS_SERVER ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + NAME varchar(190), + IS_RUNNING boolean, + DATA text, + primary key (ID) +)^ + +create unique index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ + +/***************************************************************************************************/ + +create table SYS_CONFIG ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + -- + NAME varchar(190), + VALUE text, + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ + +/**********************************************************************************************/ + +create table SYS_FILE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + NAME varchar(500) not null, + EXT varchar(20), + FILE_SIZE bigint, + CREATE_DATE datetime(3), + -- + primary key (ID) +)^ + +/**********************************************************************************************/ + +create table SYS_LOCK_CONFIG ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + NAME varchar(100), + TIMEOUT_SEC integer, + -- + primary key (ID) +)^ + +/**********************************************************************************************/ + +create table SYS_ENTITY_STATISTICS ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + -- + NAME varchar(50), + INSTANCE_COUNT bigint, + FETCH_UI integer, + MAX_FETCH_UI integer, + LAZY_COLLECTION_THRESHOLD integer, + LOOKUP_SCREEN_THRESHOLD integer, + -- + primary key (ID) +)^ + +create unique index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ + +/**********************************************************************************************/ + +create table SYS_SCHEDULED_TASK ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + DEFINED_BY varchar(1) default 'B', + CLASS_NAME varchar(500), + SCRIPT_NAME varchar(500), + BEAN_NAME varchar(50), + METHOD_NAME varchar(50), + METHOD_PARAMS varchar(1000), + USER_NAME varchar(50), + IS_SINGLETON boolean, + IS_ACTIVE boolean, + PERIOD integer, + TIMEOUT integer, + START_DATE datetime(3), + TIME_FRAME integer, + START_DELAY integer, + PERMITTED_SERVERS varchar(4096), + LOG_START boolean, + LOG_FINISH boolean, + LAST_START_TIME datetime(3), + LAST_START_SERVER varchar(512), + DESCRIPTION varchar(1000), + CRON varchar(100), + SCHEDULING_TYPE varchar(1) default 'P', + -- + primary key (ID) +)^ + +-- create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME, METHOD_PARAMS, DELETE_TS)^ + +/**********************************************************************************************/ + +create table SYS_SCHEDULED_EXECUTION ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + TASK_ID varchar(32), + SERVER varchar(512), + START_TIME datetime(3), + FINISH_TIME datetime(3), + RESULT text, + -- + primary key (ID), + constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) +)^ + +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ + +/**********************************************************************************************/ + +create table SEC_ROLE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + NAME varchar(190) not null, + LOC_NAME varchar(255), + DESCRIPTION varchar(1000), + IS_DEFAULT_ROLE boolean, + ROLE_TYPE integer, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME, DELETE_TS_NN)^ + +create trigger SEC_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_ROLE +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + +/**********************************************************************************************/ + +create table SEC_GROUP ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + NAME varchar(190) not null, + PARENT_ID varchar(32), + -- + primary key (ID), + constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME, DELETE_TS_NN)^ + +create trigger SEC_GROUP_DELETE_TS_NN_TRIGGER before update on SEC_GROUP +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + +/**********************************************************************************************/ + +create table SEC_GROUP_HIERARCHY ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + GROUP_ID varchar(32), + PARENT_ID varchar(32), + HIERARCHY_LEVEL integer, + -- + primary key (ID), + constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), + constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_USER ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + LOGIN varchar(50) not null, + LOGIN_LC varchar(50) not null, + PASSWORD varchar(255), + NAME varchar(255), + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + MIDDLE_NAME varchar(255), + POSITION_ varchar(255), + EMAIL varchar(100), + LANGUAGE_ varchar(20), + TIME_ZONE varchar(50), + TIME_ZONE_AUTO boolean, + ACTIVE boolean, + GROUP_ID varchar(32) not null, + IP_MASK varchar(200), + CHANGE_PASSWORD_AT_LOGON boolean, + -- + primary key (ID), + constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS_NN)^ + +create trigger SEC_USER_DELETE_TS_NN_TRIGGER before update on SEC_USER +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + +/**********************************************************************************************/ + +create table SEC_USER_ROLE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + USER_ID varchar(32), + ROLE_ID varchar(32), + -- + primary key (ID), + constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID, DELETE_TS_NN)^ + +create trigger SEC_USER_ROLE_DELETE_TS_NN_TRIGGER before update on SEC_USER_ROLE +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + + + +/**********************************************************************************************/ + +create table SEC_PERMISSION ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + PERMISSION_TYPE integer, + TARGET varchar(100), + VALUE integer, + ROLE_ID varchar(32), + -- + primary key (ID), + constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET, DELETE_TS_NN)^ + +create trigger SEC_PERMISSION_DELETE_TS_NN_TRIGGER before update on SEC_PERMISSION +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + + +/**********************************************************************************************/ + +create table SEC_CONSTRAINT ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + CODE varchar(255), + CHECK_TYPE varchar(50) default 'db', + OPERATION_TYPE varchar(50) default 'read', + ENTITY_NAME varchar(255) not null, + JOIN_CLAUSE varchar(500), + WHERE_CLAUSE varchar(1000), + GROOVY_SCRIPT text, + FILTER_XML text, + IS_ACTIVE boolean default true, + GROUP_ID varchar(32), + -- + primary key (ID), + constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_LOCALIZED_CONSTRAINT_MSG ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + ENTITY_NAME varchar(255) not null, + OPERATION_TYPE varchar(50) not null, + VALUES_ text, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE + on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE, DELETE_TS_NN)^ + +create trigger SEC_LOCALIZED_CONSTRAINT_MSG_DELETE_TS_NN_TRIGGER before update on SEC_LOCALIZED_CONSTRAINT_MSG +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + +/**********************************************************************************************/ + +create table SEC_SESSION_ATTR ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + NAME varchar(50), + STR_VALUE varchar(1000), + DATATYPE varchar(20), + GROUP_ID varchar(32), + -- + primary key (ID), + constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_USER_SETTING ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + USER_ID varchar(32), + CLIENT_TYPE char(1), + NAME varchar(190), + VALUE text, + -- + primary key (ID), + constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) +)^ + +/**********************************************************************************************/ + +create table SEC_USER_SUBSTITUTION ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + USER_ID varchar(32) not null, + SUBSTITUTED_USER_ID varchar(32) not null, + START_DATE datetime(3), + END_DATE datetime(3), + -- + primary key (ID), + constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_LOGGED_ENTITY ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + NAME varchar(100), + AUTO boolean, + MANUAL boolean, + -- + primary key (ID), + constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) +)^ + +/**********************************************************************************************/ + +create table SEC_LOGGED_ATTR ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + ENTITY_ID varchar(32), + NAME varchar(50), + -- + primary key (ID), + constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), + constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) +)^ + +/**********************************************************************************************/ + +create table SEC_ENTITY_LOG ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + EVENT_TS datetime(3), + USER_ID varchar(32), + CHANGE_TYPE char(1), + ENTITY varchar(100), + ENTITY_ID varchar(32), + STRING_ENTITY_ID varchar(190), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + CHANGES text, + -- + primary key (ID), + constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ + +/**********************************************************************************************/ + +create table SEC_FILTER ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + CODE varchar(200), + XML text, + USER_ID varchar(32), + -- + primary key (ID), + constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +/**********************************************************************************************/ + +create table SYS_FOLDER ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + FOLDER_TYPE char(1), + PARENT_ID varchar(32), + NAME varchar(100), + TAB_NAME varchar(100), + SORT_ORDER integer, + -- + primary key (ID), + constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) +)^ + +/**********************************************************************************************/ + +create table SYS_APP_FOLDER ( + FOLDER_ID varchar(32), + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + VISIBILITY_SCRIPT text, + QUANTITY_SCRIPT text, + APPLY_DEFAULT boolean, + -- + primary key (FOLDER_ID), + constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_PRESENTATION ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + XML varchar(7000), + USER_ID varchar(32), + IS_AUTO_SAVE boolean, + -- + primary key (ID), + constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +/**********************************************************************************************/ + +create table SEC_SEARCH_FOLDER ( + FOLDER_ID varchar(32), + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + USER_ID varchar(32), + PRESENTATION_ID varchar(32), + APPLY_DEFAULT boolean, + IS_SET boolean, + ENTITY_TYPE varchar(50), + -- + primary key (FOLDER_ID), + constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), + constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) + references SEC_PRESENTATION(ID) + on delete set null +)^ + +create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ + +/**********************************************************************************************/ + +create table SYS_FTS_QUEUE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + ENTITY_ID varchar(32), + STRING_ENTITY_ID varchar(190), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + ENTITY_NAME varchar(200), + CHANGE_TYPE char(1), + SOURCE_HOST varchar(255), + INDEXING_HOST varchar(190), + FAKE boolean, + -- + primary key (ID) +)^ + +create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ + +/**********************************************************************************************/ + +create table SEC_SCREEN_HISTORY ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + USER_ID varchar(32), + CAPTION varchar(255), + URL text, + ENTITY_ID varchar(32), + SUBSTITUTED_USER_ID varchar(32), + -- + primary key (ID), + constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), + constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) +)^ + +create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ +create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ + +/**********************************************************************************************/ + +create table SYS_SENDING_MESSAGE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + ADDRESS_TO text, + ADDRESS_FROM varchar(100), + CAPTION varchar(500), + EMAIL_HEADERS varchar(500), + CONTENT_TEXT text, + CONTENT_TEXT_FILE_ID varchar(32), + DEADLINE datetime(3), + STATUS int, + DATE_SENT datetime(3), + ATTEMPTS_COUNT int, + ATTEMPTS_MADE int, + ATTACHMENTS_NAME text, + -- + primary key (ID), + constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) +)^ + +create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ + +create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ + +create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ + + #------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_ATTACHMENT ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + MESSAGE_ID varchar(32), + CONTENT blob, + CONTENT_FILE_ID varchar(32), + CONTENT_ID varchar(50), + NAME varchar(500), + DISPOSITION varchar(50), + TEXT_ENCODING varchar(50), + + -- + primary key (ID), + constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), + constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) +)^ + +create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ + +/**********************************************************************************************/ + +create table SYS_ENTITY_SNAPSHOT ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + ENTITY_META_CLASS varchar(50) not null, + ENTITY_ID varchar(32), + STRING_ENTITY_ID varchar(190), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + AUTHOR_ID varchar(32) not null, + VIEW_XML text not null, + SNAPSHOT_XML text not null, + SNAPSHOT_DATE datetime(3) not null, + -- + primary key (ID), + constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) +)^ + +create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ + +/**********************************************************************************************/ + +create table SYS_CATEGORY( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + DELETE_TS_NN datetime(3) not null default '1000-01-01 00:00:00.000', + -- + NAME varchar(190) not null, + SPECIAL varchar(50), + ENTITY_TYPE varchar(100) not null, + IS_DEFAULT boolean, + DISCRIMINATOR integer, + LOCALE_NAMES varchar(1000), + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE, DELETE_TS_NN)^ + +create trigger SYS_CATEGORY_DELETE_TS_NN_TRIGGER before update on SYS_CATEGORY +for each row + if not(NEW.DELETE_TS <=> OLD.DELETE_TS) then + set NEW.DELETE_TS_NN = if (NEW.DELETE_TS is null, '1000-01-01 00:00:00.000', NEW.DELETE_TS); + end if^ + +/**********************************************************************************************/ + +create table SYS_CATEGORY_ATTR ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + CATEGORY_ENTITY_TYPE text, + NAME varchar(255), + CODE varchar(100) not null, + CATEGORY_ID varchar(32) not null, + ENTITY_CLASS varchar(500), + DATA_TYPE varchar(200), + DEFAULT_STRING text, + DEFAULT_INT integer, + DEFAULT_DOUBLE numeric, + DEFAULT_DATE datetime(3), + DEFAULT_DATE_IS_CURRENT boolean, + DEFAULT_BOOLEAN boolean, + DEFAULT_ENTITY_VALUE varchar(36), + DEFAULT_STR_ENTITY_VALUE varchar(255), + DEFAULT_INT_ENTITY_VALUE integer, + DEFAULT_LONG_ENTITY_VALUE bigint, + ENUMERATION varchar(500), + ORDER_NO integer, + SCREEN varchar(255), + REQUIRED boolean, + LOOKUP boolean, + TARGET_SCREENS text, + WIDTH varchar(20), + ROWS_COUNT integer, + IS_COLLECTION boolean, + JOIN_CLAUSE text, + WHERE_CLAUSE text, + FILTER_XML longtext, + LOCALE_NAMES varchar(1000), + ENUMERATION_LOCALES text, + -- + primary key (ID), + constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) +)^ + +/**********************************************************************************************/ + +create table SYS_ATTR_VALUE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + CATEGORY_ATTR_ID varchar(32) not null, + ENTITY_ID varchar(32), + STRING_ENTITY_ID varchar(190), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + STRING_VALUE text, + INTEGER_VALUE integer, + DOUBLE_VALUE numeric, + DATE_VALUE datetime(3), + BOOLEAN_VALUE boolean, + ENTITY_VALUE varchar(36), + STRING_ENTITY_VALUE varchar(190), + INT_ENTITY_VALUE integer, + LONG_ENTITY_VALUE bigint, + CODE varchar(100), + PARENT_ID varchar(32), + -- + primary key (ID), + constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), + constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) + +)^ + +create index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE(ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ + +/**********************************************************************************************/ + +create table SYS_JMX_INSTANCE ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + NODE_NAME varchar(255), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) +)^ + +/**********************************************************************************************/ + +create table SYS_QUERY_RESULT ( + ID bigint auto_increment not null, + SESSION_ID varchar(32) not null, + QUERY_KEY integer not null, + ENTITY_ID varchar(32), + STRING_ENTITY_ID varchar(190), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + -- + primary key (ID) +)^ + +create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ + +create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ + +/**********************************************************************************************/ + +create table SEC_REMEMBER_ME ( + ID varchar(32), + CREATE_TS datetime(3), + CREATED_BY varchar(50), + VERSION integer, + -- + USER_ID varchar(32) not null, + TOKEN varchar(32) not null, + -- + primary key (ID), + constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) +)^ +create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ +create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ + +/**********************************************************************************************/ + +create table SYS_REST_API_TOKEN ( + ID varchar(32) not null, + CREATE_TS datetime(3), + CREATED_BY varchar(50), + -- + ACCESS_TOKEN_VALUE varchar(255), + ACCESS_TOKEN_BYTES longblob, + AUTHENTICATION_KEY varchar(255), + AUTHENTICATION_BYTES longblob, + EXPIRY datetime(3), + USER_LOGIN varchar(50), + -- + primary key (ID) +)^ + +/**********************************************************************************************/ + +create table SEC_SESSION_LOG ( + ID varchar(32) not null, + VERSION integer not null, + CREATE_TS datetime(3), + CREATED_BY varchar(50), + UPDATE_TS datetime(3), + UPDATED_BY varchar(50), + DELETE_TS datetime(3), + DELETED_BY varchar(50), + -- + SESSION_ID varchar(32) not null, + USER_ID varchar(32) not null, + SUBSTITUTED_USER_ID varchar(32), + USER_DATA text, + LAST_ACTION integer not null, + CLIENT_INFO varchar(512), + CLIENT_TYPE varchar(10), + ADDRESS varchar(255), + STARTED_TS datetime(3), + FINISHED_TS datetime(3), + SERVER_ID varchar(128), + -- + primary key (ID), + constraint FK_SESSION_LOG_ENTRY_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SESSION_LOG_ENTRY_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SESSION_LOG_ENTRY_USER on SEC_SESSION_LOG (USER_ID)^ +create index IDX_SESSION_LOG_ENTRY_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ +create index IDX_SESSION_LOG_ENTRY_SESSION on SEC_SESSION_LOG (SESSION_ID)^ + +/**********************************************************************************************/ + +drop function if exists newid^ +create function newid() returns varchar(32) not deterministic +return replace(uuid(), '-', '')^ + +/**********************************************************************************************/ + +insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) +values ('0fa2b1a51d684d699fbddff348347f93', current_timestamp, 0, 'Company', null)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('608859871b61424794c7dff348347f93', current_timestamp, 0, 'admin', 'admin', +'cc2229d1b8a052423d9e1c9ef0113b850086586a', +'Administrator', '0fa2b1a51d684d699fbddff348347f93', 1)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('a405db59e6744f638afe269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, +'Anonymous', '0fa2b1a51d684d699fbddff348347f93', true)^ + +insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) +values ('0c018061b26f4de2a5bedff348347f93', current_timestamp, 0, 'Administrators', 10)^ + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('c838be0a96d04ef4a7c0dff348347f93', current_timestamp, 0, '608859871b61424794c7dff348347f93', '0c018061b26f4de2a5bedff348347f93')^ + +insert into SEC_FILTER (ID,CREATE_TS,CREATED_BY,VERSION,UPDATE_TS,UPDATED_BY,DELETE_TS,DELETED_BY,COMPONENT,NAME,XML,USER_ID) +values ('b61d18cbe79a46f3b16deaf4aebb10dd',{ts '2010-03-01 11:14:06.830'},'admin',2,{ts '2010-03-01 11:52:53.170'},'admin',null,null,'[sec$User.browse].genericFilter','Search by role', +' + + + ur.role.id = :component$genericFilter.UrMxpkfMGn32565 + NULL + + +', +'608859871b61424794c7dff348347f93')^ + +/**********************************************************************************************/ + +create table IF NOT EXISTS SYS_SEQUENCE ( + NAME varchar(100) not null, + INCREMENT int unsigned not null default 1, + CURR_VALUE bigint unsigned default 0, + primary key (NAME) +)^ + create unique index IDX_SYS_SEQUENCE_UNIQUE_NAME on SYS_SEQUENCE (NAME)^ \ No newline at end of file diff --git a/modules/core/db/init/postgres/create-db.sql b/modules/core/db/init/postgres/create-db.sql index db2557020b..44f0b6ee69 100644 --- a/modules/core/db/init/postgres/create-db.sql +++ b/modules/core/db/init/postgres/create-db.sql @@ -1,945 +1,945 @@ -create table SYS_SERVER ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(255), - IS_RUNNING boolean, - DATA text, - -- - primary key (ID) -)^ - -create unique index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_CONFIG ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(255), - VALUE text, - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FILE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(500) not null, - EXT varchar(20), - FILE_SIZE bigint, - CREATE_DATE timestamp, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_LOCK_CONFIG ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - NAME varchar(100), - TIMEOUT_SEC integer, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_STATISTICS ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - NAME varchar(50), - INSTANCE_COUNT bigint, - FETCH_UI integer, - MAX_FETCH_UI integer, - LAZY_COLLECTION_THRESHOLD integer, - LOOKUP_SCREEN_THRESHOLD integer, - -- - primary key (ID) -)^ - -create unique index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_TASK ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - DEFINED_BY varchar(1) default 'B', - CLASS_NAME varchar(500), - SCRIPT_NAME varchar(500), - BEAN_NAME varchar(50), - METHOD_NAME varchar(50), - METHOD_PARAMS varchar(1000), - USER_NAME varchar(50), - IS_SINGLETON boolean, - IS_ACTIVE boolean, - PERIOD integer, - TIMEOUT integer, - START_DATE timestamp, - TIME_FRAME integer, - START_DELAY integer, - PERMITTED_SERVERS varchar(4096), - LOG_START boolean, - LOG_FINISH boolean, - LAST_START_TIME timestamp with time zone, - LAST_START_SERVER varchar(512), - DESCRIPTION varchar(1000), - CRON varchar(100), - SCHEDULING_TYPE varchar(1) default 'P', - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SCHEDULED_EXECUTION ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - TASK_ID uuid, - SERVER varchar(512), - START_TIME timestamp with time zone, - FINISH_TIME timestamp with time zone, - RESULT text, - -- - primary key (ID), - constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) -)^ - -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ROLE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - LOC_NAME varchar(255), - DESCRIPTION varchar(1000), - IS_DEFAULT_ROLE boolean, - ROLE_TYPE integer, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME) where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - PARENT_ID uuid, - -- - primary key (ID), - constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ -create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME) where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_GROUP_HIERARCHY ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - GROUP_ID uuid, - PARENT_ID uuid, - HIERARCHY_LEVEL integer, - -- - primary key (ID), - constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), - constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - LOGIN varchar(50) not null, - LOGIN_LC varchar(50) not null, - PASSWORD varchar(255), - NAME varchar(255), - FIRST_NAME varchar(255), - LAST_NAME varchar(255), - MIDDLE_NAME varchar(255), - POSITION_ varchar(255), - EMAIL varchar(100), - LANGUAGE_ varchar(20), - TIME_ZONE varchar(50), - TIME_ZONE_AUTO boolean, - ACTIVE boolean, - GROUP_ID uuid not null, - IP_MASK varchar(200), - CHANGE_PASSWORD_AT_LOGON boolean, - -- - primary key (ID), - constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC) where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_ROLE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - USER_ID uuid, - ROLE_ID uuid, - -- - primary key (ID), - constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID) where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PERMISSION ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - PERMISSION_TYPE integer, - TARGET varchar(100), - VALUE integer, - ROLE_ID uuid, - -- - primary key (ID), - constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) -)^ - -create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET) where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_CONSTRAINT ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CODE varchar(255), - CHECK_TYPE varchar(50) default 'db', - OPERATION_TYPE varchar(50) default 'read', - ENTITY_NAME varchar(255) not null, - JOIN_CLAUSE varchar(500), - WHERE_CLAUSE varchar(1000), - GROOVY_SCRIPT text, - FILTER_XML text, - IS_ACTIVE boolean default true, - GROUP_ID uuid, - -- - primary key (ID), - constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOCALIZED_CONSTRAINT_MSG ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - ENTITY_NAME varchar(255) not null, - OPERATION_TYPE varchar(50) not null, - VALUES_ text, - -- - primary key (ID) -)^ - -create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE - on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE) - where DELETE_TS is null^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_ATTR ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(50), - STR_VALUE varchar(1000), - DATATYPE varchar(20), - GROUP_ID uuid, - -- - primary key (ID), - constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) -)^ - -create index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SETTING ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - USER_ID uuid, - CLIENT_TYPE char(1), - NAME varchar(255), - VALUE text, - -- - primary key (ID), - constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), - constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_USER_SUBSTITUTION ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - USER_ID uuid not null, - SUBSTITUTED_USER_ID uuid not null, - START_DATE timestamp, - END_DATE timestamp, - -- - primary key (ID), - constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SEC_USER_SUBSTITUTION_USER on SEC_USER_SUBSTITUTION (USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ENTITY ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - NAME varchar(100), - AUTO boolean, - MANUAL boolean, - -- - primary key (ID), - constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_LOGGED_ATTR ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ENTITY_ID uuid, - NAME varchar(50), - -- - primary key (ID), - constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), - constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) -)^ - -create index IDX_SEC_LOGGED_ATTR_ENTITY on SEC_LOGGED_ATTR (ENTITY_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_ENTITY_LOG ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - EVENT_TS timestamp, - USER_ID uuid, - CHANGE_TYPE char(1), - ENTITY varchar(100), - ENTITY_ID uuid, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - CHANGES text, - -- - primary key (ID), - constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ -create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_FILTER ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - CODE varchar(200), - XML text, - USER_ID uuid, - -- - primary key (ID), - constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SEC_FILTER_COMPONENT_USER on SEC_FILTER (COMPONENT, USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FOLDER ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - FOLDER_TYPE char(1), - PARENT_ID uuid, - NAME varchar(100), - TAB_NAME varchar(100), - SORT_ORDER integer, - -- - primary key (ID), - constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_APP_FOLDER ( - FOLDER_ID uuid, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - VISIBILITY_SCRIPT text, - QUANTITY_SCRIPT text, - APPLY_DEFAULT boolean, - -- - primary key (FOLDER_ID), - constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_PRESENTATION ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - -- - COMPONENT varchar(200), - NAME varchar(255), - XML varchar(7000), - USER_ID uuid, - IS_AUTO_SAVE boolean, - -- - primary key (ID), - constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) -)^ - -create index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SEARCH_FOLDER ( - FOLDER_ID uuid, - FILTER_COMPONENT varchar(200), - FILTER_XML varchar(7000), - USER_ID uuid, - PRESENTATION_ID uuid, - APPLY_DEFAULT boolean, - IS_SET boolean, - ENTITY_TYPE varchar(50), - -- - primary key (FOLDER_ID), - constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), - constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), - constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) - references SEC_PRESENTATION(ID) - on delete set null -)^ - -create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_FTS_QUEUE ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - ENTITY_ID uuid, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - ENTITY_NAME varchar(200), - CHANGE_TYPE char(1), - SOURCE_HOST varchar(255), - INDEXING_HOST varchar(255), - FAKE boolean, - - primary key (ID) -)^ - -create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SEC_SCREEN_HISTORY ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - USER_ID uuid, - CAPTION varchar(255), - URL TEXT, - ENTITY_ID uuid, - SUBSTITUTED_USER_ID uuid, - -- - primary key (ID), - constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), - constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) -)^ - -create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ -create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ - - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SENDING_MESSAGE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp with time zone, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - ADDRESS_TO text, - ADDRESS_FROM varchar(100), - CAPTION varchar(500), - EMAIL_HEADERS varchar(500), - CONTENT_TEXT text, - CONTENT_TEXT_FILE_ID uuid, - DEADLINE timestamp with time zone, - STATUS int, - DATE_SENT timestamp, - ATTEMPTS_COUNT int, - ATTEMPTS_MADE int, - ATTACHMENTS_NAME text, - -- - primary key (ID), - constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) -)^ - -create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ - -create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ - -create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_SENDING_ATTACHMENT ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - MESSAGE_ID uuid, - CONTENT bytea, - CONTENT_FILE_ID uuid, - CONTENT_ID varchar(50), - NAME varchar(500), - DISPOSITION varchar(50), - TEXT_ENCODING varchar(50), - -- - primary key (ID), - constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), - constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) -)^ - -create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_ENTITY_SNAPSHOT ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ENTITY_META_CLASS varchar(50) not null, - ENTITY_ID uuid, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - AUTHOR_ID uuid not null, - VIEW_XML text not null, - SNAPSHOT_XML text not null, - SNAPSHOT_DATE timestamp not null, - -- - primary key (ID), - constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) -)^ - -create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ -create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_CATEGORY ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NAME varchar(255) not null, - SPECIAL varchar(50), - ENTITY_TYPE varchar(100) not null, - IS_DEFAULT boolean, - DISCRIMINATOR integer, - LOCALE_NAMES varchar(1000), - -- - primary key (ID) -)^ - -create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE) where DELETE_TS is null^ - -------------------------------------------------------------------------------------------------------------- - -create table SYS_CATEGORY_ATTR ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CATEGORY_ENTITY_TYPE varchar(4000), - NAME varchar(255), - CODE varchar(100) not null, - CATEGORY_ID uuid not null, - ENTITY_CLASS varchar(500), - DATA_TYPE varchar(200), - DEFAULT_STRING varchar, - DEFAULT_INT integer, - DEFAULT_DOUBLE numeric, - DEFAULT_DATE timestamp, - DEFAULT_DATE_IS_CURRENT boolean, - DEFAULT_BOOLEAN boolean, - DEFAULT_ENTITY_VALUE uuid, - DEFAULT_STR_ENTITY_VALUE varchar(255), - DEFAULT_INT_ENTITY_VALUE integer, - DEFAULT_LONG_ENTITY_VALUE bigint, - ENUMERATION varchar(500), - ORDER_NO integer, - SCREEN varchar(255), - REQUIRED boolean, - LOOKUP boolean, - TARGET_SCREENS varchar(4000), - WIDTH varchar(20), - ROWS_COUNT integer, - IS_COLLECTION boolean, - JOIN_CLAUSE varchar(4000), - WHERE_CLAUSE varchar(4000), - FILTER_XML text, - LOCALE_NAMES varchar(1000), - ENUMERATION_LOCALES varchar(5000), - -- - primary key (ID), - constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) -)^ - -create index IDX_SYS_CATEGORY_ATTR_CATEGORY on SYS_CATEGORY_ATTR (CATEGORY_ID)^ -create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE) where DELETE_TS is null; -------------------------------------------------------------------------------------------------------------- - -create table SYS_ATTR_VALUE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CATEGORY_ATTR_ID uuid not null, - CODE varchar(100), - ENTITY_ID uuid, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - STRING_VALUE varchar, - INTEGER_VALUE integer, - DOUBLE_VALUE numeric, - DATE_VALUE timestamp, - BOOLEAN_VALUE boolean, - ENTITY_VALUE uuid, - STRING_ENTITY_VALUE varchar(255), - INT_ENTITY_VALUE integer, - LONG_ENTITY_VALUE bigint, - PARENT_ID uuid, - -- - primary key (ID), - constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), - constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) -)^ - -create index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE (ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ -create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ - ------------------------------------------------------------------------------------------------------------- - -create table SYS_JMX_INSTANCE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - NODE_NAME varchar(255), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) -)^ - ------------------------------------------------------------------------------------------------------------- - -create sequence SYS_QUERY_RESULT_SEQ -^ - -create table SYS_QUERY_RESULT ( - ID bigint not null default nextval('SYS_QUERY_RESULT_SEQ'), - SESSION_ID uuid not null, - QUERY_KEY integer not null, - ENTITY_ID uuid, - STRING_ENTITY_ID varchar(255), - INT_ENTITY_ID integer, - LONG_ENTITY_ID bigint, - primary key (ID) -)^ - -create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ -create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ - -create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ - --------------------------------------------------------------------------------------------------------------- - -create table SEC_REMEMBER_ME ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - -- - USER_ID uuid not null, - TOKEN varchar(32) not null, - -- - primary key (ID), - constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) -)^ -create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ -create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ - --------------------------------------------------------------------------------------------------------------- - -create table SYS_REST_API_TOKEN ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - -- - ACCESS_TOKEN_VALUE varchar(255), - ACCESS_TOKEN_BYTES bytea, - AUTHENTICATION_KEY varchar(255), - AUTHENTICATION_BYTES bytea, - EXPIRY timestamp, - USER_LOGIN varchar(50), - -- - primary key (ID) -)^ - --------------------------------------------------------------------------------------------------------------- - -create table SEC_SESSION_LOG ( - ID uuid, - VERSION integer not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - SESSION_ID uuid not null, - USER_ID uuid not null, - SUBSTITUTED_USER_ID uuid, - USER_DATA text, - LAST_ACTION integer not null, - CLIENT_INFO varchar(512), - CLIENT_TYPE varchar(10), - ADDRESS varchar(255), - STARTED_TS timestamp, - FINISHED_TS timestamp, - SERVER_ID varchar(128), - -- - primary key (ID) -)^ - -alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_USER foreign key (USER_ID) references SEC_USER(ID)^ -create index IDX_SEC_SESSION_LOG_USER on SEC_SESSION_LOG (USER_ID)^ -alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID)^ -create index IDX_SEC_SESSION_LOG_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ -create index IDX_SEC_SESSION_LOG_SESSION on SEC_SESSION_LOG (SESSION_ID)^ - --------------------------------------------------------------------------------------------------------------- - --- This function is designed only for convenient generation of UUID identifiers in database creation and updating scripts. --- Do not use it in application. At runtime, all UUID identifiers are generated by the middleware. -create or replace function newid() returns uuid -as 'select md5(random()::text || clock_timestamp()::text)::uuid' -language sql^ - --------------------------------------------------------------------------------------------------------------- - -insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) -values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', now(), 0, 'Company', null)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('60885987-1b61-4247-94c7-dff348347f93', now(), 0, 'admin', 'admin', -'cc2229d1b8a052423d9e1c9ef0113b850086586a', -'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) -values ('a405db59-e674-4f63-8afe-269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, -'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ - -insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) -values ('0c018061-b26f-4de2-a5be-dff348347f93', now(), 0, 'Administrators', 10)^ - -insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) -values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', now(), 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ - -insert into SEC_FILTER (ID, CREATE_TS, CREATED_BY, VERSION, COMPONENT, NAME, XML, USER_ID) -values ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd', now(), 'admin', 0, '[sec$User.browse].genericFilter', 'Search by role', - 'ur.role.id = :component$genericFilter.UrMxpkfMGn32565NULL', - '60885987-1b61-4247-94c7-dff348347f93')^ +create table SYS_SERVER ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(255), + IS_RUNNING boolean, + DATA text, + -- + primary key (ID) +)^ + +create unique index IDX_SYS_SERVER_UNIQ_NAME on SYS_SERVER (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_CONFIG ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(255), + VALUE text, + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CONFIG_UNIQ_NAME on SYS_CONFIG (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FILE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(500) not null, + EXT varchar(20), + FILE_SIZE bigint, + CREATE_DATE timestamp, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_LOCK_CONFIG ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + NAME varchar(100), + TIMEOUT_SEC integer, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_STATISTICS ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + NAME varchar(50), + INSTANCE_COUNT bigint, + FETCH_UI integer, + MAX_FETCH_UI integer, + LAZY_COLLECTION_THRESHOLD integer, + LOOKUP_SCREEN_THRESHOLD integer, + -- + primary key (ID) +)^ + +create unique index IDX_SYS_ENTITY_STATISTICS_UNIQ_NAME on SYS_ENTITY_STATISTICS (NAME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_TASK ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + DEFINED_BY varchar(1) default 'B', + CLASS_NAME varchar(500), + SCRIPT_NAME varchar(500), + BEAN_NAME varchar(50), + METHOD_NAME varchar(50), + METHOD_PARAMS varchar(1000), + USER_NAME varchar(50), + IS_SINGLETON boolean, + IS_ACTIVE boolean, + PERIOD integer, + TIMEOUT integer, + START_DATE timestamp, + TIME_FRAME integer, + START_DELAY integer, + PERMITTED_SERVERS varchar(4096), + LOG_START boolean, + LOG_FINISH boolean, + LAST_START_TIME timestamp with time zone, + LAST_START_SERVER varchar(512), + DESCRIPTION varchar(1000), + CRON varchar(100), + SCHEDULING_TYPE varchar(1) default 'P', + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SCHEDULED_EXECUTION ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + TASK_ID uuid, + SERVER varchar(512), + START_TIME timestamp with time zone, + FINISH_TIME timestamp with time zone, + RESULT text, + -- + primary key (ID), + constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) +)^ + +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_FINISH_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, FINISH_TIME)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ROLE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + LOC_NAME varchar(255), + DESCRIPTION varchar(1000), + IS_DEFAULT_ROLE boolean, + ROLE_TYPE integer, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_ROLE_UNIQ_NAME on SEC_ROLE (NAME) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + PARENT_ID uuid, + -- + primary key (ID), + constraint SEC_GROUP_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ +create unique index IDX_SEC_GROUP_UNIQ_NAME on SEC_GROUP (NAME) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_GROUP_HIERARCHY ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + GROUP_ID uuid, + PARENT_ID uuid, + HIERARCHY_LEVEL integer, + -- + primary key (ID), + constraint SEC_GROUP_HIERARCHY_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID), + constraint SEC_GROUP_HIERARCHY_PARENT foreign key (PARENT_ID) references SEC_GROUP(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + LOGIN varchar(50) not null, + LOGIN_LC varchar(50) not null, + PASSWORD varchar(255), + NAME varchar(255), + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + MIDDLE_NAME varchar(255), + POSITION_ varchar(255), + EMAIL varchar(100), + LANGUAGE_ varchar(20), + TIME_ZONE varchar(50), + TIME_ZONE_AUTO boolean, + ACTIVE boolean, + GROUP_ID uuid not null, + IP_MASK varchar(200), + CHANGE_PASSWORD_AT_LOGON boolean, + -- + primary key (ID), + constraint SEC_USER_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_ROLE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + USER_ID uuid, + ROLE_ID uuid, + -- + primary key (ID), + constraint SEC_USER_ROLE_PROFILE foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_ROLE_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_USER_ROLE_UNIQ_ROLE on SEC_USER_ROLE (USER_ID, ROLE_ID) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PERMISSION ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + PERMISSION_TYPE integer, + TARGET varchar(100), + VALUE integer, + ROLE_ID uuid, + -- + primary key (ID), + constraint SEC_PERMISSION_ROLE foreign key (ROLE_ID) references SEC_ROLE(ID) +)^ + +create unique index IDX_SEC_PERMISSION_UNIQUE on SEC_PERMISSION (ROLE_ID, PERMISSION_TYPE, TARGET) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_CONSTRAINT ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CODE varchar(255), + CHECK_TYPE varchar(50) default 'db', + OPERATION_TYPE varchar(50) default 'read', + ENTITY_NAME varchar(255) not null, + JOIN_CLAUSE varchar(500), + WHERE_CLAUSE varchar(1000), + GROOVY_SCRIPT text, + FILTER_XML text, + IS_ACTIVE boolean default true, + GROUP_ID uuid, + -- + primary key (ID), + constraint SEC_CONSTRAINT_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOCALIZED_CONSTRAINT_MSG ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + ENTITY_NAME varchar(255) not null, + OPERATION_TYPE varchar(50) not null, + VALUES_ text, + -- + primary key (ID) +)^ + +create unique index IDX_SEC_LOC_CNSTRNT_MSG_UNIQUE + on SEC_LOCALIZED_CONSTRAINT_MSG (ENTITY_NAME, OPERATION_TYPE) + where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SESSION_ATTR ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(50), + STR_VALUE varchar(1000), + DATATYPE varchar(20), + GROUP_ID uuid, + -- + primary key (ID), + constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID) +)^ + +create index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SETTING ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + USER_ID uuid, + CLIENT_TYPE char(1), + NAME varchar(255), + VALUE text, + -- + primary key (ID), + constraint SEC_USER_SETTING_USER foreign key (USER_ID) references SEC_USER(ID), + constraint SEC_USER_SETTING_UNIQ unique (USER_ID, NAME, CLIENT_TYPE) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_USER_SUBSTITUTION ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + USER_ID uuid not null, + SUBSTITUTED_USER_ID uuid not null, + START_DATE timestamp, + END_DATE timestamp, + -- + primary key (ID), + constraint FK_SEC_USER_SUBSTITUTION_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_USER_SUBSTITUTION_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SEC_USER_SUBSTITUTION_USER on SEC_USER_SUBSTITUTION (USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ENTITY ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + NAME varchar(100), + AUTO boolean, + MANUAL boolean, + -- + primary key (ID), + constraint SEC_LOGGED_ENTITY_UNIQ_NAME unique (NAME) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_LOGGED_ATTR ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ENTITY_ID uuid, + NAME varchar(50), + -- + primary key (ID), + constraint FK_SEC_LOGGED_ATTR_ENTITY foreign key (ENTITY_ID) references SEC_LOGGED_ENTITY(ID), + constraint SEC_LOGGED_ATTR_UNIQ_NAME unique (ENTITY_ID, NAME) +)^ + +create index IDX_SEC_LOGGED_ATTR_ENTITY on SEC_LOGGED_ATTR (ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_ENTITY_LOG ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + EVENT_TS timestamp, + USER_ID uuid, + CHANGE_TYPE char(1), + ENTITY varchar(100), + ENTITY_ID uuid, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + CHANGES text, + -- + primary key (ID), + constraint FK_SEC_ENTITY_LOG_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SEC_ENTITY_LOG_ENTITY_ID on SEC_ENTITY_LOG (ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_SENTITY_ID on SEC_ENTITY_LOG (STRING_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_IENTITY_ID on SEC_ENTITY_LOG (INT_ENTITY_ID)^ +create index IDX_SEC_ENTITY_LOG_LENTITY_ID on SEC_ENTITY_LOG (LONG_ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_FILTER ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + CODE varchar(200), + XML text, + USER_ID uuid, + -- + primary key (ID), + constraint FK_SEC_FILTER_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SEC_FILTER_COMPONENT_USER on SEC_FILTER (COMPONENT, USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FOLDER ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + FOLDER_TYPE char(1), + PARENT_ID uuid, + NAME varchar(100), + TAB_NAME varchar(100), + SORT_ORDER integer, + -- + primary key (ID), + constraint FK_SYS_FOLDER_PARENT foreign key (PARENT_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_APP_FOLDER ( + FOLDER_ID uuid, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + VISIBILITY_SCRIPT text, + QUANTITY_SCRIPT text, + APPLY_DEFAULT boolean, + -- + primary key (FOLDER_ID), + constraint FK_SYS_APP_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_PRESENTATION ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + -- + COMPONENT varchar(200), + NAME varchar(255), + XML varchar(7000), + USER_ID uuid, + IS_AUTO_SAVE boolean, + -- + primary key (ID), + constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID) +)^ + +create index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SEARCH_FOLDER ( + FOLDER_ID uuid, + FILTER_COMPONENT varchar(200), + FILTER_XML varchar(7000), + USER_ID uuid, + PRESENTATION_ID uuid, + APPLY_DEFAULT boolean, + IS_SET boolean, + ENTITY_TYPE varchar(50), + -- + primary key (FOLDER_ID), + constraint FK_SEC_SEARCH_FOLDER_FOLDER foreign key (FOLDER_ID) references SYS_FOLDER(ID), + constraint FK_SEC_SEARCH_FOLDER_USER foreign key (USER_ID) references SEC_USER(ID), + constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) + references SEC_PRESENTATION(ID) + on delete set null +)^ + +create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_FTS_QUEUE ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + ENTITY_ID uuid, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + ENTITY_NAME varchar(200), + CHANGE_TYPE char(1), + SOURCE_HOST varchar(255), + INDEXING_HOST varchar(255), + FAKE boolean, + + primary key (ID) +)^ + +create index IDX_SYS_FTS_QUEUE_IDXHOST_CRTS on SYS_FTS_QUEUE (INDEXING_HOST, CREATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SEC_SCREEN_HISTORY ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + USER_ID uuid, + CAPTION varchar(255), + URL TEXT, + ENTITY_ID uuid, + SUBSTITUTED_USER_ID uuid, + -- + primary key (ID), + constraint FK_SEC_HISTORY_USER foreign key (USER_ID) references SEC_USER (ID), + constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID) +)^ + +create index IDX_SEC_SCREEN_HISTORY_USER on SEC_SCREEN_HISTORY (USER_ID)^ +create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID)^ + + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_MESSAGE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp with time zone, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + ADDRESS_TO text, + ADDRESS_FROM varchar(100), + CAPTION varchar(500), + EMAIL_HEADERS varchar(500), + CONTENT_TEXT text, + CONTENT_TEXT_FILE_ID uuid, + DEADLINE timestamp with time zone, + STATUS int, + DATE_SENT timestamp, + ATTEMPTS_COUNT int, + ATTEMPTS_MADE int, + ATTACHMENTS_NAME text, + -- + primary key (ID), + constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID) +)^ + +create index IDX_SYS_SENDING_MESSAGE_STATUS on SYS_SENDING_MESSAGE (STATUS)^ + +create index IDX_SYS_SENDING_MESSAGE_DATE_SENT on SYS_SENDING_MESSAGE (DATE_SENT)^ + +create index IDX_SYS_SENDING_MESSAGE_UPDATE_TS on SYS_SENDING_MESSAGE (UPDATE_TS)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_SENDING_ATTACHMENT ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + MESSAGE_ID uuid, + CONTENT bytea, + CONTENT_FILE_ID uuid, + CONTENT_ID varchar(50), + NAME varchar(500), + DISPOSITION varchar(50), + TEXT_ENCODING varchar(50), + -- + primary key (ID), + constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID), + constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE foreign key (CONTENT_FILE_ID) references SYS_FILE (ID) +)^ + +create index SYS_SENDING_ATTACHMENT_MESSAGE_IDX on SYS_SENDING_ATTACHMENT (MESSAGE_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_ENTITY_SNAPSHOT ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ENTITY_META_CLASS varchar(50) not null, + ENTITY_ID uuid, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + AUTHOR_ID uuid not null, + VIEW_XML text not null, + SNAPSHOT_XML text not null, + SNAPSHOT_DATE timestamp not null, + -- + primary key (ID), + constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID) +)^ + +create index IDX_SYS_ENTITY_SNAPSHOT_ENTITY_ID on SYS_ENTITY_SNAPSHOT (ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_SENTITY_ID on SYS_ENTITY_SNAPSHOT (STRING_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_IENTITY_ID on SYS_ENTITY_SNAPSHOT (INT_ENTITY_ID)^ +create index IDX_SYS_ENTITY_SNAPSHOT_LENTITY_ID on SYS_ENTITY_SNAPSHOT (LONG_ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_CATEGORY ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NAME varchar(255) not null, + SPECIAL varchar(50), + ENTITY_TYPE varchar(100) not null, + IS_DEFAULT boolean, + DISCRIMINATOR integer, + LOCALE_NAMES varchar(1000), + -- + primary key (ID) +)^ + +create unique index IDX_SYS_CATEGORY_UNIQ_NAME_ENTITY_TYPE on SYS_CATEGORY (NAME, ENTITY_TYPE) where DELETE_TS is null^ + +------------------------------------------------------------------------------------------------------------- + +create table SYS_CATEGORY_ATTR ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CATEGORY_ENTITY_TYPE varchar(4000), + NAME varchar(255), + CODE varchar(100) not null, + CATEGORY_ID uuid not null, + ENTITY_CLASS varchar(500), + DATA_TYPE varchar(200), + DEFAULT_STRING varchar, + DEFAULT_INT integer, + DEFAULT_DOUBLE numeric, + DEFAULT_DATE timestamp, + DEFAULT_DATE_IS_CURRENT boolean, + DEFAULT_BOOLEAN boolean, + DEFAULT_ENTITY_VALUE uuid, + DEFAULT_STR_ENTITY_VALUE varchar(255), + DEFAULT_INT_ENTITY_VALUE integer, + DEFAULT_LONG_ENTITY_VALUE bigint, + ENUMERATION varchar(500), + ORDER_NO integer, + SCREEN varchar(255), + REQUIRED boolean, + LOOKUP boolean, + TARGET_SCREENS varchar(4000), + WIDTH varchar(20), + ROWS_COUNT integer, + IS_COLLECTION boolean, + JOIN_CLAUSE varchar(4000), + WHERE_CLAUSE varchar(4000), + FILTER_XML text, + LOCALE_NAMES varchar(1000), + ENUMERATION_LOCALES varchar(5000), + -- + primary key (ID), + constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID) +)^ + +create index IDX_SYS_CATEGORY_ATTR_CATEGORY on SYS_CATEGORY_ATTR (CATEGORY_ID)^ +create unique index IDX_CAT_ATTR_ENT_TYPE_AND_CODE on SYS_CATEGORY_ATTR (CATEGORY_ENTITY_TYPE, CODE) where DELETE_TS is null; +------------------------------------------------------------------------------------------------------------- + +create table SYS_ATTR_VALUE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CATEGORY_ATTR_ID uuid not null, + CODE varchar(100), + ENTITY_ID uuid, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + STRING_VALUE varchar, + INTEGER_VALUE integer, + DOUBLE_VALUE numeric, + DATE_VALUE timestamp, + BOOLEAN_VALUE boolean, + ENTITY_VALUE uuid, + STRING_ENTITY_VALUE varchar(255), + INT_ENTITY_VALUE integer, + LONG_ENTITY_VALUE bigint, + PARENT_ID uuid, + -- + primary key (ID), + constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID), + constraint SYS_ATTR_VALUE_ATTR_VALUE_PARENT_ID foreign key (PARENT_ID) references SYS_ATTR_VALUE(ID) +)^ + +create index IDX_SYS_ATTR_VALUE_ENTITY on SYS_ATTR_VALUE (ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_SENTITY on SYS_ATTR_VALUE(STRING_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_IENTITY on SYS_ATTR_VALUE(INT_ENTITY_ID)^ +create index IDX_SYS_ATTR_VALUE_LENTITY on SYS_ATTR_VALUE(LONG_ENTITY_ID)^ + +------------------------------------------------------------------------------------------------------------ + +create table SYS_JMX_INSTANCE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + NODE_NAME varchar(255), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) +)^ + +------------------------------------------------------------------------------------------------------------ + +create sequence SYS_QUERY_RESULT_SEQ +^ + +create table SYS_QUERY_RESULT ( + ID bigint not null default nextval('SYS_QUERY_RESULT_SEQ'), + SESSION_ID uuid not null, + QUERY_KEY integer not null, + ENTITY_ID uuid, + STRING_ENTITY_ID varchar(255), + INT_ENTITY_ID integer, + LONG_ENTITY_ID bigint, + primary key (ID) +)^ + +create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_SENTITY_SESSION_KEY on SYS_QUERY_RESULT (STRING_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_IENTITY_SESSION_KEY on SYS_QUERY_RESULT (INT_ENTITY_ID, SESSION_ID, QUERY_KEY)^ +create index IDX_SYS_QUERY_RESULT_LENTITY_SESSION_KEY on SYS_QUERY_RESULT (LONG_ENTITY_ID, SESSION_ID, QUERY_KEY)^ + +create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SEC_REMEMBER_ME ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + -- + USER_ID uuid not null, + TOKEN varchar(32) not null, + -- + primary key (ID), + constraint FK_SEC_REMEMBER_ME_USER foreign key (USER_ID) references SEC_USER(ID) +)^ +create index IDX_SEC_REMEMBER_ME_USER on SEC_REMEMBER_ME(USER_ID)^ +create index IDX_SEC_REMEMBER_ME_TOKEN on SEC_REMEMBER_ME(TOKEN)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SYS_REST_API_TOKEN ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + -- + ACCESS_TOKEN_VALUE varchar(255), + ACCESS_TOKEN_BYTES bytea, + AUTHENTICATION_KEY varchar(255), + AUTHENTICATION_BYTES bytea, + EXPIRY timestamp, + USER_LOGIN varchar(50), + -- + primary key (ID) +)^ + +-------------------------------------------------------------------------------------------------------------- + +create table SEC_SESSION_LOG ( + ID uuid, + VERSION integer not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + SESSION_ID uuid not null, + USER_ID uuid not null, + SUBSTITUTED_USER_ID uuid, + USER_DATA text, + LAST_ACTION integer not null, + CLIENT_INFO varchar(512), + CLIENT_TYPE varchar(10), + ADDRESS varchar(255), + STARTED_TS timestamp, + FINISHED_TS timestamp, + SERVER_ID varchar(128), + -- + primary key (ID) +)^ + +alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_USER foreign key (USER_ID) references SEC_USER(ID)^ +create index IDX_SEC_SESSION_LOG_USER on SEC_SESSION_LOG (USER_ID)^ +alter table SEC_SESSION_LOG add constraint FK_SEC_SESSION_LOG_SUBUSER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID)^ +create index IDX_SEC_SESSION_LOG_SUBUSER on SEC_SESSION_LOG (SUBSTITUTED_USER_ID)^ +create index IDX_SEC_SESSION_LOG_SESSION on SEC_SESSION_LOG (SESSION_ID)^ + +-------------------------------------------------------------------------------------------------------------- + +-- This function is designed only for convenient generation of UUID identifiers in database creation and updating scripts. +-- Do not use it in application. At runtime, all UUID identifiers are generated by the middleware. +create or replace function newid() returns uuid +as 'select md5(random()::text || clock_timestamp()::text)::uuid' +language sql^ + +-------------------------------------------------------------------------------------------------------------- + +insert into SEC_GROUP (ID, CREATE_TS, VERSION, NAME, PARENT_ID) +values ('0fa2b1a5-1d68-4d69-9fbd-dff348347f93', now(), 0, 'Company', null)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('60885987-1b61-4247-94c7-dff348347f93', now(), 0, 'admin', 'admin', +'cc2229d1b8a052423d9e1c9ef0113b850086586a', +'Administrator', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) +values ('a405db59-e674-4f63-8afe-269dda788fe8', now(), 0, 'anonymous', 'anonymous', null, +'Anonymous', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ + +insert into SEC_ROLE (ID, CREATE_TS, VERSION, NAME, ROLE_TYPE) +values ('0c018061-b26f-4de2-a5be-dff348347f93', now(), 0, 'Administrators', 10)^ + +insert into SEC_USER_ROLE (ID, CREATE_TS, VERSION, USER_ID, ROLE_ID) +values ('c838be0a-96d0-4ef4-a7c0-dff348347f93', now(), 0, '60885987-1b61-4247-94c7-dff348347f93', '0c018061-b26f-4de2-a5be-dff348347f93')^ + +insert into SEC_FILTER (ID, CREATE_TS, CREATED_BY, VERSION, COMPONENT, NAME, XML, USER_ID) +values ('b61d18cb-e79a-46f3-b16d-eaf4aebb10dd', now(), 'admin', 0, '[sec$User.browse].genericFilter', 'Search by role', + 'ur.role.id = :component$genericFilter.UrMxpkfMGn32565NULL', + '60885987-1b61-4247-94c7-dff348347f93')^ diff --git a/modules/core/db/init/postgres/functions.sql b/modules/core/db/init/postgres/functions.sql index 5c7ef58c66..7d5c74cb79 100644 --- a/modules/core/db/init/postgres/functions.sql +++ b/modules/core/db/init/postgres/functions.sql @@ -1,19 +1,19 @@ --- Useful SQL functions ------------------------------------------------------------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION FirstDateOfMonth(date) RETURNS date AS ' -SELECT CAST(date_trunc(''month'', $1) as date); -' LANGUAGE sql^ - -CREATE OR REPLACE FUNCTION LastDateOfMonth(date) RETURNS date AS ' -SELECT CAST(date_trunc(''month'', $1) + interval ''1 month'' -- interval ''1 day'' as date); -' LANGUAGE sql^ - ---This function allows to concat text columns -CREATE AGGREGATE concat ( - BASETYPE = text, - SFUNC = textcat, - STYPE = text, - INITCOND = '' -)^ +-- Useful SQL functions +------------------------------------------------------------------------------------------------------------------------ +CREATE OR REPLACE FUNCTION FirstDateOfMonth(date) RETURNS date AS ' +SELECT CAST(date_trunc(''month'', $1) as date); +' LANGUAGE sql^ + +CREATE OR REPLACE FUNCTION LastDateOfMonth(date) RETURNS date AS ' +SELECT CAST(date_trunc(''month'', $1) + interval ''1 month'' +- interval ''1 day'' as date); +' LANGUAGE sql^ + +--This function allows to concat text columns +CREATE AGGREGATE concat ( + BASETYPE = text, + SFUNC = textcat, + STYPE = text, + INITCOND = '' +)^ ------------------------------------------------------------------------------------------------------------------------ \ No newline at end of file diff --git a/modules/core/db/run-hsqldb.bat b/modules/core/db/run-hsqldb.bat index 5139dbad29..2256429597 100644 --- a/modules/core/db/run-hsqldb.bat +++ b/modules/core/db/run-hsqldb.bat @@ -1,2 +1,2 @@ -java -cp %1 org.hsqldb.server.Server --database.0 file:%2 --dbname.0 %2 -exit +java -cp %1 org.hsqldb.server.Server --database.0 file:%2 --dbname.0 %2 +exit diff --git a/modules/core/db/update/hsql/15/150203-sendingMessageEmailHeaders.sql b/modules/core/db/update/hsql/15/150203-sendingMessageEmailHeaders.sql index f22d55088c..c735e66084 100644 --- a/modules/core/db/update/hsql/15/150203-sendingMessageEmailHeaders.sql +++ b/modules/core/db/update/hsql/15/150203-sendingMessageEmailHeaders.sql @@ -1,3 +1,3 @@ --- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS - +-- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS + alter table SYS_SENDING_MESSAGE add EMAIL_HEADERS varchar(500)^ \ No newline at end of file diff --git a/modules/core/db/update/hsql/15/150205-addSubstituteUserInScreenHistory.sql b/modules/core/db/update/hsql/15/150205-addSubstituteUserInScreenHistory.sql index 63c46e7436..0134b71dcf 100644 --- a/modules/core/db/update/hsql/15/150205-addSubstituteUserInScreenHistory.sql +++ b/modules/core/db/update/hsql/15/150205-addSubstituteUserInScreenHistory.sql @@ -1,4 +1,4 @@ --- Description: - -alter table sec_screen_history add substituted_user_id varchar(36)^ +-- Description: + +alter table sec_screen_history add substituted_user_id varchar(36)^ alter table sec_screen_history add constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID)^ \ No newline at end of file diff --git a/modules/core/db/update/hsql/15/150226-addIndexInScreenHistory.sql b/modules/core/db/update/hsql/15/150226-addIndexInScreenHistory.sql index cfd2b6509c..858531e8a8 100644 --- a/modules/core/db/update/hsql/15/150226-addIndexInScreenHistory.sql +++ b/modules/core/db/update/hsql/15/150226-addIndexInScreenHistory.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID); \ No newline at end of file diff --git a/modules/core/db/update/hsql/15/150805-fakeFtsQueue.sql b/modules/core/db/update/hsql/15/150805-fakeFtsQueue.sql index 6beb0fb0d7..e7da4be51a 100644 --- a/modules/core/db/update/hsql/15/150805-fakeFtsQueue.sql +++ b/modules/core/db/update/hsql/15/150805-fakeFtsQueue.sql @@ -1 +1 @@ -alter table SYS_FTS_QUEUE add FAKE boolean^ +alter table SYS_FTS_QUEUE add FAKE boolean^ diff --git a/modules/core/db/update/hsql/15/151116-rowLevelSecurity.sql b/modules/core/db/update/hsql/15/151116-rowLevelSecurity.sql index b26f97ae16..2c38fce3f8 100644 --- a/modules/core/db/update/hsql/15/151116-rowLevelSecurity.sql +++ b/modules/core/db/update/hsql/15/151116-rowLevelSecurity.sql @@ -1,7 +1,7 @@ -alter table sec_constraint add column CODE varchar(255)^ -alter table sec_constraint add column CHECK_TYPE varchar(50) default 'db'^ -alter table sec_constraint add column OPERATION_TYPE varchar(50) default 'read'^ -alter table sec_constraint add column GROOVY_SCRIPT varchar(500)^ -alter table sec_constraint add column FILTER_XML varchar(1000)^ -update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ -update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ +alter table sec_constraint add column CODE varchar(255)^ +alter table sec_constraint add column CHECK_TYPE varchar(50) default 'db'^ +alter table sec_constraint add column OPERATION_TYPE varchar(50) default 'read'^ +alter table sec_constraint add column GROOVY_SCRIPT varchar(500)^ +alter table sec_constraint add column FILTER_XML varchar(1000)^ +update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ +update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ diff --git a/modules/core/db/update/hsql/15/151228-sendingMessagesExtendFields.sql b/modules/core/db/update/hsql/15/151228-sendingMessagesExtendFields.sql index b0bf4d6f2f..b6884ea2ab 100644 --- a/modules/core/db/update/hsql/15/151228-sendingMessagesExtendFields.sql +++ b/modules/core/db/update/hsql/15/151228-sendingMessagesExtendFields.sql @@ -1,3 +1,3 @@ -alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO longvarchar^ -alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME longvarchar^ - +alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO longvarchar^ +alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME longvarchar^ + diff --git a/modules/core/db/update/hsql/15/1512282-addIsActiveToConstraint.sql b/modules/core/db/update/hsql/15/1512282-addIsActiveToConstraint.sql index 291bfb411f..54d80067ac 100644 --- a/modules/core/db/update/hsql/15/1512282-addIsActiveToConstraint.sql +++ b/modules/core/db/update/hsql/15/1512282-addIsActiveToConstraint.sql @@ -1,2 +1,2 @@ -alter table SEC_CONSTRAINT add IS_ACTIVE boolean default true^ - +alter table SEC_CONSTRAINT add IS_ACTIVE boolean default true^ + diff --git a/modules/core/db/update/mssql/02/02-100-entitySnapshotAuthor.sql b/modules/core/db/update/mssql/02/02-100-entitySnapshotAuthor.sql index 87d9a93927..ec3f2c179e 100644 --- a/modules/core/db/update/mssql/02/02-100-entitySnapshotAuthor.sql +++ b/modules/core/db/update/mssql/02/02-100-entitySnapshotAuthor.sql @@ -1,6 +1,6 @@ --- Description: core$EntitySnapshot.author attribute added - -alter table SYS_ENTITY_SNAPSHOT add AUTHOR_ID uniqueidentifier^ - -alter table SYS_ENTITY_SNAPSHOT +-- Description: core$EntitySnapshot.author attribute added + +alter table SYS_ENTITY_SNAPSHOT add AUTHOR_ID uniqueidentifier^ + +alter table SYS_ENTITY_SNAPSHOT add constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID)^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/02/02-110-addUserDescriminator.sql b/modules/core/db/update/mssql/02/02-110-addUserDescriminator.sql index a7de81fb77..95f38e0a94 100644 --- a/modules/core/db/update/mssql/02/02-110-addUserDescriminator.sql +++ b/modules/core/db/update/mssql/02/02-110-addUserDescriminator.sql @@ -1,4 +1,4 @@ - -alter table SEC_USER add TYPE varchar(1)^ - + +alter table SEC_USER add TYPE varchar(1)^ + update SEC_USER set TYPE = 'C'^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/02/02-130-queryResults.sql b/modules/core/db/update/mssql/02/02-130-queryResults.sql index 085e037373..c56da4ed6b 100644 --- a/modules/core/db/update/mssql/02/02-130-queryResults.sql +++ b/modules/core/db/update/mssql/02/02-130-queryResults.sql @@ -1,13 +1,13 @@ --- Description: DDL for QueryResult entity - -create table SYS_QUERY_RESULT ( - ID bigint identity not null, - SESSION_ID uniqueidentifier not null, - QUERY_KEY integer not null, - ENTITY_ID uniqueidentifier, - primary key (ID) -)^ - -create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ - -create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ +-- Description: DDL for QueryResult entity + +create table SYS_QUERY_RESULT ( + ID bigint identity not null, + SESSION_ID uniqueidentifier not null, + QUERY_KEY integer not null, + ENTITY_ID uniqueidentifier, + primary key (ID) +)^ + +create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ + +create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ diff --git a/modules/core/db/update/mssql/02/02-140-entityLogChanges.sql b/modules/core/db/update/mssql/02/02-140-entityLogChanges.sql index 6811d25e7c..2b94a95cd2 100644 --- a/modules/core/db/update/mssql/02/02-140-entityLogChanges.sql +++ b/modules/core/db/update/mssql/02/02-140-entityLogChanges.sql @@ -1,3 +1,3 @@ --- Description: add SEC_ENTITY_LOG.CHANGES - -alter table SEC_ENTITY_LOG add CHANGES varchar(max); +-- Description: add SEC_ENTITY_LOG.CHANGES + +alter table SEC_ENTITY_LOG add CHANGES varchar(max); diff --git a/modules/core/db/update/mssql/02/02-150-alterSysScheduledTask.sql b/modules/core/db/update/mssql/02/02-150-alterSysScheduledTask.sql index 436d405a78..4962ff4772 100644 --- a/modules/core/db/update/mssql/02/02-150-alterSysScheduledTask.sql +++ b/modules/core/db/update/mssql/02/02-150-alterSysScheduledTask.sql @@ -1,4 +1,4 @@ - -alter table SYS_SCHEDULED_TASK add METHOD_PARAMS varchar(1000); -drop index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK; + +alter table SYS_SCHEDULED_TASK add METHOD_PARAMS varchar(1000); +drop index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK; create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME, METHOD_PARAMS, DELETE_TS); \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121002-updateScreenPermissions.sql b/modules/core/db/update/mssql/12/121002-updateScreenPermissions.sql index b0aa55b376..f4dd46a760 100644 --- a/modules/core/db/update/mssql/12/121002-updateScreenPermissions.sql +++ b/modules/core/db/update/mssql/12/121002-updateScreenPermissions.sql @@ -1,3 +1,3 @@ --- Description: update screen permissions according to #1532 - -update sec_permission set target = substring(target, 3, len(target) - 2) where type = 10; +-- Description: update screen permissions according to #1532 + +update sec_permission set target = substring(target, 3, len(target) - 2) where type = 10; diff --git a/modules/core/db/update/mssql/12/121003-addCodeToCategoryAttribute.sql b/modules/core/db/update/mssql/12/121003-addCodeToCategoryAttribute.sql index e20a9dc301..59a9d7b9cd 100644 --- a/modules/core/db/update/mssql/12/121003-addCodeToCategoryAttribute.sql +++ b/modules/core/db/update/mssql/12/121003-addCodeToCategoryAttribute.sql @@ -1,3 +1,3 @@ --- Description: add code field to CategoryAttribute - +-- Description: add code field to CategoryAttribute + alter table SYS_CATEGORY_ATTR add CODE varchar(50); \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121004-addFieldsToScheduledTasks.sql b/modules/core/db/update/mssql/12/121004-addFieldsToScheduledTasks.sql index 5ff1a0e7ce..856716d3d5 100644 --- a/modules/core/db/update/mssql/12/121004-addFieldsToScheduledTasks.sql +++ b/modules/core/db/update/mssql/12/121004-addFieldsToScheduledTasks.sql @@ -1,9 +1,9 @@ --- Description: add defined by, class name and script name fields to scheduled task --- also update all existing tasks to beans - -if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%02-120-alterScheduledTask.sql') -begin - alter table SYS_SCHEDULED_TASK add DEFINED_BY varchar(1) default 'B'; - alter table SYS_SCHEDULED_TASK add CLASS_NAME varchar(500); - alter table SYS_SCHEDULED_TASK add SCRIPT_NAME varchar(500); -end +-- Description: add defined by, class name and script name fields to scheduled task +-- also update all existing tasks to beans + +if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%02-120-alterScheduledTask.sql') +begin + alter table SYS_SCHEDULED_TASK add DEFINED_BY varchar(1) default 'B'; + alter table SYS_SCHEDULED_TASK add CLASS_NAME varchar(500); + alter table SYS_SCHEDULED_TASK add SCRIPT_NAME varchar(500); +end diff --git a/modules/core/db/update/mssql/12/121020-addLoginConstraintsForUser.sql b/modules/core/db/update/mssql/12/121020-addLoginConstraintsForUser.sql index ea1fb3546f..0d252ca957 100644 --- a/modules/core/db/update/mssql/12/121020-addLoginConstraintsForUser.sql +++ b/modules/core/db/update/mssql/12/121020-addLoginConstraintsForUser.sql @@ -1,16 +1,16 @@ --- Description: add not null constraint on LOGIN and LOGIN_LC for SEC_USER - -update SEC_USER -set LOGIN = cast(ID as varchar(50)), LOGIN_LC = cast(ID as varchar(50)) -where (LOGIN is null) or (LOGIN_LC is null)^ - -alter table SEC_USER alter column LOGIN varchar(50) not null^ - -drop index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER^ -drop index IDX_SEC_USER_LOGIN on SEC_USER^ - -alter table SEC_USER alter column LOGIN_LC varchar(50) not null^ - -create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS)^ - +-- Description: add not null constraint on LOGIN and LOGIN_LC for SEC_USER + +update SEC_USER +set LOGIN = cast(ID as varchar(50)), LOGIN_LC = cast(ID as varchar(50)) +where (LOGIN is null) or (LOGIN_LC is null)^ + +alter table SEC_USER alter column LOGIN varchar(50) not null^ + +drop index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER^ +drop index IDX_SEC_USER_LOGIN on SEC_USER^ + +alter table SEC_USER alter column LOGIN_LC varchar(50) not null^ + +create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC, DELETE_TS)^ + create clustered index IDX_SEC_USER_LOGIN on SEC_USER (LOGIN_LC)^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121024-addEncryptionParamsToUser.sql b/modules/core/db/update/mssql/12/121024-addEncryptionParamsToUser.sql index b26e38644b..682c166b12 100644 --- a/modules/core/db/update/mssql/12/121024-addEncryptionParamsToUser.sql +++ b/modules/core/db/update/mssql/12/121024-addEncryptionParamsToUser.sql @@ -1,7 +1,7 @@ --- Description: add SALT, HASH_METHOD, CHANGE_PASSWORD_AT_LOGON fields - -alter table SEC_USER alter column PASSWORD varchar(40)^ - -alter table SEC_USER add CHANGE_PASSWORD_AT_LOGON tinyint^ - +-- Description: add SALT, HASH_METHOD, CHANGE_PASSWORD_AT_LOGON fields + +alter table SEC_USER alter column PASSWORD varchar(40)^ + +alter table SEC_USER add CHANGE_PASSWORD_AT_LOGON tinyint^ + alter table SEC_USER add SALT varchar(16)^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121031-dropPasswordColumnFromScheduledTask.sql b/modules/core/db/update/mssql/12/121031-dropPasswordColumnFromScheduledTask.sql index 0739ae0ea1..d96fce690b 100644 --- a/modules/core/db/update/mssql/12/121031-dropPasswordColumnFromScheduledTask.sql +++ b/modules/core/db/update/mssql/12/121031-dropPasswordColumnFromScheduledTask.sql @@ -1,3 +1,3 @@ --- Description: drop USER_PASSWORD column from SYS_SCHEDULED_TASK - +-- Description: drop USER_PASSWORD column from SYS_SCHEDULED_TASK + alter table SYS_SCHEDULED_TASK drop column USER_PASSWORD^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121102-dropSaltColumn.sql b/modules/core/db/update/mssql/12/121102-dropSaltColumn.sql index 3de03fae4c..d3c2a09a0e 100644 --- a/modules/core/db/update/mssql/12/121102-dropSaltColumn.sql +++ b/modules/core/db/update/mssql/12/121102-dropSaltColumn.sql @@ -1,3 +1,3 @@ --- Description: drop SALT column in SEC_USER - +-- Description: drop SALT column in SEC_USER + alter table SEC_USER drop column SALT^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121114-addDescriptionToScheduledTask.sql b/modules/core/db/update/mssql/12/121114-addDescriptionToScheduledTask.sql index 5fb960fb93..6d616a6ce1 100644 --- a/modules/core/db/update/mssql/12/121114-addDescriptionToScheduledTask.sql +++ b/modules/core/db/update/mssql/12/121114-addDescriptionToScheduledTask.sql @@ -1,2 +1,2 @@ - + alter table SYS_SCHEDULED_TASK add DESCRIPTION varchar(1000); \ No newline at end of file diff --git a/modules/core/db/update/mssql/12/121228-addJmxInstance.sql b/modules/core/db/update/mssql/12/121228-addJmxInstance.sql index 8f5fd942e8..38766ebc3b 100644 --- a/modules/core/db/update/mssql/12/121228-addJmxInstance.sql +++ b/modules/core/db/update/mssql/12/121228-addJmxInstance.sql @@ -1,20 +1,20 @@ --- Description: add SYS_JMX_INSTANCE table - -create table SYS_JMX_INSTANCE ( - ID uniqueidentifier not null, - CREATE_TS datetime, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS datetime, - UPDATED_BY varchar(50), - DELETE_TS datetime, - DELETED_BY varchar(50), - -- - CLUSTER_NODE_NAME varchar(255), - DESCRIPTION varchar(500), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) +-- Description: add SYS_JMX_INSTANCE table + +create table SYS_JMX_INSTANCE ( + ID uniqueidentifier not null, + CREATE_TS datetime, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS datetime, + UPDATED_BY varchar(50), + DELETE_TS datetime, + DELETED_BY varchar(50), + -- + CLUSTER_NODE_NAME varchar(255), + DESCRIPTION varchar(500), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) )^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/13/130110-removeJmxInstanceDescription.sql b/modules/core/db/update/mssql/13/130110-removeJmxInstanceDescription.sql index 6b4816417b..c4e6eb5345 100644 --- a/modules/core/db/update/mssql/13/130110-removeJmxInstanceDescription.sql +++ b/modules/core/db/update/mssql/13/130110-removeJmxInstanceDescription.sql @@ -1,8 +1,8 @@ --- Description: remove column DESCRIPTION from SYS_JMX_INSTANCE table - -if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%131001-removeJmxInstanceDescription.sql') -begin - alter table SYS_JMX_INSTANCE drop column DESCRIPTION; - - exec sp_rename 'SYS_JMX_INSTANCE.CLUSTER_NODE_NAME', 'NODE_NAME', 'COLUMN'; +-- Description: remove column DESCRIPTION from SYS_JMX_INSTANCE table + +if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%131001-removeJmxInstanceDescription.sql') +begin + alter table SYS_JMX_INSTANCE drop column DESCRIPTION; + + exec sp_rename 'SYS_JMX_INSTANCE.CLUSTER_NODE_NAME', 'NODE_NAME', 'COLUMN'; end \ No newline at end of file diff --git a/modules/core/db/update/mssql/13/130918-email-attachment-options.sql b/modules/core/db/update/mssql/13/130918-email-attachment-options.sql index 182eb8982e..0397a6d905 100644 --- a/modules/core/db/update/mssql/13/130918-email-attachment-options.sql +++ b/modules/core/db/update/mssql/13/130918-email-attachment-options.sql @@ -1,9 +1,9 @@ --- Add columns to store email attachment disposition and encoding - -alter table SYS_SENDING_ATTACHMENT add VERSION integer; -alter table SYS_SENDING_ATTACHMENT add UPDATE_TS datetime; -alter table SYS_SENDING_ATTACHMENT add UPDATED_BY varchar(50); -alter table SYS_SENDING_ATTACHMENT add DELETE_TS datetime; -alter table SYS_SENDING_ATTACHMENT add DELETED_BY varchar(50); -alter table SYS_SENDING_ATTACHMENT add DISPOSITION varchar(50); -alter table SYS_SENDING_ATTACHMENT add TEXT_ENCODING varchar(50); +-- Add columns to store email attachment disposition and encoding + +alter table SYS_SENDING_ATTACHMENT add VERSION integer; +alter table SYS_SENDING_ATTACHMENT add UPDATE_TS datetime; +alter table SYS_SENDING_ATTACHMENT add UPDATED_BY varchar(50); +alter table SYS_SENDING_ATTACHMENT add DELETE_TS datetime; +alter table SYS_SENDING_ATTACHMENT add DELETED_BY varchar(50); +alter table SYS_SENDING_ATTACHMENT add DISPOSITION varchar(50); +alter table SYS_SENDING_ATTACHMENT add TEXT_ENCODING varchar(50); diff --git a/modules/core/db/update/mssql/13/130920-email-file-storage.sql b/modules/core/db/update/mssql/13/130920-email-file-storage.sql index c3ac1ca927..6045ccb8bc 100644 --- a/modules/core/db/update/mssql/13/130920-email-file-storage.sql +++ b/modules/core/db/update/mssql/13/130920-email-file-storage.sql @@ -1,9 +1,9 @@ --- Add linking columns from SendingMessage and SendingAttachment to sys$File - -alter table SYS_SENDING_MESSAGE add CONTENT_TEXT_FILE_ID uniqueidentifier^ -alter table SYS_SENDING_MESSAGE add constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE -foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID)^ - -alter table SYS_SENDING_ATTACHMENT add CONTENT_FILE_ID uniqueidentifier^ -alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE -foreign key (CONTENT_FILE_ID) references SYS_FILE (ID)^ +-- Add linking columns from SendingMessage and SendingAttachment to sys$File + +alter table SYS_SENDING_MESSAGE add CONTENT_TEXT_FILE_ID uniqueidentifier^ +alter table SYS_SENDING_MESSAGE add constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE +foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID)^ + +alter table SYS_SENDING_ATTACHMENT add CONTENT_FILE_ID uniqueidentifier^ +alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE +foreign key (CONTENT_FILE_ID) references SYS_FILE (ID)^ diff --git a/modules/core/db/update/mssql/13/130923-permissionsToRenamedScreens.sql b/modules/core/db/update/mssql/13/130923-permissionsToRenamedScreens.sql index f12cb3279d..efb62bc520 100644 --- a/modules/core/db/update/mssql/13/130923-permissionsToRenamedScreens.sql +++ b/modules/core/db/update/mssql/13/130923-permissionsToRenamedScreens.sql @@ -1,9 +1,9 @@ --- Update permissions to renamed screens - -update SEC_PERMISSION set TARGET = 'sys$Category.browse' where PERMISSION_TYPE = 10 and TARGET = 'sys$Categories.browse'; - -update SEC_PERMISSION set TARGET = 'entityRestore' where PERMISSION_TYPE = 10 and TARGET = 'sys$Entity.restore'; - -update SEC_PERMISSION set TARGET = 'jmxConsole' where PERMISSION_TYPE = 10 and TARGET = 'jmxcontrol$DisplayMbeans'; - -update SEC_PERMISSION set TARGET = 'serverLog' where PERMISSION_TYPE = 10 and TARGET = 'logcontrol$ServerLog'; +-- Update permissions to renamed screens + +update SEC_PERMISSION set TARGET = 'sys$Category.browse' where PERMISSION_TYPE = 10 and TARGET = 'sys$Categories.browse'; + +update SEC_PERMISSION set TARGET = 'entityRestore' where PERMISSION_TYPE = 10 and TARGET = 'sys$Entity.restore'; + +update SEC_PERMISSION set TARGET = 'jmxConsole' where PERMISSION_TYPE = 10 and TARGET = 'jmxcontrol$DisplayMbeans'; + +update SEC_PERMISSION set TARGET = 'serverLog' where PERMISSION_TYPE = 10 and TARGET = 'logcontrol$ServerLog'; diff --git a/modules/core/db/update/mssql/15/150203-sendingMessageEmailHeaders.sql b/modules/core/db/update/mssql/15/150203-sendingMessageEmailHeaders.sql index f22d55088c..c735e66084 100644 --- a/modules/core/db/update/mssql/15/150203-sendingMessageEmailHeaders.sql +++ b/modules/core/db/update/mssql/15/150203-sendingMessageEmailHeaders.sql @@ -1,3 +1,3 @@ --- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS - +-- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS + alter table SYS_SENDING_MESSAGE add EMAIL_HEADERS varchar(500)^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/15/150205-addSubstituteUserInScreenHistory.sql b/modules/core/db/update/mssql/15/150205-addSubstituteUserInScreenHistory.sql index f7a14e5920..1ed58db6ee 100644 --- a/modules/core/db/update/mssql/15/150205-addSubstituteUserInScreenHistory.sql +++ b/modules/core/db/update/mssql/15/150205-addSubstituteUserInScreenHistory.sql @@ -1,4 +1,4 @@ --- Description: - -alter table sec_screen_history add substituted_user_id uniqueidentifier^ +-- Description: + +alter table sec_screen_history add substituted_user_id uniqueidentifier^ alter table sec_screen_history add constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER (ID)^ \ No newline at end of file diff --git a/modules/core/db/update/mssql/15/150226-addIndexInScreenHistory.sql b/modules/core/db/update/mssql/15/150226-addIndexInScreenHistory.sql index cfd2b6509c..858531e8a8 100644 --- a/modules/core/db/update/mssql/15/150226-addIndexInScreenHistory.sql +++ b/modules/core/db/update/mssql/15/150226-addIndexInScreenHistory.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID); \ No newline at end of file diff --git a/modules/core/db/update/mssql/15/150805-fakeFtsQueue.sql b/modules/core/db/update/mssql/15/150805-fakeFtsQueue.sql index b0df29e8a5..3a79c71af6 100644 --- a/modules/core/db/update/mssql/15/150805-fakeFtsQueue.sql +++ b/modules/core/db/update/mssql/15/150805-fakeFtsQueue.sql @@ -1 +1 @@ -alter table SYS_FTS_QUEUE add FAKE tinyint^ +alter table SYS_FTS_QUEUE add FAKE tinyint^ diff --git a/modules/core/db/update/mssql/15/151116-rowLevelSecurity.sql b/modules/core/db/update/mssql/15/151116-rowLevelSecurity.sql index b9be8fc0b2..59cc699d54 100644 --- a/modules/core/db/update/mssql/15/151116-rowLevelSecurity.sql +++ b/modules/core/db/update/mssql/15/151116-rowLevelSecurity.sql @@ -1,7 +1,7 @@ -alter table sec_constraint add CODE varchar(255)^ -alter table sec_constraint add CHECK_TYPE varchar(50) default 'db'^ -alter table sec_constraint add OPERATION_TYPE varchar(50) default 'read'^ -alter table sec_constraint add GROOVY_SCRIPT varchar(500)^ -alter table sec_constraint add FILTER_XML varchar(1000)^ -update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ -update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ +alter table sec_constraint add CODE varchar(255)^ +alter table sec_constraint add CHECK_TYPE varchar(50) default 'db'^ +alter table sec_constraint add OPERATION_TYPE varchar(50) default 'read'^ +alter table sec_constraint add GROOVY_SCRIPT varchar(500)^ +alter table sec_constraint add FILTER_XML varchar(1000)^ +update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ +update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ diff --git a/modules/core/db/update/mssql/15/151228-sendingMessagesExtendFields.sql b/modules/core/db/update/mssql/15/151228-sendingMessagesExtendFields.sql index 652f78a6f5..c44decc2ab 100644 --- a/modules/core/db/update/mssql/15/151228-sendingMessagesExtendFields.sql +++ b/modules/core/db/update/mssql/15/151228-sendingMessagesExtendFields.sql @@ -1,3 +1,3 @@ -alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO varchar(max)^ -alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME varchar(max)^ - +alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO varchar(max)^ +alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME varchar(max)^ + diff --git a/modules/core/db/update/mssql/15/1512282-addIsActiveToConstraint.sql b/modules/core/db/update/mssql/15/1512282-addIsActiveToConstraint.sql index 41290d9461..65e21cb10c 100644 --- a/modules/core/db/update/mssql/15/1512282-addIsActiveToConstraint.sql +++ b/modules/core/db/update/mssql/15/1512282-addIsActiveToConstraint.sql @@ -1,2 +1,2 @@ -alter table SEC_CONSTRAINT add IS_ACTIVE tinyint default 1^ - +alter table SEC_CONSTRAINT add IS_ACTIVE tinyint default 1^ + diff --git a/modules/core/db/update/oracle/14/140608-addGetCurrValFunction.sql b/modules/core/db/update/oracle/14/140608-addGetCurrValFunction.sql index b08f411beb..08be6b7c8b 100644 --- a/modules/core/db/update/oracle/14/140608-addGetCurrValFunction.sql +++ b/modules/core/db/update/oracle/14/140608-addGetCurrValFunction.sql @@ -1,15 +1,15 @@ ---Description: create procedure to select current value of a sequence - -create or replace function GET_SEQ_VAL(seqname varchar2) return NUMBER -as - ln number; - ib number; -begin - select LAST_NUMBER, INCREMENT_BY - into ln, ib - from USER_SEQUENCES - where SEQUENCE_NAME = upper(seqname); - - return ln - ib; -end; +--Description: create procedure to select current value of a sequence + +create or replace function GET_SEQ_VAL(seqname varchar2) return NUMBER +as + ln number; + ib number; +begin + select LAST_NUMBER, INCREMENT_BY + into ln, ib + from USER_SEQUENCES + where SEQUENCE_NAME = upper(seqname); + + return ln - ib; +end; ^ \ No newline at end of file diff --git a/modules/core/db/update/oracle/15/150203-sendingMessageEmailHeaders.sql b/modules/core/db/update/oracle/15/150203-sendingMessageEmailHeaders.sql index 74a13d1664..7b7ef36720 100644 --- a/modules/core/db/update/oracle/15/150203-sendingMessageEmailHeaders.sql +++ b/modules/core/db/update/oracle/15/150203-sendingMessageEmailHeaders.sql @@ -1,3 +1,3 @@ --- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS - +-- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS + alter table SYS_SENDING_MESSAGE add EMAIL_HEADERS varchar2(500)^ \ No newline at end of file diff --git a/modules/core/db/update/oracle/15/150205-addSubstituteUserInScreenHistory.sql b/modules/core/db/update/oracle/15/150205-addSubstituteUserInScreenHistory.sql index fee2254b0c..1cea81e198 100644 --- a/modules/core/db/update/oracle/15/150205-addSubstituteUserInScreenHistory.sql +++ b/modules/core/db/update/oracle/15/150205-addSubstituteUserInScreenHistory.sql @@ -1,4 +1,4 @@ --- Description: - -alter table sec_screen_history add substituted_user_id varchar2(32)^ +-- Description: + +alter table sec_screen_history add substituted_user_id varchar2(32)^ create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY(SUBSTITUTED_USER_ID)^ \ No newline at end of file diff --git a/modules/core/db/update/oracle/15/150226-addConstaintInScreenHistory.sql b/modules/core/db/update/oracle/15/150226-addConstaintInScreenHistory.sql index 7c255d3d5a..9a135db8ed 100644 --- a/modules/core/db/update/oracle/15/150226-addConstaintInScreenHistory.sql +++ b/modules/core/db/update/oracle/15/150226-addConstaintInScreenHistory.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + alter table SEC_SCREEN_HISTORY add constraint FK_SEC_HISTORY_SUB_USER foreign key (SUBSTITUTED_USER_ID) references SEC_USER(ID); \ No newline at end of file diff --git a/modules/core/db/update/oracle/15/150717-fixSysQueryResult.sql b/modules/core/db/update/oracle/15/150717-fixSysQueryResult.sql index a82e7f2a5d..0c34a814b2 100644 --- a/modules/core/db/update/oracle/15/150717-fixSysQueryResult.sql +++ b/modules/core/db/update/oracle/15/150717-fixSysQueryResult.sql @@ -1,13 +1,13 @@ - -create sequence SYS_QUERY_RESULT_SEQ -^ - -create or replace trigger SYS_QUERY_RESULT_ID_GEN -before insert on SYS_QUERY_RESULT -for each row -begin - select SYS_QUERY_RESULT_SEQ.nextval - into :new.id - from dual; -end; -^ + +create sequence SYS_QUERY_RESULT_SEQ +^ + +create or replace trigger SYS_QUERY_RESULT_ID_GEN +before insert on SYS_QUERY_RESULT +for each row +begin + select SYS_QUERY_RESULT_SEQ.nextval + into :new.id + from dual; +end; +^ diff --git a/modules/core/db/update/oracle/15/150805-fakeFtsQueue.sql b/modules/core/db/update/oracle/15/150805-fakeFtsQueue.sql index cde1067740..b431b4f9bb 100644 --- a/modules/core/db/update/oracle/15/150805-fakeFtsQueue.sql +++ b/modules/core/db/update/oracle/15/150805-fakeFtsQueue.sql @@ -1 +1 @@ -alter table SYS_FTS_QUEUE add FAKE char(1)^ +alter table SYS_FTS_QUEUE add FAKE char(1)^ diff --git a/modules/core/db/update/oracle/15/151116-rowLevelSecurity.sql b/modules/core/db/update/oracle/15/151116-rowLevelSecurity.sql index 10d054730b..65f858a4d8 100644 --- a/modules/core/db/update/oracle/15/151116-rowLevelSecurity.sql +++ b/modules/core/db/update/oracle/15/151116-rowLevelSecurity.sql @@ -1,7 +1,7 @@ -alter table sec_constraint add CODE varchar2(255)^ -alter table sec_constraint add CHECK_TYPE varchar2(50) default 'db'^ -alter table sec_constraint add OPERATION_TYPE varchar2(50) default 'read'^ -alter table sec_constraint add GROOVY_SCRIPT varchar2(500)^ -alter table sec_constraint add FILTER_XML varchar2(1000)^ -update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ +alter table sec_constraint add CODE varchar2(255)^ +alter table sec_constraint add CHECK_TYPE varchar2(50) default 'db'^ +alter table sec_constraint add OPERATION_TYPE varchar2(50) default 'read'^ +alter table sec_constraint add GROOVY_SCRIPT varchar2(500)^ +alter table sec_constraint add FILTER_XML varchar2(1000)^ +update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ \ No newline at end of file diff --git a/modules/core/db/update/oracle/15/151228-sendingMessagesExtendFields.sql b/modules/core/db/update/oracle/15/151228-sendingMessagesExtendFields.sql index 61c95144d8..2530014fce 100644 --- a/modules/core/db/update/oracle/15/151228-sendingMessagesExtendFields.sql +++ b/modules/core/db/update/oracle/15/151228-sendingMessagesExtendFields.sql @@ -1,12 +1,12 @@ -alter table SYS_SENDING_MESSAGE add ADDRESS_TO_ clob^ -alter table SYS_SENDING_MESSAGE add ATTACHMENTS_NAME_ clob^ - -update SYS_SENDING_MESSAGE set ADDRESS_TO_ = ADDRESS_TO, ATTACHMENTS_NAME_ = ATTACHMENTS_NAME_^ - -alter table SYS_SENDING_MESSAGE drop column ADDRESS_TO^ -alter table SYS_SENDING_MESSAGE drop column ATTACHMENTS_NAME^ - -alter table SYS_SENDING_MESSAGE rename column ADDRESS_TO_ to ADDRESS_TO^ -alter table SYS_SENDING_MESSAGE rename column ATTACHMENTS_NAME_ to ATTACHMENTS_NAME^ - - +alter table SYS_SENDING_MESSAGE add ADDRESS_TO_ clob^ +alter table SYS_SENDING_MESSAGE add ATTACHMENTS_NAME_ clob^ + +update SYS_SENDING_MESSAGE set ADDRESS_TO_ = ADDRESS_TO, ATTACHMENTS_NAME_ = ATTACHMENTS_NAME_^ + +alter table SYS_SENDING_MESSAGE drop column ADDRESS_TO^ +alter table SYS_SENDING_MESSAGE drop column ATTACHMENTS_NAME^ + +alter table SYS_SENDING_MESSAGE rename column ADDRESS_TO_ to ADDRESS_TO^ +alter table SYS_SENDING_MESSAGE rename column ATTACHMENTS_NAME_ to ATTACHMENTS_NAME^ + + diff --git a/modules/core/db/update/oracle/15/1512282-addIsActiveToConstraint.sql b/modules/core/db/update/oracle/15/1512282-addIsActiveToConstraint.sql index 5348a8428c..3f24a97768 100644 --- a/modules/core/db/update/oracle/15/1512282-addIsActiveToConstraint.sql +++ b/modules/core/db/update/oracle/15/1512282-addIsActiveToConstraint.sql @@ -1,2 +1,2 @@ -alter table SEC_CONSTRAINT add IS_ACTIVE char(1) default '1'^ - +alter table SEC_CONSTRAINT add IS_ACTIVE char(1) default '1'^ + diff --git a/modules/core/db/update/postgres/01/01-010-addValueIdToEntityLog.sql b/modules/core/db/update/postgres/01/01-010-addValueIdToEntityLog.sql index 3ab2205c6b..01bfd103ac 100644 --- a/modules/core/db/update/postgres/01/01-010-addValueIdToEntityLog.sql +++ b/modules/core/db/update/postgres/01/01-010-addValueIdToEntityLog.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + alter table SEC_ENTITY_LOG_ATTR add column VALUE_ID uuid; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-020-dropDbUpdatePKey.sql b/modules/core/db/update/postgres/01/01-020-dropDbUpdatePKey.sql index 1055e96d75..f925c2df54 100644 --- a/modules/core/db/update/postgres/01/01-020-dropDbUpdatePKey.sql +++ b/modules/core/db/update/postgres/01/01-020-dropDbUpdatePKey.sql @@ -1,4 +1,4 @@ --- Description: Moving to the new update database mechanism - -alter table SYS_DB_UPDATE drop constraint SYS_DB_UPDATE_PKEY; - +-- Description: Moving to the new update database mechanism + +alter table SYS_DB_UPDATE drop constraint SYS_DB_UPDATE_PKEY; + diff --git a/modules/core/db/update/postgres/01/01-030-add_EntityLogAttr_messagesPack.sql b/modules/core/db/update/postgres/01/01-030-add_EntityLogAttr_messagesPack.sql index 10a8cead82..99e192d75e 100644 --- a/modules/core/db/update/postgres/01/01-030-add_EntityLogAttr_messagesPack.sql +++ b/modules/core/db/update/postgres/01/01-030-add_EntityLogAttr_messagesPack.sql @@ -1,4 +1,4 @@ --- Description: adding SEC_ENTITY_LOG_ATTR.MESSAGES_PACK field - -alter table SEC_ENTITY_LOG_ATTR add MESSAGES_PACK varchar(200) -^ +-- Description: adding SEC_ENTITY_LOG_ATTR.MESSAGES_PACK field + +alter table SEC_ENTITY_LOG_ATTR add MESSAGES_PACK varchar(200) +^ diff --git a/modules/core/db/update/postgres/01/01-040-renameUserPosition.sql b/modules/core/db/update/postgres/01/01-040-renameUserPosition.sql index f8169bf539..8d93af15ea 100644 --- a/modules/core/db/update/postgres/01/01-040-renameUserPosition.sql +++ b/modules/core/db/update/postgres/01/01-040-renameUserPosition.sql @@ -1,4 +1,4 @@ --- Description: sec_user.position field - -alter table sec_user rename column position to position_ -^ +-- Description: sec_user.position field + +alter table sec_user rename column position to position_ +^ diff --git a/modules/core/db/update/postgres/01/01-050-addUserLanguage.sql b/modules/core/db/update/postgres/01/01-050-addUserLanguage.sql index e29190f589..4e490cb7d6 100644 --- a/modules/core/db/update/postgres/01/01-050-addUserLanguage.sql +++ b/modules/core/db/update/postgres/01/01-050-addUserLanguage.sql @@ -1,4 +1,4 @@ --- Description: sec_user.language_ field - -alter table SEC_USER add LANGUAGE_ varchar(10) -^ +-- Description: sec_user.language_ field + +alter table SEC_USER add LANGUAGE_ varchar(10) +^ diff --git a/modules/core/db/update/postgres/01/01-050-sysFtsQueue.sql b/modules/core/db/update/postgres/01/01-050-sysFtsQueue.sql index f812254e8b..f5a3acfffd 100644 --- a/modules/core/db/update/postgres/01/01-050-sysFtsQueue.sql +++ b/modules/core/db/update/postgres/01/01-050-sysFtsQueue.sql @@ -1,15 +1,15 @@ --- Description: SYS_FTS_QUEUE table - -create table SYS_FTS_QUEUE ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - ENTITY_ID uuid, - ENTITY_NAME varchar(200), - CHANGE_TYPE char(1), - SOURCE_HOST varchar(100), - primary key (ID) -)^ - -create index IDX_SYS_FTS_QUEUE_CREATE_TS on SYS_FTS_QUEUE (CREATE_TS) -^ +-- Description: SYS_FTS_QUEUE table + +create table SYS_FTS_QUEUE ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + ENTITY_ID uuid, + ENTITY_NAME varchar(200), + CHANGE_TYPE char(1), + SOURCE_HOST varchar(100), + primary key (ID) +)^ + +create index IDX_SYS_FTS_QUEUE_CREATE_TS on SYS_FTS_QUEUE (CREATE_TS) +^ diff --git a/modules/core/db/update/postgres/01/01-055-createReportTables.sql b/modules/core/db/update/postgres/01/01-055-createReportTables.sql index 3c1eb2f3fc..df7827697f 100644 --- a/modules/core/db/update/postgres/01/01-055-createReportTables.sql +++ b/modules/core/db/update/postgres/01/01-055-createReportTables.sql @@ -1,120 +1,120 @@ -CREATE TABLE report_band_definition -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - query character varying(255), - parent_definition_id uuid, - "name" character varying(255), - orientation integer DEFAULT 0, - "position" integer DEFAULT 0, - CONSTRAINT report_band_definition_pkey PRIMARY KEY (id), - CONSTRAINT fk_report_band_definition_to_report_band_definition FOREIGN KEY (parent_definition_id) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION -); - -CREATE TABLE report_report -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - "name" character varying(255), - root_definition_id uuid, - template_path text, - report_output_type integer DEFAULT 0, - is_custom boolean DEFAULT false, - custom_class character varying, - linked_entity character varying, - template_file_id uuid, - report_type integer, - CONSTRAINT report_report_pkey PRIMARY KEY (id), - CONSTRAINT fk_report_report_to_report_band_definition FOREIGN KEY (root_definition_id) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION -); - -CREATE TABLE report_input_parameter -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - report_id uuid, - "type" integer, - "name" character varying(255), - alias character varying(100), - screen character varying(255), - class_name character varying, - from_browser boolean, - required boolean DEFAULT false, - CONSTRAINT repor_input_parameter_pkey PRIMARY KEY (id), - CONSTRAINT fk_repor_input_parameter_to_report_report FOREIGN KEY (report_id) - REFERENCES report_report (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION -); - -CREATE TABLE report_data_set -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - "name" character varying(255), - "text" text, - "type" integer, - band_definition uuid, - CONSTRAINT report_data_set_pkey PRIMARY KEY (id), - CONSTRAINT fk_report_data_set_to_report_band_definition FOREIGN KEY (band_definition) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION -); - -create table REPORT_REPORTS_ROLES ( -REPORT_ID uuid not null, -ROLE_ID uuid not null -); - -alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_REPORT -foreign key (REPORT_ID) references REPORT_REPORT(ID); - -alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_ROLE -foreign key (ROLE_ID) references SEC_ROLE(ID); - - -CREATE TABLE report_report_screen -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - report_id uuid, - screen_id character varying(255), - CONSTRAINT report_report_screen_pkey PRIMARY KEY (id), - CONSTRAINT fk_report_report_screen_to_report_report FOREIGN KEY (report_id) - REFERENCES report_report (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION -); - +CREATE TABLE report_band_definition +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + query character varying(255), + parent_definition_id uuid, + "name" character varying(255), + orientation integer DEFAULT 0, + "position" integer DEFAULT 0, + CONSTRAINT report_band_definition_pkey PRIMARY KEY (id), + CONSTRAINT fk_report_band_definition_to_report_band_definition FOREIGN KEY (parent_definition_id) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION +); + +CREATE TABLE report_report +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + "name" character varying(255), + root_definition_id uuid, + template_path text, + report_output_type integer DEFAULT 0, + is_custom boolean DEFAULT false, + custom_class character varying, + linked_entity character varying, + template_file_id uuid, + report_type integer, + CONSTRAINT report_report_pkey PRIMARY KEY (id), + CONSTRAINT fk_report_report_to_report_band_definition FOREIGN KEY (root_definition_id) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION +); + +CREATE TABLE report_input_parameter +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + report_id uuid, + "type" integer, + "name" character varying(255), + alias character varying(100), + screen character varying(255), + class_name character varying, + from_browser boolean, + required boolean DEFAULT false, + CONSTRAINT repor_input_parameter_pkey PRIMARY KEY (id), + CONSTRAINT fk_repor_input_parameter_to_report_report FOREIGN KEY (report_id) + REFERENCES report_report (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION +); + +CREATE TABLE report_data_set +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + "name" character varying(255), + "text" text, + "type" integer, + band_definition uuid, + CONSTRAINT report_data_set_pkey PRIMARY KEY (id), + CONSTRAINT fk_report_data_set_to_report_band_definition FOREIGN KEY (band_definition) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION +); + +create table REPORT_REPORTS_ROLES ( +REPORT_ID uuid not null, +ROLE_ID uuid not null +); + +alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_REPORT +foreign key (REPORT_ID) references REPORT_REPORT(ID); + +alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_ROLE +foreign key (ROLE_ID) references SEC_ROLE(ID); + + +CREATE TABLE report_report_screen +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + report_id uuid, + screen_id character varying(255), + CONSTRAINT report_report_screen_pkey PRIMARY KEY (id), + CONSTRAINT fk_report_report_screen_to_report_report FOREIGN KEY (report_id) + REFERENCES report_report (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION +); + diff --git a/modules/core/db/update/postgres/01/01-060-addReportParameterPosition.sql b/modules/core/db/update/postgres/01/01-060-addReportParameterPosition.sql index f47c003e9e..5dac99d9a9 100644 --- a/modules/core/db/update/postgres/01/01-060-addReportParameterPosition.sql +++ b/modules/core/db/update/postgres/01/01-060-addReportParameterPosition.sql @@ -1,8 +1,8 @@ -alter table report_input_parameter add column position integer default 0 -^ -alter table report_input_parameter add column meta_class varchar(255) -^ -update report_input_parameter set meta_class=screen -^ -update report_input_parameter set screen = null -^ +alter table report_input_parameter add column position integer default 0 +^ +alter table report_input_parameter add column meta_class varchar(255) +^ +update report_input_parameter set meta_class=screen +^ +update report_input_parameter set screen = null +^ diff --git a/modules/core/db/update/postgres/01/01-080-SessionAttributes.sql b/modules/core/db/update/postgres/01/01-080-SessionAttributes.sql index a089bb3797..a2011cd5d5 100644 --- a/modules/core/db/update/postgres/01/01-080-SessionAttributes.sql +++ b/modules/core/db/update/postgres/01/01-080-SessionAttributes.sql @@ -1,19 +1,19 @@ --- Description: SessionAttributes functionality - -create table SEC_SESSION_ATTR ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - NAME varchar(50), - STR_VALUE varchar(1000), - DATATYPE varchar(20), - GROUP_ID uuid, - primary key (ID) -)^ - -alter table SEC_SESSION_ATTR add constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID)^ +-- Description: SessionAttributes functionality + +create table SEC_SESSION_ATTR ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + NAME varchar(50), + STR_VALUE varchar(1000), + DATATYPE varchar(20), + GROUP_ID uuid, + primary key (ID) +)^ + +alter table SEC_SESSION_ATTR add constraint SEC_SESSION_ATTR_GROUP foreign key (GROUP_ID) references SEC_GROUP(ID)^ diff --git a/modules/core/db/update/postgres/01/01-090-ChangeReportKeys.sql b/modules/core/db/update/postgres/01/01-090-ChangeReportKeys.sql index e6f993a630..1c16994999 100644 --- a/modules/core/db/update/postgres/01/01-090-ChangeReportKeys.sql +++ b/modules/core/db/update/postgres/01/01-090-ChangeReportKeys.sql @@ -1,30 +1,30 @@ --- Description: reports now are hard deleted - -alter table report_band_definition drop CONSTRAINT fk_report_band_definition_to_report_band_definition^ -alter table report_band_definition add CONSTRAINT fk_report_band_definition_to_report_band_definition FOREIGN KEY (parent_definition_id) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE CASCADE^ - -alter table report_report drop CONSTRAINT fk_report_report_to_report_band_definition^ -alter table report_report add CONSTRAINT fk_report_report_to_report_band_definition FOREIGN KEY (root_definition_id) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE CASCADE^ - -ALTER table report_input_parameter drop CONSTRAINT fk_repor_input_parameter_to_report_report^ -alter table report_input_parameter add constraint fk_repor_input_parameter_to_report_report FOREIGN KEY (report_id) - REFERENCES report_report (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE CASCADE^ - -alter table report_data_set drop constraint fk_report_data_set_to_report_band_definition^ -alter table report_data_set add constraint fk_report_data_set_to_report_band_definition FOREIGN KEY (band_definition) - REFERENCES report_band_definition (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE CASCADE^ - -alter table REPORT_REPORTS_ROLES drop constraint FK_REPORT_REPORTS_ROLES_TO_REPORT^ -alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_REPORT -foreign key (REPORT_ID) references REPORT_REPORT(ID) on delete cascade^ - -alter table report_report_screen drop CONSTRAINT fk_report_report_screen_to_report_report^ -alter table report_report_screen add CONSTRAINT fk_report_report_screen_to_report_report FOREIGN KEY (report_id) - REFERENCES report_report (id) MATCH SIMPLE +-- Description: reports now are hard deleted + +alter table report_band_definition drop CONSTRAINT fk_report_band_definition_to_report_band_definition^ +alter table report_band_definition add CONSTRAINT fk_report_band_definition_to_report_band_definition FOREIGN KEY (parent_definition_id) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE CASCADE^ + +alter table report_report drop CONSTRAINT fk_report_report_to_report_band_definition^ +alter table report_report add CONSTRAINT fk_report_report_to_report_band_definition FOREIGN KEY (root_definition_id) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE CASCADE^ + +ALTER table report_input_parameter drop CONSTRAINT fk_repor_input_parameter_to_report_report^ +alter table report_input_parameter add constraint fk_repor_input_parameter_to_report_report FOREIGN KEY (report_id) + REFERENCES report_report (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE CASCADE^ + +alter table report_data_set drop constraint fk_report_data_set_to_report_band_definition^ +alter table report_data_set add constraint fk_report_data_set_to_report_band_definition FOREIGN KEY (band_definition) + REFERENCES report_band_definition (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE CASCADE^ + +alter table REPORT_REPORTS_ROLES drop constraint FK_REPORT_REPORTS_ROLES_TO_REPORT^ +alter table REPORT_REPORTS_ROLES add constraint FK_REPORT_REPORTS_ROLES_TO_REPORT +foreign key (REPORT_ID) references REPORT_REPORT(ID) on delete cascade^ + +alter table report_report_screen drop CONSTRAINT fk_report_report_screen_to_report_report^ +alter table report_report_screen add CONSTRAINT fk_report_report_screen_to_report_report FOREIGN KEY (report_id) + REFERENCES report_report (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE cascade^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-100-EntityStatistics.sql b/modules/core/db/update/postgres/01/01-100-EntityStatistics.sql index 2fbd628e6d..fd46e5fc36 100644 --- a/modules/core/db/update/postgres/01/01-100-EntityStatistics.sql +++ b/modules/core/db/update/postgres/01/01-100-EntityStatistics.sql @@ -1,14 +1,14 @@ --- Description: adding SYS_ENTITY_STATISTICS table - -create table SYS_ENTITY_STATISTICS ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - NAME varchar(50), - INSTANCE_COUNT bigint, - MAX_FETCH_UI integer, - LAZY_COLLECTION_THRESHOLD integer, - primary key (ID) -)^ +-- Description: adding SYS_ENTITY_STATISTICS table + +create table SYS_ENTITY_STATISTICS ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + NAME varchar(50), + INSTANCE_COUNT bigint, + MAX_FETCH_UI integer, + LAZY_COLLECTION_THRESHOLD integer, + primary key (ID) +)^ diff --git a/modules/core/db/update/postgres/01/01-100-addPresentations.sql b/modules/core/db/update/postgres/01/01-100-addPresentations.sql index 99de549e35..7ada87f4ae 100644 --- a/modules/core/db/update/postgres/01/01-100-addPresentations.sql +++ b/modules/core/db/update/postgres/01/01-100-addPresentations.sql @@ -1,23 +1,23 @@ --- Description: added Presentation table and updated SearchFolder - -create table SEC_PRESENTATION ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - COMPONENT varchar(200), - NAME varchar(255), - XML varchar(7000), - USER_ID uuid, - IS_AUTO_SAVE boolean, - primary key (ID) -); - -alter table SEC_PRESENTATION add constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID); - - -alter table SEC_SEARCH_FOLDER add column PRESENTATION_ID uuid; - - -alter table SEC_SEARCH_FOLDER add constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) references SEC_PRESENTATION(ID) on delete set null; +-- Description: added Presentation table and updated SearchFolder + +create table SEC_PRESENTATION ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + COMPONENT varchar(200), + NAME varchar(255), + XML varchar(7000), + USER_ID uuid, + IS_AUTO_SAVE boolean, + primary key (ID) +); + +alter table SEC_PRESENTATION add constraint SEC_PRESENTATION_USER foreign key (USER_ID) references SEC_USER(ID); + + +alter table SEC_SEARCH_FOLDER add column PRESENTATION_ID uuid; + + +alter table SEC_SEARCH_FOLDER add constraint FK_SEC_SEARCH_FOLDER_PRESENTATION foreign key (PRESENTATION_ID) references SEC_PRESENTATION(ID) on delete set null; diff --git a/modules/core/db/update/postgres/01/01-110-AddFieldInSysFolder.sql b/modules/core/db/update/postgres/01/01-110-AddFieldInSysFolder.sql index b65617bc3b..174eababcd 100644 --- a/modules/core/db/update/postgres/01/01-110-AddFieldInSysFolder.sql +++ b/modules/core/db/update/postgres/01/01-110-AddFieldInSysFolder.sql @@ -1,3 +1,3 @@ --- Description: adding field in SYS_FOLDER - +-- Description: adding field in SYS_FOLDER + alter table SYS_FOLDER add column DOUBLE_NAME varchar(100); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-120-AddCodeFieldInSecFilter.sql b/modules/core/db/update/postgres/01/01-120-AddCodeFieldInSecFilter.sql index 1228f0460f..0db4fdb84d 100644 --- a/modules/core/db/update/postgres/01/01-120-AddCodeFieldInSecFilter.sql +++ b/modules/core/db/update/postgres/01/01-120-AddCodeFieldInSecFilter.sql @@ -1,3 +1,3 @@ --- Description: adding field in SEC_FILTER - +-- Description: adding field in SEC_FILTER + alter table SEC_FILTER add column CODE varchar(200); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-130-createReportValueFormatTable.sql b/modules/core/db/update/postgres/01/01-130-createReportValueFormatTable.sql index cdbcc29926..88b8e467af 100644 --- a/modules/core/db/update/postgres/01/01-130-createReportValueFormatTable.sql +++ b/modules/core/db/update/postgres/01/01-130-createReportValueFormatTable.sql @@ -1,18 +1,18 @@ -CREATE TABLE report_value_format -( - id uuid NOT NULL, - create_ts timestamp without time zone, - created_by character varying(50), - "version" integer, - update_ts timestamp without time zone, - updated_by character varying(50), - delete_ts timestamp without time zone, - deleted_by character varying(50), - report_id uuid, - "name" character varying(255), - format character varying(255), - CONSTRAINT report_value_format_pkey PRIMARY KEY (id), - CONSTRAINT fk_report_value_format_to_report_report FOREIGN KEY (report_id) - REFERENCES report_report (id) MATCH SIMPLE - ON UPDATE NO ACTION ON DELETE NO ACTION +CREATE TABLE report_value_format +( + id uuid NOT NULL, + create_ts timestamp without time zone, + created_by character varying(50), + "version" integer, + update_ts timestamp without time zone, + updated_by character varying(50), + delete_ts timestamp without time zone, + deleted_by character varying(50), + report_id uuid, + "name" character varying(255), + format character varying(255), + CONSTRAINT report_value_format_pkey PRIMARY KEY (id), + CONSTRAINT fk_report_value_format_to_report_report FOREIGN KEY (report_id) + REFERENCES report_report (id) MATCH SIMPLE + ON UPDATE NO ACTION ON DELETE NO ACTION ); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-140-AddTabHistory.sql b/modules/core/db/update/postgres/01/01-140-AddTabHistory.sql index 86a3f26ce7..f16d5597d4 100644 --- a/modules/core/db/update/postgres/01/01-140-AddTabHistory.sql +++ b/modules/core/db/update/postgres/01/01-140-AddTabHistory.sql @@ -1,12 +1,12 @@ --- Description: -create table SEC_TAB_HISTORY ( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - CREATOR_ID uuid, - CAPTION varchar(255), - URL varchar(4000), - primary key (ID) -); - -alter table SEC_TAB_HISTORY add constraint FK_SEC_HISTORY_USER foreign key (CREATOR_ID) references SEC_USER (ID); +-- Description: +create table SEC_TAB_HISTORY ( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + CREATOR_ID uuid, + CAPTION varchar(255), + URL varchar(4000), + primary key (ID) +); + +alter table SEC_TAB_HISTORY add constraint FK_SEC_HISTORY_USER foreign key (CREATOR_ID) references SEC_USER (ID); diff --git a/modules/core/db/update/postgres/01/01-150-CreateIndexes.sql b/modules/core/db/update/postgres/01/01-150-CreateIndexes.sql index 456305a3f8..a7489fcd0d 100644 --- a/modules/core/db/update/postgres/01/01-150-CreateIndexes.sql +++ b/modules/core/db/update/postgres/01/01-150-CreateIndexes.sql @@ -1,9 +1,9 @@ --- Description: - -create index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ - -create index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ - -create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ - -create index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ +-- Description: + +create index IDX_SEC_CONSTRAINT_GROUP on SEC_CONSTRAINT (GROUP_ID)^ + +create index IDX_SEC_SESSION_ATTR_GROUP on SEC_SESSION_ATTR (GROUP_ID)^ + +create index IDX_SEC_SEARCH_FOLDER_USER on SEC_SEARCH_FOLDER (USER_ID)^ + +create index IDX_SEC_PRESENTATION_COMPONENT_USER on SEC_PRESENTATION (COMPONENT, USER_ID)^ diff --git a/modules/core/db/update/postgres/01/01-160-screenHistory.sql b/modules/core/db/update/postgres/01/01-160-screenHistory.sql index 8e4232c0bd..2545b9d540 100644 --- a/modules/core/db/update/postgres/01/01-160-screenHistory.sql +++ b/modules/core/db/update/postgres/01/01-160-screenHistory.sql @@ -1,5 +1,5 @@ --- Description: - -alter table SEC_TAB_HISTORY rename to SEC_SCREEN_HISTORY^ - +-- Description: + +alter table SEC_TAB_HISTORY rename to SEC_SCREEN_HISTORY^ + alter table SEC_SCREEN_HISTORY rename column CREATOR_ID to USER_ID^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-170-entityStatisticsFetchUI.sql b/modules/core/db/update/postgres/01/01-170-entityStatisticsFetchUI.sql index 6152a71bda..528d03ee7d 100644 --- a/modules/core/db/update/postgres/01/01-170-entityStatisticsFetchUI.sql +++ b/modules/core/db/update/postgres/01/01-170-entityStatisticsFetchUI.sql @@ -1,3 +1,3 @@ --- Description: add SYS_ENTITY_STATISTICS.FETCH_UI column - -alter table SYS_ENTITY_STATISTICS add FETCH_UI integer^ +-- Description: add SYS_ENTITY_STATISTICS.FETCH_UI column + +alter table SYS_ENTITY_STATISTICS add FETCH_UI integer^ diff --git a/modules/core/db/update/postgres/01/01-180-changeAppFoldersScriptsLength.sql b/modules/core/db/update/postgres/01/01-180-changeAppFoldersScriptsLength.sql index fec051393d..90dbfbc831 100644 --- a/modules/core/db/update/postgres/01/01-180-changeAppFoldersScriptsLength.sql +++ b/modules/core/db/update/postgres/01/01-180-changeAppFoldersScriptsLength.sql @@ -1,3 +1,3 @@ --- Description: change type of script columns -ALTER TABLE sys_app_folder ALTER COLUMN visibility_script TYPE text; +-- Description: change type of script columns +ALTER TABLE sys_app_folder ALTER COLUMN visibility_script TYPE text; ALTER TABLE sys_app_folder ALTER COLUMN quantity_script TYPE text; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-190-renameDoubleNameInSysFolder.sql b/modules/core/db/update/postgres/01/01-190-renameDoubleNameInSysFolder.sql index cc02e0b76f..6a21a2bba6 100644 --- a/modules/core/db/update/postgres/01/01-190-renameDoubleNameInSysFolder.sql +++ b/modules/core/db/update/postgres/01/01-190-renameDoubleNameInSysFolder.sql @@ -1,2 +1,2 @@ --- Description: Rename double_name column to tab_name +-- Description: Rename double_name column to tab_name ALTER TABLE sys_folder RENAME COLUMN double_name to tab_name; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-200-deleteCodeInSysFolders.sql b/modules/core/db/update/postgres/01/01-200-deleteCodeInSysFolders.sql index 33705f8d77..5b1c194063 100644 --- a/modules/core/db/update/postgres/01/01-200-deleteCodeInSysFolders.sql +++ b/modules/core/db/update/postgres/01/01-200-deleteCodeInSysFolders.sql @@ -1,6 +1,6 @@ --- Description: delete code column in sys_folder -UPDATE sys_folder as folder1 - SET name = code - WHERE name IS NULL^ - -ALTER TABLE sys_folder DROP COLUMN code; +-- Description: delete code column in sys_folder +UPDATE sys_folder as folder1 + SET name = code + WHERE name IS NULL^ + +ALTER TABLE sys_folder DROP COLUMN code; diff --git a/modules/core/db/update/postgres/01/01-210-updateTabNameInSysFolder.sql b/modules/core/db/update/postgres/01/01-210-updateTabNameInSysFolder.sql index 7b8dd92834..e279822148 100644 --- a/modules/core/db/update/postgres/01/01-210-updateTabNameInSysFolder.sql +++ b/modules/core/db/update/postgres/01/01-210-updateTabNameInSysFolder.sql @@ -1,5 +1,5 @@ --- Description: update tab_name in sys_folder : for search folder, --- wich haven't tab name,put to tab name name of folder + '.tabName' -UPDATE sys_folder - SET tab_name = name || '.tabName' +-- Description: update tab_name in sys_folder : for search folder, +-- wich haven't tab name,put to tab name name of folder + '.tabName' +UPDATE sys_folder + SET tab_name = name || '.tabName' WHERE tab_name IS NULL AND type='S'; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-220-reportTablesChangeColumns.sql b/modules/core/db/update/postgres/01/01-220-reportTablesChangeColumns.sql index 02fc3b8ffb..85b676507e 100644 --- a/modules/core/db/update/postgres/01/01-220-reportTablesChangeColumns.sql +++ b/modules/core/db/update/postgres/01/01-220-reportTablesChangeColumns.sql @@ -1,9 +1,9 @@ --- Description: --- * Drop column 'CLASS_NAME' in table 'REPORT_INPUT_PARAMETER' --- * Rename 'POSITION' to 'POSITION_' - -alter table REPORT_INPUT_PARAMETER drop column CLASS_NAME ^ - -alter table REPORT_INPUT_PARAMETER rename column POSITION to POSITION_ ^ - +-- Description: +-- * Drop column 'CLASS_NAME' in table 'REPORT_INPUT_PARAMETER' +-- * Rename 'POSITION' to 'POSITION_' + +alter table REPORT_INPUT_PARAMETER drop column CLASS_NAME ^ + +alter table REPORT_INPUT_PARAMETER rename column POSITION to POSITION_ ^ + alter table REPORT_BAND_DEFINITION rename column POSITION to POSITION_ ^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-230-reportParameterAddEnumClass.sql b/modules/core/db/update/postgres/01/01-230-reportParameterAddEnumClass.sql index 07a34b9077..346e9d3330 100644 --- a/modules/core/db/update/postgres/01/01-230-reportParameterAddEnumClass.sql +++ b/modules/core/db/update/postgres/01/01-230-reportParameterAddEnumClass.sql @@ -1,4 +1,4 @@ --- Description: --- * Add to 'REPORT_INPUT_PARAMETER' column 'ENUM_CLASS' - +-- Description: +-- * Add to 'REPORT_INPUT_PARAMETER' column 'ENUM_CLASS' + alter table REPORT_INPUT_PARAMETER add column ENUM_CLASS varchar(500); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-240-userIpMask.sql b/modules/core/db/update/postgres/01/01-240-userIpMask.sql index 69deda419b..3559f21123 100644 --- a/modules/core/db/update/postgres/01/01-240-userIpMask.sql +++ b/modules/core/db/update/postgres/01/01-240-userIpMask.sql @@ -1,3 +1,3 @@ --- Description: adding SEC_USER.IP_MASK - +-- Description: adding SEC_USER.IP_MASK + alter table SEC_USER add column IP_MASK varchar(200); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-250-entityStatLookupScreenThreshold.sql b/modules/core/db/update/postgres/01/01-250-entityStatLookupScreenThreshold.sql index 1a6e84c1e4..f54ca723bf 100644 --- a/modules/core/db/update/postgres/01/01-250-entityStatLookupScreenThreshold.sql +++ b/modules/core/db/update/postgres/01/01-250-entityStatLookupScreenThreshold.sql @@ -1,3 +1,3 @@ --- Description: adding SYS_ENTITY_STATISTICS.LOOKUP_SCREEN_THRESHOLD - +-- Description: adding SYS_ENTITY_STATISTICS.LOOKUP_SCREEN_THRESHOLD + alter table SYS_ENTITY_STATISTICS add column LOOKUP_SCREEN_THRESHOLD integer; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-260-reportTemplatesTable.sql b/modules/core/db/update/postgres/01/01-260-reportTemplatesTable.sql index bc3d4f3185..18d0df04d0 100644 --- a/modules/core/db/update/postgres/01/01-260-reportTemplatesTable.sql +++ b/modules/core/db/update/postgres/01/01-260-reportTemplatesTable.sql @@ -1,79 +1,79 @@ --- Description: add REPORT_TEMPLATE table, drop obsolete columns in REPORT_REPORT - -create table REPORT_TEMPLATE -( - ID uuid not null, - CREATE_TS timestamp without time zone, - CREATED_BY character varying(50), - VERSION integer, - UPDATE_TS timestamp without time zone, - UPDATED_BY character varying(50), - - REPORT_ID uuid, - CODE varchar(50), - TEMPLATE_FILE_ID uuid, - OUTPUT_TYPE integer default 0, - IS_DEFAULT boolean default false, - IS_CUSTOM boolean default false, - CUSTOM_CLASS character varying, - - primary key (ID), - constraint FK_REPORT_TEMPLATE_TO_REPORT foreign key (REPORT_ID) - references REPORT_REPORT (ID) -)^ - -alter table REPORT_REPORT drop column DELETE_TS^ -alter table REPORT_REPORT drop column DELETED_BY^ -alter table REPORT_REPORT drop column TEMPLATE_PATH^ - -alter table REPORT_BAND_DEFINITION drop column DELETE_TS^ -alter table REPORT_BAND_DEFINITION drop column DELETED_BY^ - -alter table REPORT_INPUT_PARAMETER drop column DELETE_TS^ -alter table REPORT_INPUT_PARAMETER drop column DELETED_BY^ - -alter table REPORT_DATA_SET drop column DELETE_TS^ -alter table REPORT_DATA_SET drop column DELETED_BY^ - -alter table REPORT_REPORT_SCREEN drop column DELETE_TS^ -alter table REPORT_REPORT_SCREEN drop column DELETED_BY^ - -alter table REPORT_VALUE_FORMAT drop column DELETE_TS^ -alter table REPORT_VALUE_FORMAT drop column DELETED_BY^ - -insert into REPORT_TEMPLATE( - ID, - CREATE_TS, - CREATED_BY, - VERSION, - UPDATE_TS, - UPDATED_BY, - REPORT_ID, - IS_CUSTOM, - CUSTOM_CLASS, - CODE, - IS_DEFAULT, - TEMPLATE_FILE_ID, - OUTPUT_TYPE -) -select - newid(), - CREATE_TS, - CREATED_BY, - VERSION, - UPDATE_TS, - UPDATED_BY, - ID, - IS_CUSTOM, - CUSTOM_CLASS, - 'report$default', - true, - TEMPLATE_FILE_ID, - REPORT_OUTPUT_TYPE -from REPORT_REPORT^ - -alter table REPORT_REPORT drop column REPORT_OUTPUT_TYPE^ -alter table REPORT_REPORT drop column TEMPLATE_FILE_ID^ -alter table REPORT_REPORT drop column IS_CUSTOM^ -alter table REPORT_REPORT drop column CUSTOM_CLASS^ +-- Description: add REPORT_TEMPLATE table, drop obsolete columns in REPORT_REPORT + +create table REPORT_TEMPLATE +( + ID uuid not null, + CREATE_TS timestamp without time zone, + CREATED_BY character varying(50), + VERSION integer, + UPDATE_TS timestamp without time zone, + UPDATED_BY character varying(50), + + REPORT_ID uuid, + CODE varchar(50), + TEMPLATE_FILE_ID uuid, + OUTPUT_TYPE integer default 0, + IS_DEFAULT boolean default false, + IS_CUSTOM boolean default false, + CUSTOM_CLASS character varying, + + primary key (ID), + constraint FK_REPORT_TEMPLATE_TO_REPORT foreign key (REPORT_ID) + references REPORT_REPORT (ID) +)^ + +alter table REPORT_REPORT drop column DELETE_TS^ +alter table REPORT_REPORT drop column DELETED_BY^ +alter table REPORT_REPORT drop column TEMPLATE_PATH^ + +alter table REPORT_BAND_DEFINITION drop column DELETE_TS^ +alter table REPORT_BAND_DEFINITION drop column DELETED_BY^ + +alter table REPORT_INPUT_PARAMETER drop column DELETE_TS^ +alter table REPORT_INPUT_PARAMETER drop column DELETED_BY^ + +alter table REPORT_DATA_SET drop column DELETE_TS^ +alter table REPORT_DATA_SET drop column DELETED_BY^ + +alter table REPORT_REPORT_SCREEN drop column DELETE_TS^ +alter table REPORT_REPORT_SCREEN drop column DELETED_BY^ + +alter table REPORT_VALUE_FORMAT drop column DELETE_TS^ +alter table REPORT_VALUE_FORMAT drop column DELETED_BY^ + +insert into REPORT_TEMPLATE( + ID, + CREATE_TS, + CREATED_BY, + VERSION, + UPDATE_TS, + UPDATED_BY, + REPORT_ID, + IS_CUSTOM, + CUSTOM_CLASS, + CODE, + IS_DEFAULT, + TEMPLATE_FILE_ID, + OUTPUT_TYPE +) +select + newid(), + CREATE_TS, + CREATED_BY, + VERSION, + UPDATE_TS, + UPDATED_BY, + ID, + IS_CUSTOM, + CUSTOM_CLASS, + 'report$default', + true, + TEMPLATE_FILE_ID, + REPORT_OUTPUT_TYPE +from REPORT_REPORT^ + +alter table REPORT_REPORT drop column REPORT_OUTPUT_TYPE^ +alter table REPORT_REPORT drop column TEMPLATE_FILE_ID^ +alter table REPORT_REPORT drop column IS_CUSTOM^ +alter table REPORT_REPORT drop column CUSTOM_CLASS^ alter table REPORT_REPORT drop column LINKED_ENTITY^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-270-sendingMessagesHistory.sql b/modules/core/db/update/postgres/01/01-270-sendingMessagesHistory.sql index 60db38ec56..6df896b93f 100644 --- a/modules/core/db/update/postgres/01/01-270-sendingMessagesHistory.sql +++ b/modules/core/db/update/postgres/01/01-270-sendingMessagesHistory.sql @@ -1,42 +1,42 @@ --- Description: - -create table SYS_SENDING_MESSAGE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - ADDRESS_TO varchar(500), - ADDRESS_FROM varchar(100), - CAPTION varchar(500), - CONTENT_TEXT text, - DEADLINE timestamp, - STATUS int, - DATE_SENT timestamp, - ATTEMPTS_COUNT int, - ATTEMPTS_MADE int, - ATTACHMENTS_NAME varchar(500), - primary key (ID) -)^ - -create table SYS_SENDING_ATTACHMENT( - ID uuid, - CREATE_TS timestamp, - CREATED_BY varchar(50), - MESSAGE_ID uuid, - CONTENT bytea, - CONTENT_ID varchar(50), - NAME varchar(500), - primary key (ID) -)^ - -alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID)^ - -CREATE INDEX SYS_SENDING_ATTACHMENT_MESSAGE_IDX - ON SYS_SENDING_ATTACHMENT(MESSAGE_ID )^ - -insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) - values ('60885987-1b61-4247-94c7-dff348347f94', now(), 0, 'emailer', 'emailer', '2f22cf032e4be87de59e4e8bfd066ed1', 'User for Email sending', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ +-- Description: + +create table SYS_SENDING_MESSAGE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + ADDRESS_TO varchar(500), + ADDRESS_FROM varchar(100), + CAPTION varchar(500), + CONTENT_TEXT text, + DEADLINE timestamp, + STATUS int, + DATE_SENT timestamp, + ATTEMPTS_COUNT int, + ATTEMPTS_MADE int, + ATTACHMENTS_NAME varchar(500), + primary key (ID) +)^ + +create table SYS_SENDING_ATTACHMENT( + ID uuid, + CREATE_TS timestamp, + CREATED_BY varchar(50), + MESSAGE_ID uuid, + CONTENT bytea, + CONTENT_ID varchar(50), + NAME varchar(500), + primary key (ID) +)^ + +alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_SENDING_MESSAGE foreign key (MESSAGE_ID) references SYS_SENDING_MESSAGE (ID)^ + +CREATE INDEX SYS_SENDING_ATTACHMENT_MESSAGE_IDX + ON SYS_SENDING_ATTACHMENT(MESSAGE_ID )^ + +insert into SEC_USER (ID, CREATE_TS, VERSION, LOGIN, LOGIN_LC, PASSWORD, NAME, GROUP_ID, ACTIVE) + values ('60885987-1b61-4247-94c7-dff348347f94', now(), 0, 'emailer', 'emailer', '2f22cf032e4be87de59e4e8bfd066ed1', 'User for Email sending', '0fa2b1a5-1d68-4d69-9fbd-dff348347f93', true)^ diff --git a/modules/core/db/update/postgres/01/01-280-addApplyDefault.sql b/modules/core/db/update/postgres/01/01-280-addApplyDefault.sql index 506136d87e..0497ce014a 100644 --- a/modules/core/db/update/postgres/01/01-280-addApplyDefault.sql +++ b/modules/core/db/update/postgres/01/01-280-addApplyDefault.sql @@ -1,3 +1,3 @@ --- Description: -alter table SYS_APP_FOLDER add column APPLY_DEFAULT boolean; -alter table SEC_SEARCH_FOLDER add column APPLY_DEFAULT boolean; +-- Description: +alter table SYS_APP_FOLDER add column APPLY_DEFAULT boolean; +alter table SEC_SEARCH_FOLDER add column APPLY_DEFAULT boolean; diff --git a/modules/core/db/update/postgres/01/01-290-addIsSetToSearchFolder.sql b/modules/core/db/update/postgres/01/01-290-addIsSetToSearchFolder.sql index a5472d9f68..13618e2b62 100644 --- a/modules/core/db/update/postgres/01/01-290-addIsSetToSearchFolder.sql +++ b/modules/core/db/update/postgres/01/01-290-addIsSetToSearchFolder.sql @@ -1,3 +1,3 @@ --- Description -alter table SEC_SEARCH_FOLDER add column IS_SET boolean; -alter table SEC_SEARCH_FOLDER add column ENTITY_TYPE varchar(50); +-- Description +alter table SEC_SEARCH_FOLDER add column IS_SET boolean; +alter table SEC_SEARCH_FOLDER add column ENTITY_TYPE varchar(50); diff --git a/modules/core/db/update/postgres/01/01-300-addEntitySnapshotTable.sql b/modules/core/db/update/postgres/01/01-300-addEntitySnapshotTable.sql index 68784080ce..31f4363b01 100644 --- a/modules/core/db/update/postgres/01/01-300-addEntitySnapshotTable.sql +++ b/modules/core/db/update/postgres/01/01-300-addEntitySnapshotTable.sql @@ -1,12 +1,12 @@ --- Description: add table SYS_ENTITY_SNAPSHOT - -create table SYS_ENTITY_SNAPSHOT ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - ENTITY_META_CLASS varchar(50), - ENTITY_ID uuid, - VIEW_XML text, - SNAPSHOT_XML text, - primary key (ID) -)^ +-- Description: add table SYS_ENTITY_SNAPSHOT + +create table SYS_ENTITY_SNAPSHOT ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + ENTITY_META_CLASS varchar(50), + ENTITY_ID uuid, + VIEW_XML text, + SNAPSHOT_XML text, + primary key (ID) +)^ diff --git a/modules/core/db/update/postgres/01/01-310-RuntimePropertiesTables.sql b/modules/core/db/update/postgres/01/01-310-RuntimePropertiesTables.sql index 986c6adbbe..977f14a2b2 100644 --- a/modules/core/db/update/postgres/01/01-310-RuntimePropertiesTables.sql +++ b/modules/core/db/update/postgres/01/01-310-RuntimePropertiesTables.sql @@ -1,57 +1,57 @@ --- Description: - - create table SYS_CATEGORY( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - NAME varchar(255), - SPECIAL varchar(50), - ENTITY_TYPE varchar(50), - IS_DEFAULT boolean, - primary key (ID) -)^ - -create table SYS_CATEGORY_ATTR( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - ACTIVE boolean, - NAME varchar(255), - CATEGORY_ID uuid, - IS_ENTITY boolean, - DATA_TYPE varchar(20), - DEFAULT_VALUE varchar, - DEFAULT_ENTITY_VALUE uuid, - ENUMERATION varchar(500), - primary key (ID) -)^ - -alter table SYS_CATEGORY_ATTR add constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID)^ - -create table SYS_ATTR_VALUE( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - CATEGORY_ATTR_ID uuid, - ENTITY_ID uuid, - VALUE varchar(255), - ENTITY_VALUE uuid, - primary key (ID) -)^ - +-- Description: + + create table SYS_CATEGORY( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + NAME varchar(255), + SPECIAL varchar(50), + ENTITY_TYPE varchar(50), + IS_DEFAULT boolean, + primary key (ID) +)^ + +create table SYS_CATEGORY_ATTR( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + ACTIVE boolean, + NAME varchar(255), + CATEGORY_ID uuid, + IS_ENTITY boolean, + DATA_TYPE varchar(20), + DEFAULT_VALUE varchar, + DEFAULT_ENTITY_VALUE uuid, + ENUMERATION varchar(500), + primary key (ID) +)^ + +alter table SYS_CATEGORY_ATTR add constraint SYS_CATEGORY_ATTR_CATEGORY_ID foreign key (CATEGORY_ID) references SYS_CATEGORY(ID)^ + +create table SYS_ATTR_VALUE( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + CATEGORY_ATTR_ID uuid, + ENTITY_ID uuid, + VALUE varchar(255), + ENTITY_VALUE uuid, + primary key (ID) +)^ + alter table SYS_ATTR_VALUE add constraint SYS_ATTR_VALUE_CATEGORY_ATTR_ID foreign key (CATEGORY_ATTR_ID) references SYS_CATEGORY_ATTR(ID)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-320-RuntimePropertiesRework.sql b/modules/core/db/update/postgres/01/01-320-RuntimePropertiesRework.sql index 9ad8cf22fc..01affccb48 100644 --- a/modules/core/db/update/postgres/01/01-320-RuntimePropertiesRework.sql +++ b/modules/core/db/update/postgres/01/01-320-RuntimePropertiesRework.sql @@ -1,14 +1,14 @@ --- Description: -alter table SYS_CATEGORY_ATTR drop column DEFAULT_VALUE^ -alter table SYS_CATEGORY_ATTR add column DEFAULT_STRING varchar^ -alter table SYS_CATEGORY_ATTR add column DEFAULT_INT integer^ -alter table SYS_CATEGORY_ATTR add column DEFAULT_DOUBLE real^ -alter table SYS_CATEGORY_ATTR add column DEFAULT_DATE date^ -alter table SYS_CATEGORY_ATTR add column DEFAULT_BOOLEAN boolean^ - -alter table SYS_ATTR_VALUE drop column VALUE^ -alter table SYS_ATTR_VALUE add column STRING_VALUE varchar^ -alter table SYS_ATTR_VALUE add column INTEGER_VALUE integer^ -alter table SYS_ATTR_VALUE add column DOUBLE_VALUE real^ -alter table SYS_ATTR_VALUE add column DATE_VALUE date^ +-- Description: +alter table SYS_CATEGORY_ATTR drop column DEFAULT_VALUE^ +alter table SYS_CATEGORY_ATTR add column DEFAULT_STRING varchar^ +alter table SYS_CATEGORY_ATTR add column DEFAULT_INT integer^ +alter table SYS_CATEGORY_ATTR add column DEFAULT_DOUBLE real^ +alter table SYS_CATEGORY_ATTR add column DEFAULT_DATE date^ +alter table SYS_CATEGORY_ATTR add column DEFAULT_BOOLEAN boolean^ + +alter table SYS_ATTR_VALUE drop column VALUE^ +alter table SYS_ATTR_VALUE add column STRING_VALUE varchar^ +alter table SYS_ATTR_VALUE add column INTEGER_VALUE integer^ +alter table SYS_ATTR_VALUE add column DOUBLE_VALUE real^ +alter table SYS_ATTR_VALUE add column DATE_VALUE date^ alter table SYS_ATTR_VALUE add column BOOLEAN_VALUE boolean^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-330-CategoryAttrAlterType.sql b/modules/core/db/update/postgres/01/01-330-CategoryAttrAlterType.sql index 0ba1e4d462..dc218dd93c 100644 --- a/modules/core/db/update/postgres/01/01-330-CategoryAttrAlterType.sql +++ b/modules/core/db/update/postgres/01/01-330-CategoryAttrAlterType.sql @@ -1,2 +1,2 @@ --- Description: +-- Description: alter table SYS_CATEGORY_ATTR alter column DATA_TYPE type varchar(200); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-340-CategoryDiscriminator.sql b/modules/core/db/update/postgres/01/01-340-CategoryDiscriminator.sql index c6afa9b851..de8fcf7b21 100644 --- a/modules/core/db/update/postgres/01/01-340-CategoryDiscriminator.sql +++ b/modules/core/db/update/postgres/01/01-340-CategoryDiscriminator.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + alter table SYS_CATEGORY add DISCRIMINATOR integer; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-350-categoryAttrOrderNo.sql b/modules/core/db/update/postgres/01/01-350-categoryAttrOrderNo.sql index e30570a866..22100655b3 100644 --- a/modules/core/db/update/postgres/01/01-350-categoryAttrOrderNo.sql +++ b/modules/core/db/update/postgres/01/01-350-categoryAttrOrderNo.sql @@ -1,2 +1,2 @@ --- Description: +-- Description: alter table SYS_CATEGORY_ATTR add ORDER_NO integer; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-360-CategoryAttrScreen.sql b/modules/core/db/update/postgres/01/01-360-CategoryAttrScreen.sql index 6a5eb86f48..0a9fc9b798 100644 --- a/modules/core/db/update/postgres/01/01-360-CategoryAttrScreen.sql +++ b/modules/core/db/update/postgres/01/01-360-CategoryAttrScreen.sql @@ -1,2 +1,2 @@ - + alter table SYS_CATEGORY_ATTR add SCREEN varchar(255); \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-370-CategoryAttrRequired.sql b/modules/core/db/update/postgres/01/01-370-CategoryAttrRequired.sql index c0a7a5479b..414d50ee85 100644 --- a/modules/core/db/update/postgres/01/01-370-CategoryAttrRequired.sql +++ b/modules/core/db/update/postgres/01/01-370-CategoryAttrRequired.sql @@ -1,3 +1,3 @@ - -alter table SYS_CATEGORY_ATTR add REQUIRED boolean; + +alter table SYS_CATEGORY_ATTR add REQUIRED boolean; update SYS_CATEGORY_ATTR set REQUIRED = false; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-380-AlterTypeColumnUrlInScreenHistory.sql b/modules/core/db/update/postgres/01/01-380-AlterTypeColumnUrlInScreenHistory.sql index f48cd89ad5..9b75c2ce6e 100644 --- a/modules/core/db/update/postgres/01/01-380-AlterTypeColumnUrlInScreenHistory.sql +++ b/modules/core/db/update/postgres/01/01-380-AlterTypeColumnUrlInScreenHistory.sql @@ -1,2 +1,2 @@ --- Description: +-- Description: ALTER TABLE SEC_SCREEN_HISTORY ALTER column URL type TEXT; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-390-AlterTableSysCategoryAttr.sql b/modules/core/db/update/postgres/01/01-390-AlterTableSysCategoryAttr.sql index c5d15dabe6..6fc2f73169 100644 --- a/modules/core/db/update/postgres/01/01-390-AlterTableSysCategoryAttr.sql +++ b/modules/core/db/update/postgres/01/01-390-AlterTableSysCategoryAttr.sql @@ -1,2 +1,2 @@ --- Description: +-- Description: ALTER TABLE SYS_CATEGORY_ATTR ALTER COLUMN DEFAULT_DATE TYPE timestamp; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-400-AlterTableSysAttrValue.sql b/modules/core/db/update/postgres/01/01-400-AlterTableSysAttrValue.sql index afe295084d..5a99903014 100644 --- a/modules/core/db/update/postgres/01/01-400-AlterTableSysAttrValue.sql +++ b/modules/core/db/update/postgres/01/01-400-AlterTableSysAttrValue.sql @@ -1,2 +1,2 @@ --- Description: +-- Description: ALTER TABLE SYS_ATTR_VALUE ALTER COLUMN DATE_VALUE TYPE timestamp; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-410-addDataSetParams.sql b/modules/core/db/update/postgres/01/01-410-addDataSetParams.sql index b5ced9723a..ac0bb0d993 100644 --- a/modules/core/db/update/postgres/01/01-410-addDataSetParams.sql +++ b/modules/core/db/update/postgres/01/01-410-addDataSetParams.sql @@ -1,7 +1,7 @@ ---Add fields for specify parameters in Entity/EntityList/Filter loaders - -alter table REPORT_DATA_SET add ENTITY_PARAM_NAME varchar(255) ^ -alter table REPORT_DATA_SET add LIST_ENTITIES_PARAM_NAME varchar(255) ^ - -update REPORT_DATA_SET set ENTITY_PARAM_NAME = 'entity' ^ +--Add fields for specify parameters in Entity/EntityList/Filter loaders + +alter table REPORT_DATA_SET add ENTITY_PARAM_NAME varchar(255) ^ +alter table REPORT_DATA_SET add LIST_ENTITIES_PARAM_NAME varchar(255) ^ + +update REPORT_DATA_SET set ENTITY_PARAM_NAME = 'entity' ^ update REPORT_DATA_SET set LIST_ENTITIES_PARAM_NAME = 'entities' ^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-410-addStartDateToUserSubstitution.sql b/modules/core/db/update/postgres/01/01-410-addStartDateToUserSubstitution.sql index 8e6ecfbe74..3e06dea61f 100644 --- a/modules/core/db/update/postgres/01/01-410-addStartDateToUserSubstitution.sql +++ b/modules/core/db/update/postgres/01/01-410-addStartDateToUserSubstitution.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + alter table SEC_USER_SUBSTITUTION add column START_DATE timestamp; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-420-addEntityIdToScreenHistory.sql b/modules/core/db/update/postgres/01/01-420-addEntityIdToScreenHistory.sql index da3b9d790f..33a3099aac 100644 --- a/modules/core/db/update/postgres/01/01-420-addEntityIdToScreenHistory.sql +++ b/modules/core/db/update/postgres/01/01-420-addEntityIdToScreenHistory.sql @@ -1,2 +1,2 @@ - + alter table SEC_SCREEN_HISTORY add ENTITY_ID uuid; \ No newline at end of file diff --git a/modules/core/db/update/postgres/01/01-440-addDropdownToCategoryAttribute.sql b/modules/core/db/update/postgres/01/01-440-addDropdownToCategoryAttribute.sql index 7f5cfdc431..7704501358 100644 --- a/modules/core/db/update/postgres/01/01-440-addDropdownToCategoryAttribute.sql +++ b/modules/core/db/update/postgres/01/01-440-addDropdownToCategoryAttribute.sql @@ -1,2 +1,2 @@ - -alter table SYS_CATEGORY_ATTR add column LOOKUP boolean; + +alter table SYS_CATEGORY_ATTR add column LOOKUP boolean; diff --git a/modules/core/db/update/postgres/01/01-450-alterSecConstraint.sql b/modules/core/db/update/postgres/01/01-450-alterSecConstraint.sql index 3e88f3dd58..851e478e9f 100644 --- a/modules/core/db/update/postgres/01/01-450-alterSecConstraint.sql +++ b/modules/core/db/update/postgres/01/01-450-alterSecConstraint.sql @@ -1,2 +1,2 @@ - + alter table SEC_CONSTRAINT alter column WHERE_CLAUSE type varchar(1000)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-010-addScheduledTasks.sql b/modules/core/db/update/postgres/02/02-010-addScheduledTasks.sql index db5708be3f..74b588198d 100644 --- a/modules/core/db/update/postgres/02/02-010-addScheduledTasks.sql +++ b/modules/core/db/update/postgres/02/02-010-addScheduledTasks.sql @@ -1,47 +1,47 @@ --- Add tables for core$ScheduledTask and core$ScheduledExecution entities - -create table SYS_SCHEDULED_TASK ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - BEAN_NAME varchar(50), - METHOD_NAME varchar(50), - USER_NAME varchar(50), - USER_PASSWORD varchar(50), - IS_SINGLETON boolean, - IS_ACTIVE boolean, - PERIOD integer, - TIMEOUT integer, - START_DATE timestamp, - TIME_FRAME integer, - START_DELAY integer, - PERMITTED_SERVERS varchar(500), - LOG_START boolean, - LOG_FINISH boolean, - LAST_START_TIME timestamp, - LAST_START_SERVER varchar(50), - primary key (ID) -)^ - -create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME) -where DELETE_TS is null^ - -create table SYS_SCHEDULED_EXECUTION ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - TASK_ID uuid, - SERVER varchar(50), - START_TIME timestamp, - FINISH_TIME timestamp, - RESULT text, - primary key (ID), - constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) -)^ - -create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ +-- Add tables for core$ScheduledTask and core$ScheduledExecution entities + +create table SYS_SCHEDULED_TASK ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + BEAN_NAME varchar(50), + METHOD_NAME varchar(50), + USER_NAME varchar(50), + USER_PASSWORD varchar(50), + IS_SINGLETON boolean, + IS_ACTIVE boolean, + PERIOD integer, + TIMEOUT integer, + START_DATE timestamp, + TIME_FRAME integer, + START_DELAY integer, + PERMITTED_SERVERS varchar(500), + LOG_START boolean, + LOG_FINISH boolean, + LAST_START_TIME timestamp, + LAST_START_SERVER varchar(50), + primary key (ID) +)^ + +create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME) +where DELETE_TS is null^ + +create table SYS_SCHEDULED_EXECUTION ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + TASK_ID uuid, + SERVER varchar(50), + START_TIME timestamp, + FINISH_TIME timestamp, + RESULT text, + primary key (ID), + constraint SYS_SCHEDULED_EXECUTION_TASK foreign key (TASK_ID) references SYS_SCHEDULED_TASK(ID) +)^ + +create index IDX_SYS_SCHEDULED_EXECUTION_TASK_START_TIME on SYS_SCHEDULED_EXECUTION (TASK_ID, START_TIME)^ diff --git a/modules/core/db/update/postgres/02/02-020-alterDoubleValueColumnInSysAttrValueTable.sql b/modules/core/db/update/postgres/02/02-020-alterDoubleValueColumnInSysAttrValueTable.sql index 87468eb7f4..36dbd113e3 100644 --- a/modules/core/db/update/postgres/02/02-020-alterDoubleValueColumnInSysAttrValueTable.sql +++ b/modules/core/db/update/postgres/02/02-020-alterDoubleValueColumnInSysAttrValueTable.sql @@ -1,3 +1,3 @@ --- Description: -alter table SYS_ATTR_VALUE alter column DOUBLE_VALUE type numeric; +-- Description: +alter table SYS_ATTR_VALUE alter column DOUBLE_VALUE type numeric; alter table SYS_CATEGORY_ATTR alter column DEFAULT_DOUBLE type numeric; \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-030-addReportGroup.sql b/modules/core/db/update/postgres/02/02-030-addReportGroup.sql index 7cd1785445..b141adf360 100644 --- a/modules/core/db/update/postgres/02/02-030-addReportGroup.sql +++ b/modules/core/db/update/postgres/02/02-030-addReportGroup.sql @@ -1,27 +1,27 @@ --- Add table for ReportGroup - -create table REPORT_GROUP ( - ID uuid not null, - CREATE_TS timestamp without time zone, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp without time zone, - UPDATED_BY varchar(50), - - TITLE varchar(255) not null, - CODE varchar(255), - - primary key (ID) -)^ - -alter table REPORT_REPORT add column GROUP_ID uuid^ -alter table REPORT_REPORT add constraint FK_REPORT_REPORT_TO_REPORT_GROUP foreign key (GROUP_ID) - references REPORT_GROUP (ID)^ - -insert into REPORT_GROUP (ID, CREATE_TS, CREATED_BY, VERSION, TITLE, CODE) -values ('4e083530-0b9c-11e1-9b41-6bdaa41bff94', now(), 'admin', 0, 'General', 'ReportGroup.default')^ - -update REPORT_REPORT -set GROUP_ID = '4e083530-0b9c-11e1-9b41-6bdaa41bff94'^ - +-- Add table for ReportGroup + +create table REPORT_GROUP ( + ID uuid not null, + CREATE_TS timestamp without time zone, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp without time zone, + UPDATED_BY varchar(50), + + TITLE varchar(255) not null, + CODE varchar(255), + + primary key (ID) +)^ + +alter table REPORT_REPORT add column GROUP_ID uuid^ +alter table REPORT_REPORT add constraint FK_REPORT_REPORT_TO_REPORT_GROUP foreign key (GROUP_ID) + references REPORT_GROUP (ID)^ + +insert into REPORT_GROUP (ID, CREATE_TS, CREATED_BY, VERSION, TITLE, CODE) +values ('4e083530-0b9c-11e1-9b41-6bdaa41bff94', now(), 'admin', 0, 'General', 'ReportGroup.default')^ + +update REPORT_REPORT +set GROUP_ID = '4e083530-0b9c-11e1-9b41-6bdaa41bff94'^ + alter table REPORT_REPORT alter column GROUP_ID set not null^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-040-addReportRefToBand.sql b/modules/core/db/update/postgres/02/02-040-addReportRefToBand.sql index 9c3892d896..fe5085e49e 100644 --- a/modules/core/db/update/postgres/02/02-040-addReportRefToBand.sql +++ b/modules/core/db/update/postgres/02/02-040-addReportRefToBand.sql @@ -1,41 +1,41 @@ --- Add to BandDefinition report field - -alter table REPORT_BAND_DEFINITION add column REPORT_ID uuid^ - -alter table REPORT_BAND_DEFINITION add constraint FK_REPORT_BAND_DEFINITION_TO_REPORT_REPORT -foreign key (REPORT_ID) references REPORT_REPORT (ID)^ - --- Set reports for bands - -create function updateBands(parentId uuid, reportId uuid) returns void as $$ -declare - bandId uuid; - childBandId uuid; -begin - for bandId in select ID from REPORT_BAND_DEFINITION where PARENT_DEFINITION_ID = parentId loop - update REPORT_BAND_DEFINITION set REPORT_ID = reportId where ID = bandId; - for childBandId in select ID from REPORT_BAND_DEFINITION where PARENT_DEFINITION_ID = bandId loop - perform updateBands(bandId, reportId); - end loop; - end loop; -end; -$$ language plpgsql^ - -create function updateReports() returns void as $$ -declare - reportId uuid; - rootBandId uuid; -begin - for rootBandId in select ROOT_DEFINITION_ID from REPORT_REPORT loop - select ID into reportId from REPORT_REPORT where ROOT_DEFINITION_ID = rootBandId; - update REPORT_BAND_DEFINITION set REPORT_ID = reportId where ID = rootBandId; - perform updateBands(rootBandId, reportId); - end loop; -end; -$$ language plpgsql^ - -select updateReports()^ - -drop function updateReports()^ - +-- Add to BandDefinition report field + +alter table REPORT_BAND_DEFINITION add column REPORT_ID uuid^ + +alter table REPORT_BAND_DEFINITION add constraint FK_REPORT_BAND_DEFINITION_TO_REPORT_REPORT +foreign key (REPORT_ID) references REPORT_REPORT (ID)^ + +-- Set reports for bands + +create function updateBands(parentId uuid, reportId uuid) returns void as $$ +declare + bandId uuid; + childBandId uuid; +begin + for bandId in select ID from REPORT_BAND_DEFINITION where PARENT_DEFINITION_ID = parentId loop + update REPORT_BAND_DEFINITION set REPORT_ID = reportId where ID = bandId; + for childBandId in select ID from REPORT_BAND_DEFINITION where PARENT_DEFINITION_ID = bandId loop + perform updateBands(bandId, reportId); + end loop; + end loop; +end; +$$ language plpgsql^ + +create function updateReports() returns void as $$ +declare + reportId uuid; + rootBandId uuid; +begin + for rootBandId in select ROOT_DEFINITION_ID from REPORT_REPORT loop + select ID into reportId from REPORT_REPORT where ROOT_DEFINITION_ID = rootBandId; + update REPORT_BAND_DEFINITION set REPORT_ID = reportId where ID = rootBandId; + perform updateBands(rootBandId, reportId); + end loop; +end; +$$ language plpgsql^ + +select updateReports()^ + +drop function updateReports()^ + drop function updateBands(uuid,uuid)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-050-reportLocales.sql b/modules/core/db/update/postgres/02/02-050-reportLocales.sql index 2ffe020890..eaa2b9ff46 100644 --- a/modules/core/db/update/postgres/02/02-050-reportLocales.sql +++ b/modules/core/db/update/postgres/02/02-050-reportLocales.sql @@ -1,10 +1,10 @@ --- Add localization to ReportGroup, Report, ReportInputParameter - -alter table REPORT_GROUP add LOCALE_NAMES text^ -alter table REPORT_REPORT add LOCALE_NAMES text^ -alter table REPORT_INPUT_PARAMETER add LOCALE_NAMES text^ - -update REPORT_GROUP -set LOCALE_NAMES = -E'en=General \nru=Общие' +-- Add localization to ReportGroup, Report, ReportInputParameter + +alter table REPORT_GROUP add LOCALE_NAMES text^ +alter table REPORT_REPORT add LOCALE_NAMES text^ +alter table REPORT_INPUT_PARAMETER add LOCALE_NAMES text^ + +update REPORT_GROUP +set LOCALE_NAMES = +E'en=General \nru=Общие' where code = 'ReportGroup.default'^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-080-addSnapshotDate.sql b/modules/core/db/update/postgres/02/02-080-addSnapshotDate.sql index 04ed80cf41..d2f973b083 100644 --- a/modules/core/db/update/postgres/02/02-080-addSnapshotDate.sql +++ b/modules/core/db/update/postgres/02/02-080-addSnapshotDate.sql @@ -1,2 +1,2 @@ - + alter table SYS_ENTITY_SNAPSHOT add column SNAPSHOT_DATE timestamp^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-090-schedulingDaylightSaving.sql b/modules/core/db/update/postgres/02/02-090-schedulingDaylightSaving.sql index 6df014d329..0b99bef54c 100644 --- a/modules/core/db/update/postgres/02/02-090-schedulingDaylightSaving.sql +++ b/modules/core/db/update/postgres/02/02-090-schedulingDaylightSaving.sql @@ -1,6 +1,6 @@ - --- Description: Change scheduling column types to work normally during time shift (when clocks go back 1 hour) - -alter table SYS_SCHEDULED_TASK alter column LAST_START_TIME type timestamp with time zone; -alter table SYS_SCHEDULED_EXECUTION alter column START_TIME type timestamp with time zone; -alter table SYS_SCHEDULED_EXECUTION alter column FINISH_TIME type timestamp with time zone; + +-- Description: Change scheduling column types to work normally during time shift (when clocks go back 1 hour) + +alter table SYS_SCHEDULED_TASK alter column LAST_START_TIME type timestamp with time zone; +alter table SYS_SCHEDULED_EXECUTION alter column START_TIME type timestamp with time zone; +alter table SYS_SCHEDULED_EXECUTION alter column FINISH_TIME type timestamp with time zone; diff --git a/modules/core/db/update/postgres/02/02-100-entitySnapshotAuthor.sql b/modules/core/db/update/postgres/02/02-100-entitySnapshotAuthor.sql index 3ae73a77a9..f604455dc2 100644 --- a/modules/core/db/update/postgres/02/02-100-entitySnapshotAuthor.sql +++ b/modules/core/db/update/postgres/02/02-100-entitySnapshotAuthor.sql @@ -1,6 +1,6 @@ --- Description: core$EntitySnapshot.author attribute added - -alter table SYS_ENTITY_SNAPSHOT add AUTHOR_ID uuid^ - -alter table SYS_ENTITY_SNAPSHOT +-- Description: core$EntitySnapshot.author attribute added + +alter table SYS_ENTITY_SNAPSHOT add AUTHOR_ID uuid^ + +alter table SYS_ENTITY_SNAPSHOT add constraint FK_SYS_ENTITY_SNAPSHOT_AUTHOR_ID foreign key (AUTHOR_ID) references SEC_USER(ID)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-120-addUserDescriminator.sql b/modules/core/db/update/postgres/02/02-120-addUserDescriminator.sql index f4554bd705..25f062a7f6 100644 --- a/modules/core/db/update/postgres/02/02-120-addUserDescriminator.sql +++ b/modules/core/db/update/postgres/02/02-120-addUserDescriminator.sql @@ -1,4 +1,4 @@ - -alter table SEC_USER add column TYPE varchar(1)^ - + +alter table SEC_USER add column TYPE varchar(1)^ + update SEC_USER set TYPE = 'C'^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-130-alterSecConstraint.sql b/modules/core/db/update/postgres/02/02-130-alterSecConstraint.sql index 2bb1cd2a7b..be3b3fc1a6 100644 --- a/modules/core/db/update/postgres/02/02-130-alterSecConstraint.sql +++ b/modules/core/db/update/postgres/02/02-130-alterSecConstraint.sql @@ -1,2 +1,2 @@ - + alter table SEC_CONSTRAINT alter WHERE_CLAUSE type varchar(1000); \ No newline at end of file diff --git a/modules/core/db/update/postgres/02/02-130-queryResults.sql b/modules/core/db/update/postgres/02/02-130-queryResults.sql index 884229a2b6..87df57f5dd 100644 --- a/modules/core/db/update/postgres/02/02-130-queryResults.sql +++ b/modules/core/db/update/postgres/02/02-130-queryResults.sql @@ -1,16 +1,16 @@ --- Description: DDL for QueryResult entity - -create sequence SYS_QUERY_RESULT_SEQ -^ - -create table SYS_QUERY_RESULT ( - ID bigint not null default nextval('SYS_QUERY_RESULT_SEQ'), - SESSION_ID uuid not null, - QUERY_KEY integer not null, - ENTITY_ID uuid not null, - primary key (ID) -)^ - -create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ - -create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ +-- Description: DDL for QueryResult entity + +create sequence SYS_QUERY_RESULT_SEQ +^ + +create table SYS_QUERY_RESULT ( + ID bigint not null default nextval('SYS_QUERY_RESULT_SEQ'), + SESSION_ID uuid not null, + QUERY_KEY integer not null, + ENTITY_ID uuid not null, + primary key (ID) +)^ + +create index IDX_SYS_QUERY_RESULT_ENTITY_SESSION_KEY on SYS_QUERY_RESULT (ENTITY_ID, SESSION_ID, QUERY_KEY)^ + +create index IDX_SYS_QUERY_RESULT_SESSION_KEY on SYS_QUERY_RESULT (SESSION_ID, QUERY_KEY)^ diff --git a/modules/core/db/update/postgres/02/02-140-entityLogChanges.sql b/modules/core/db/update/postgres/02/02-140-entityLogChanges.sql index 44abd148ff..42e89d1e94 100644 --- a/modules/core/db/update/postgres/02/02-140-entityLogChanges.sql +++ b/modules/core/db/update/postgres/02/02-140-entityLogChanges.sql @@ -1,3 +1,3 @@ --- Description: add SEC_ENTITY_LOG.CHANGES - -alter table SEC_ENTITY_LOG add CHANGES text; +-- Description: add SEC_ENTITY_LOG.CHANGES + +alter table SEC_ENTITY_LOG add CHANGES text; diff --git a/modules/core/db/update/postgres/02/02-150-alterSysScheduledTask.sql b/modules/core/db/update/postgres/02/02-150-alterSysScheduledTask.sql index 12794be6b7..8dfb189794 100644 --- a/modules/core/db/update/postgres/02/02-150-alterSysScheduledTask.sql +++ b/modules/core/db/update/postgres/02/02-150-alterSysScheduledTask.sql @@ -1,4 +1,4 @@ - -alter table SYS_SCHEDULED_TASK add METHOD_PARAMS varchar(1000); -drop index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD; + +alter table SYS_SCHEDULED_TASK add METHOD_PARAMS varchar(1000); +drop index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD; create unique index IDX_SYS_SCHEDULED_TASK_UNIQ_BEAN_METHOD on SYS_SCHEDULED_TASK (BEAN_NAME, METHOD_NAME, METHOD_PARAMS, DELETE_TS); \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121002-updateScreenPermissions.sql b/modules/core/db/update/postgres/12/121002-updateScreenPermissions.sql index d375b3cb67..aea8527905 100644 --- a/modules/core/db/update/postgres/12/121002-updateScreenPermissions.sql +++ b/modules/core/db/update/postgres/12/121002-updateScreenPermissions.sql @@ -1,3 +1,3 @@ --- Description: update screen permissions according to #1532 - -update sec_permission set target = substring(target from 3) where type = 10; +-- Description: update screen permissions according to #1532 + +update sec_permission set target = substring(target from 3) where type = 10; diff --git a/modules/core/db/update/postgres/12/121003-addCodeToCategoryAttribute.sql b/modules/core/db/update/postgres/12/121003-addCodeToCategoryAttribute.sql index 4364e0bfae..cf531261f5 100644 --- a/modules/core/db/update/postgres/12/121003-addCodeToCategoryAttribute.sql +++ b/modules/core/db/update/postgres/12/121003-addCodeToCategoryAttribute.sql @@ -1,3 +1,3 @@ --- Description: add code field to CategoryAttribute - +-- Description: add code field to CategoryAttribute + alter table SYS_CATEGORY_ATTR add column CODE varchar(50); \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121004-addFieldsToScheduledTasks.sql b/modules/core/db/update/postgres/12/121004-addFieldsToScheduledTasks.sql index 8f19bc7f63..a00425b3aa 100644 --- a/modules/core/db/update/postgres/12/121004-addFieldsToScheduledTasks.sql +++ b/modules/core/db/update/postgres/12/121004-addFieldsToScheduledTasks.sql @@ -1,12 +1,12 @@ --- Description: add defined by, class name and script name fields to scheduled task --- also update all existing tasks to beans - - -do $$ -begin - if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%02-140-alterScheduledTask.sql') then - alter table SYS_SCHEDULED_TASK add column DEFINED_BY varchar(1) default 'B'; - alter table SYS_SCHEDULED_TASK add column CLASS_NAME varchar(500); - alter table SYS_SCHEDULED_TASK add column SCRIPT_NAME varchar(500); - end if; -end $$; +-- Description: add defined by, class name and script name fields to scheduled task +-- also update all existing tasks to beans + + +do $$ +begin + if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%02-140-alterScheduledTask.sql') then + alter table SYS_SCHEDULED_TASK add column DEFINED_BY varchar(1) default 'B'; + alter table SYS_SCHEDULED_TASK add column CLASS_NAME varchar(500); + alter table SYS_SCHEDULED_TASK add column SCRIPT_NAME varchar(500); + end if; +end $$; diff --git a/modules/core/db/update/postgres/12/121020-addLoginConstraintsForUser.sql b/modules/core/db/update/postgres/12/121020-addLoginConstraintsForUser.sql index 1be71f8f56..8bed096a0e 100644 --- a/modules/core/db/update/postgres/12/121020-addLoginConstraintsForUser.sql +++ b/modules/core/db/update/postgres/12/121020-addLoginConstraintsForUser.sql @@ -1,13 +1,13 @@ --- Description: add not null constraint on LOGIN and LOGIN_LC for SEC_USER - -update SEC_USER -set LOGIN = cast(ID as varchar(50)), LOGIN_LC = cast(ID as varchar(50)) -where (LOGIN is null) or (LOGIN_LC is null)^ - -alter table SEC_USER alter column LOGIN set not null^ - -drop index IDX_SEC_USER_UNIQ_LOGIN^ - -alter table SEC_USER alter column LOGIN_LC set not null^ - +-- Description: add not null constraint on LOGIN and LOGIN_LC for SEC_USER + +update SEC_USER +set LOGIN = cast(ID as varchar(50)), LOGIN_LC = cast(ID as varchar(50)) +where (LOGIN is null) or (LOGIN_LC is null)^ + +alter table SEC_USER alter column LOGIN set not null^ + +drop index IDX_SEC_USER_UNIQ_LOGIN^ + +alter table SEC_USER alter column LOGIN_LC set not null^ + create unique index IDX_SEC_USER_UNIQ_LOGIN on SEC_USER (LOGIN_LC) where DELETE_TS is null^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121024-addEncryptionParamsToUser.sql b/modules/core/db/update/postgres/12/121024-addEncryptionParamsToUser.sql index e7799d2ff6..589e2cc284 100644 --- a/modules/core/db/update/postgres/12/121024-addEncryptionParamsToUser.sql +++ b/modules/core/db/update/postgres/12/121024-addEncryptionParamsToUser.sql @@ -1,7 +1,7 @@ --- Description: add SALT, HASH_METHOD, CHANGE_PASSWORD_AT_LOGON fields - -alter table SEC_USER alter column PASSWORD set data type varchar(40)^ - -alter table SEC_USER add column CHANGE_PASSWORD_AT_LOGON boolean^ - +-- Description: add SALT, HASH_METHOD, CHANGE_PASSWORD_AT_LOGON fields + +alter table SEC_USER alter column PASSWORD set data type varchar(40)^ + +alter table SEC_USER add column CHANGE_PASSWORD_AT_LOGON boolean^ + alter table SEC_USER add column SALT varchar(16)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121031-dropPasswordColumnFromScheduledTask.sql b/modules/core/db/update/postgres/12/121031-dropPasswordColumnFromScheduledTask.sql index 0739ae0ea1..d96fce690b 100644 --- a/modules/core/db/update/postgres/12/121031-dropPasswordColumnFromScheduledTask.sql +++ b/modules/core/db/update/postgres/12/121031-dropPasswordColumnFromScheduledTask.sql @@ -1,3 +1,3 @@ --- Description: drop USER_PASSWORD column from SYS_SCHEDULED_TASK - +-- Description: drop USER_PASSWORD column from SYS_SCHEDULED_TASK + alter table SYS_SCHEDULED_TASK drop column USER_PASSWORD^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121102-dropSaltColumn.sql b/modules/core/db/update/postgres/12/121102-dropSaltColumn.sql index 3de03fae4c..d3c2a09a0e 100644 --- a/modules/core/db/update/postgres/12/121102-dropSaltColumn.sql +++ b/modules/core/db/update/postgres/12/121102-dropSaltColumn.sql @@ -1,3 +1,3 @@ --- Description: drop SALT column in SEC_USER - +-- Description: drop SALT column in SEC_USER + alter table SEC_USER drop column SALT^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121114-addDescriptionToScheduledTask.sql b/modules/core/db/update/postgres/12/121114-addDescriptionToScheduledTask.sql index 5fb960fb93..6d616a6ce1 100644 --- a/modules/core/db/update/postgres/12/121114-addDescriptionToScheduledTask.sql +++ b/modules/core/db/update/postgres/12/121114-addDescriptionToScheduledTask.sql @@ -1,2 +1,2 @@ - + alter table SYS_SCHEDULED_TASK add DESCRIPTION varchar(1000); \ No newline at end of file diff --git a/modules/core/db/update/postgres/12/121228-addJmxInstance.sql b/modules/core/db/update/postgres/12/121228-addJmxInstance.sql index 26361fb355..5f0ddb7779 100644 --- a/modules/core/db/update/postgres/12/121228-addJmxInstance.sql +++ b/modules/core/db/update/postgres/12/121228-addJmxInstance.sql @@ -1,20 +1,20 @@ --- Description: add SYS_JMX_INSTANCE table - -create table SYS_JMX_INSTANCE ( - ID uuid not null, - CREATE_TS timestamp, - CREATED_BY varchar(50), - VERSION integer, - UPDATE_TS timestamp, - UPDATED_BY varchar(50), - DELETE_TS timestamp, - DELETED_BY varchar(50), - -- - CLUSTER_NODE_NAME varchar(255), - DESCRIPTION varchar(500), - ADDRESS varchar(500) not null, - LOGIN varchar(50) not null, - PASSWORD varchar(255) not null, - -- - primary key (ID) +-- Description: add SYS_JMX_INSTANCE table + +create table SYS_JMX_INSTANCE ( + ID uuid not null, + CREATE_TS timestamp, + CREATED_BY varchar(50), + VERSION integer, + UPDATE_TS timestamp, + UPDATED_BY varchar(50), + DELETE_TS timestamp, + DELETED_BY varchar(50), + -- + CLUSTER_NODE_NAME varchar(255), + DESCRIPTION varchar(500), + ADDRESS varchar(500) not null, + LOGIN varchar(50) not null, + PASSWORD varchar(255) not null, + -- + primary key (ID) )^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/13/130110-removeJmxInstanceDescription.sql b/modules/core/db/update/postgres/13/130110-removeJmxInstanceDescription.sql index 4406a7d207..7055cf0b24 100644 --- a/modules/core/db/update/postgres/13/130110-removeJmxInstanceDescription.sql +++ b/modules/core/db/update/postgres/13/130110-removeJmxInstanceDescription.sql @@ -1,9 +1,9 @@ --- Description: remove column DESCRIPTION from SYS_JMX_INSTANCE table - -do $$ -begin - if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%131001-removeJmxInstanceDescription.sql') then - alter table SYS_JMX_INSTANCE drop column DESCRIPTION; - alter table SYS_JMX_INSTANCE rename column CLUSTER_NODE_NAME to NODE_NAME; - end if; +-- Description: remove column DESCRIPTION from SYS_JMX_INSTANCE table + +do $$ +begin + if not exists(select SCRIPT_NAME from SYS_DB_CHANGELOG where SCRIPT_NAME like '%131001-removeJmxInstanceDescription.sql') then + alter table SYS_JMX_INSTANCE drop column DESCRIPTION; + alter table SYS_JMX_INSTANCE rename column CLUSTER_NODE_NAME to NODE_NAME; + end if; end $$; \ No newline at end of file diff --git a/modules/core/db/update/postgres/13/130918-email-attachment-options.sql b/modules/core/db/update/postgres/13/130918-email-attachment-options.sql index f5bb75b45e..7eb178cb97 100644 --- a/modules/core/db/update/postgres/13/130918-email-attachment-options.sql +++ b/modules/core/db/update/postgres/13/130918-email-attachment-options.sql @@ -1,10 +1,10 @@ --- Add columns to store email attachment disposition and encoding - -alter table SYS_SENDING_ATTACHMENT - add column VERSION integer, - add column UPDATE_TS timestamp, - add column UPDATED_BY varchar(50), - add column DELETE_TS timestamp, - add column DELETED_BY varchar(50), - add column DISPOSITION varchar(50), - add column TEXT_ENCODING varchar(50); +-- Add columns to store email attachment disposition and encoding + +alter table SYS_SENDING_ATTACHMENT + add column VERSION integer, + add column UPDATE_TS timestamp, + add column UPDATED_BY varchar(50), + add column DELETE_TS timestamp, + add column DELETED_BY varchar(50), + add column DISPOSITION varchar(50), + add column TEXT_ENCODING varchar(50); diff --git a/modules/core/db/update/postgres/13/130920-email-file-storage.sql b/modules/core/db/update/postgres/13/130920-email-file-storage.sql index 338c59d10c..842403615f 100644 --- a/modules/core/db/update/postgres/13/130920-email-file-storage.sql +++ b/modules/core/db/update/postgres/13/130920-email-file-storage.sql @@ -1,9 +1,9 @@ --- Add linking columns from SendingMessage and SendingAttachment to sys$File - -alter table SYS_SENDING_MESSAGE add column CONTENT_TEXT_FILE_ID uuid; -alter table SYS_SENDING_MESSAGE ADD constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE -foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID); - -alter table SYS_SENDING_ATTACHMENT add column CONTENT_FILE_ID uuid; -alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE -foreign key (CONTENT_FILE_ID) references SYS_FILE (ID); +-- Add linking columns from SendingMessage and SendingAttachment to sys$File + +alter table SYS_SENDING_MESSAGE add column CONTENT_TEXT_FILE_ID uuid; +alter table SYS_SENDING_MESSAGE ADD constraint FK_SYS_SENDING_MESSAGE_CONTENT_FILE +foreign key (CONTENT_TEXT_FILE_ID) references SYS_FILE(ID); + +alter table SYS_SENDING_ATTACHMENT add column CONTENT_FILE_ID uuid; +alter table SYS_SENDING_ATTACHMENT add constraint FK_SYS_SENDING_ATTACHMENT_CONTENT_FILE +foreign key (CONTENT_FILE_ID) references SYS_FILE (ID); diff --git a/modules/core/db/update/postgres/13/130923-permissionsToRenamedScreens.sql b/modules/core/db/update/postgres/13/130923-permissionsToRenamedScreens.sql index f12cb3279d..efb62bc520 100644 --- a/modules/core/db/update/postgres/13/130923-permissionsToRenamedScreens.sql +++ b/modules/core/db/update/postgres/13/130923-permissionsToRenamedScreens.sql @@ -1,9 +1,9 @@ --- Update permissions to renamed screens - -update SEC_PERMISSION set TARGET = 'sys$Category.browse' where PERMISSION_TYPE = 10 and TARGET = 'sys$Categories.browse'; - -update SEC_PERMISSION set TARGET = 'entityRestore' where PERMISSION_TYPE = 10 and TARGET = 'sys$Entity.restore'; - -update SEC_PERMISSION set TARGET = 'jmxConsole' where PERMISSION_TYPE = 10 and TARGET = 'jmxcontrol$DisplayMbeans'; - -update SEC_PERMISSION set TARGET = 'serverLog' where PERMISSION_TYPE = 10 and TARGET = 'logcontrol$ServerLog'; +-- Update permissions to renamed screens + +update SEC_PERMISSION set TARGET = 'sys$Category.browse' where PERMISSION_TYPE = 10 and TARGET = 'sys$Categories.browse'; + +update SEC_PERMISSION set TARGET = 'entityRestore' where PERMISSION_TYPE = 10 and TARGET = 'sys$Entity.restore'; + +update SEC_PERMISSION set TARGET = 'jmxConsole' where PERMISSION_TYPE = 10 and TARGET = 'jmxcontrol$DisplayMbeans'; + +update SEC_PERMISSION set TARGET = 'serverLog' where PERMISSION_TYPE = 10 and TARGET = 'logcontrol$ServerLog'; diff --git a/modules/core/db/update/postgres/15/150203-sendingMessageEmailHeaders.sql b/modules/core/db/update/postgres/15/150203-sendingMessageEmailHeaders.sql index f22d55088c..c735e66084 100644 --- a/modules/core/db/update/postgres/15/150203-sendingMessageEmailHeaders.sql +++ b/modules/core/db/update/postgres/15/150203-sendingMessageEmailHeaders.sql @@ -1,3 +1,3 @@ --- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS - +-- Add SYS_SENDING_MESSAGE.EMAIL_HEADERS + alter table SYS_SENDING_MESSAGE add EMAIL_HEADERS varchar(500)^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/15/150205-addSubstituteUserInScreenHistory.sql b/modules/core/db/update/postgres/15/150205-addSubstituteUserInScreenHistory.sql index 5c4608ac6e..bdd481d6da 100644 --- a/modules/core/db/update/postgres/15/150205-addSubstituteUserInScreenHistory.sql +++ b/modules/core/db/update/postgres/15/150205-addSubstituteUserInScreenHistory.sql @@ -1,4 +1,4 @@ --- Description: - -alter table sec_screen_history add substituted_user_id uuid; +-- Description: + +alter table sec_screen_history add substituted_user_id uuid; alter table sec_screen_history add constraint FK_SEC_HISTORY_SUBSTITUTED_USER foreign key (substituted_user_id) references sec_user (id); \ No newline at end of file diff --git a/modules/core/db/update/postgres/15/150226-addIndexInScreenHistory.sql b/modules/core/db/update/postgres/15/150226-addIndexInScreenHistory.sql index cfd2b6509c..858531e8a8 100644 --- a/modules/core/db/update/postgres/15/150226-addIndexInScreenHistory.sql +++ b/modules/core/db/update/postgres/15/150226-addIndexInScreenHistory.sql @@ -1,3 +1,3 @@ --- Description: - +-- Description: + create index IDX_SEC_SCREEN_HIST_SUB_USER on SEC_SCREEN_HISTORY (SUBSTITUTED_USER_ID); \ No newline at end of file diff --git a/modules/core/db/update/postgres/15/150805-fakeFtsQueue.sql b/modules/core/db/update/postgres/15/150805-fakeFtsQueue.sql index 6beb0fb0d7..e7da4be51a 100644 --- a/modules/core/db/update/postgres/15/150805-fakeFtsQueue.sql +++ b/modules/core/db/update/postgres/15/150805-fakeFtsQueue.sql @@ -1 +1 @@ -alter table SYS_FTS_QUEUE add FAKE boolean^ +alter table SYS_FTS_QUEUE add FAKE boolean^ diff --git a/modules/core/db/update/postgres/15/151116-rowLevelSecurity.sql b/modules/core/db/update/postgres/15/151116-rowLevelSecurity.sql index b8e43251ab..ffb5704e2f 100644 --- a/modules/core/db/update/postgres/15/151116-rowLevelSecurity.sql +++ b/modules/core/db/update/postgres/15/151116-rowLevelSecurity.sql @@ -1,7 +1,7 @@ -alter table sec_constraint add column CODE varchar(255)^ -alter table sec_constraint add column CHECK_TYPE varchar(50) default 'db'^ -alter table sec_constraint add column OPERATION_TYPE varchar(50) default 'read'^ -alter table sec_constraint add column GROOVY_SCRIPT varchar(500)^ -alter table sec_constraint add column FILTER_XML varchar(1000)^ -update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ +alter table sec_constraint add column CODE varchar(255)^ +alter table sec_constraint add column CHECK_TYPE varchar(50) default 'db'^ +alter table sec_constraint add column OPERATION_TYPE varchar(50) default 'read'^ +alter table sec_constraint add column GROOVY_SCRIPT varchar(500)^ +alter table sec_constraint add column FILTER_XML varchar(1000)^ +update sec_constraint set CHECK_TYPE = 'db' where CHECK_TYPE is null^ update sec_constraint set OPERATION_TYPE = 'read' where OPERATION_TYPE is null^ \ No newline at end of file diff --git a/modules/core/db/update/postgres/15/151228-sendingMessagesExtendFields.sql b/modules/core/db/update/postgres/15/151228-sendingMessagesExtendFields.sql index 0777c89b76..1cb7fdb1d0 100644 --- a/modules/core/db/update/postgres/15/151228-sendingMessagesExtendFields.sql +++ b/modules/core/db/update/postgres/15/151228-sendingMessagesExtendFields.sql @@ -1,3 +1,3 @@ -alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO type text^ -alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME type text^ - +alter table SYS_SENDING_MESSAGE alter column ADDRESS_TO type text^ +alter table SYS_SENDING_MESSAGE alter column ATTACHMENTS_NAME type text^ + diff --git a/modules/core/db/update/postgres/15/1512282-addIsActiveToConstraint.sql b/modules/core/db/update/postgres/15/1512282-addIsActiveToConstraint.sql index 5898e8e2a6..64d67abc9f 100644 --- a/modules/core/db/update/postgres/15/1512282-addIsActiveToConstraint.sql +++ b/modules/core/db/update/postgres/15/1512282-addIsActiveToConstraint.sql @@ -1,2 +1,2 @@ -alter table SEC_CONSTRAINT add column IS_ACTIVE boolean default true^ - +alter table SEC_CONSTRAINT add column IS_ACTIVE boolean default true^ + diff --git a/modules/core/src/com/haulmont/cuba/core/EntityManager.java b/modules/core/src/com/haulmont/cuba/core/EntityManager.java index 334c1cb497..77169704d8 100644 --- a/modules/core/src/com/haulmont/cuba/core/EntityManager.java +++ b/modules/core/src/com/haulmont/cuba/core/EntityManager.java @@ -1,257 +1,257 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import javax.annotation.Nullable; -import java.sql.Connection; - -/** - * Interface used to interact with the persistence context. - * - *

Mostly mimics the {@code javax.persistence.EntityManager} interface and adds methods for working with views and - * soft deletion.

- */ -public interface EntityManager { - - /** - * Make an instance managed and persistent. - * - * @param entity entity instance - * @throws IllegalArgumentException if not an entity - */ - void persist(Entity entity); - - /** - * Merge the state of the given entity into the current persistence context. - *

If a new or patch entity (see {@code PersistenceHelper} methods) with non-null ID is passed to merge, - * EntityManager loads the corresponding object from the database and updates it with non-null values - * of attributes of the passed entity. If the object does not exist in the database, the passed entity is persisted - * and returned. - * - * @param entity entity instance - * @return the instance that the state was merged to - * @throws IllegalArgumentException if instance is not an entity or is a removed entity - * @see com.haulmont.cuba.core.global.PersistenceHelper#isNew(Object) - * @see com.haulmont.cuba.core.global.PersistenceHelper#makePatch(BaseGenericIdEntity) - */ - T merge(T entity); - - /** - * DEPRECATED. Use {@code com.haulmont.cuba.core.sys.EntityFetcher#fetch(Entity, View)} if needed. - */ - @Deprecated - T merge(T entity, @Nullable View view); - - /** - * DEPRECATED. Use {@code com.haulmont.cuba.core.sys.EntityFetcher#fetch(Entity, String)} if needed. - */ - @Deprecated - T merge(T entity, @Nullable String viewName); - - /** - * Remove the entity instance. - * What actually happens depends on {@link #isSoftDeletion} flag. - * - * @param entity entity instance - * @throws IllegalArgumentException if not an entity - */ - void remove(Entity entity); - - /** - * Find by primary key. - * - * @param entityClass entity class - * @param id entity id - * @return the found entity instance or null if the entity does not exist - * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument - * is not a valid type for that entity's primary key - */ - @Nullable - , K> T find(Class entityClass, K id); - - /** - * Find by primary key. - *

- * Due to accepting views, this method actually executes a {@link Query} which may lead to flushing of the - * persistence context and invoking listeners on modified entities. - * - * @param entityClass entity class - * @param id entity id - * @param views array of views - * @return the found entity instance or null if the entity does not exist - * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument - * is not a valid type for that entity's primary key - */ - @Nullable - , K> T find(Class entityClass, K id, View... views); - - /** - * Find by primary key. - *

- * Due to accepting views, this method actually executes a {@link Query} which may lead to flushing of the - * persistence context and invoking listeners on modified entities. - * - * @param entityClass entity class - * @param id entity id - * @param viewNames array of view names for this entity - * - * @return the found entity instance or null if the entity does not exist - * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument - * is not a valid type for that entity's primary key - */ - @Nullable - , K> T find(Class entityClass, K id, String... viewNames); - - /** - * Get an instance, whose state may be lazily fetched.
- * If the requested instance does not exist in the database, - * the EntityNotFoundException is thrown when the instance - * state is first accessed.
- * The application should not expect that the instance state will - * be available upon detachment, unless it was accessed by the - * application while the entity manager was open. - * - * @param entityClass entity class - * @param id entity id - * @return the found entity instance - * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument - * is not a valid type for that entity's primary key - * @throws javax.persistence.EntityNotFoundException if the entity state cannot be accessed - */ - , K> T getReference(Class entityClass, K id); - - /** - * Create an instance of Query for executing a Java Persistence query language statement. - * - * @return the new query instance - */ - Query createQuery(); - - /** - * Create an instance of Query for executing a Java Persistence query language statement. - * - * @param qlString a Java Persistence query string - * @return the new query instance - */ - Query createQuery(String qlString); - - /** - * Create a type-safe instance of Query for executing a Java Persistence query language statement. - * Can be used to conveniently perform select queries with runtime result type check. - * - * @param qlString a Java Persistence query string - * @param resultClass expected result class - * @return the new query instance - */ - TypedQuery createQuery(String qlString, Class resultClass); - - /** - * Create an instance of Query for executing a native SQL statement, e.g., for update or delete. - * - * @return the new query instance - */ - Query createNativeQuery(); - - /** - * Create an instance of Query for executing a native SQL statement, e.g., for update or delete.
- * - * @param sqlString a native SQL query string - * @return the new query instance - */ - Query createNativeQuery(String sqlString); - - /** - * Create an instance of Query for executing a native SQL statement and map its result to an entity.
- * - * @param sqlString a native SQL query string - * @param resultClass expected result class - * @return the new query instance - */ - TypedQuery createNativeQuery(String sqlString, Class resultClass); - - /** - * Reload an entity from DB according to a combined view defined by the given array of views. - *
Ensures all combined view attributes are loaded. - *
If the given entity is in managed state, the method returns the same object instance. If the entity is - * detached, the method returns a new object instance. - * - * @param entity entity instance to reload - * @param viewNames array of view names - * @return reloaded entity instance, or null if it has been deleted - */ - @Nullable - T reload(T entity, String... viewNames); - - /** - * Reload an entity from DB according to a combined view defined by the given array of views. - *
Ensures all combined view attributes are loaded. - *
If the given entity is in managed state, the method returns the same object instance. If the entity is - * detached, the method returns a new object instance. - * - * @param entity entity instance to reload - * @param viewNames array of view names - * @return reloaded entity instance - * @throws javax.persistence.EntityNotFoundException if the entity has been deleted - */ - T reloadNN(T entity, String... viewNames); - - /** - * Synchronize the persistence context to the underlying database. - */ - void flush(); - - /** - * @return true if the EntityManager is in SoftDeletion mode - */ - boolean isSoftDeletion(); - - /** - * Set SoftDeletion mode for this EntityManager. - * - * @param softDeletion mode - */ - void setSoftDeletion(boolean softDeletion); - - /** - * @return database connection associated with the current transaction. - *

Don't close this connection after use, it will be automatically closed on transaction end. - */ - Connection getConnection(); - - /** - * @return underlying implementation provided by ORM - */ - javax.persistence.EntityManager getDelegate(); - - /** - * DEPRECATED since v.6 - */ - @Deprecated - void fetch(Entity entity, View view); - - /** - * DEPRECATED since v.6. - * Use {@link #find(Class, Object, String...)} - */ - @Deprecated - @Nullable - , K> T reload(Class entityClass, K id, String... viewNames); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import javax.annotation.Nullable; +import java.sql.Connection; + +/** + * Interface used to interact with the persistence context. + * + *

Mostly mimics the {@code javax.persistence.EntityManager} interface and adds methods for working with views and + * soft deletion.

+ */ +public interface EntityManager { + + /** + * Make an instance managed and persistent. + * + * @param entity entity instance + * @throws IllegalArgumentException if not an entity + */ + void persist(Entity entity); + + /** + * Merge the state of the given entity into the current persistence context. + *

If a new or patch entity (see {@code PersistenceHelper} methods) with non-null ID is passed to merge, + * EntityManager loads the corresponding object from the database and updates it with non-null values + * of attributes of the passed entity. If the object does not exist in the database, the passed entity is persisted + * and returned. + * + * @param entity entity instance + * @return the instance that the state was merged to + * @throws IllegalArgumentException if instance is not an entity or is a removed entity + * @see com.haulmont.cuba.core.global.PersistenceHelper#isNew(Object) + * @see com.haulmont.cuba.core.global.PersistenceHelper#makePatch(BaseGenericIdEntity) + */ + T merge(T entity); + + /** + * DEPRECATED. Use {@code com.haulmont.cuba.core.sys.EntityFetcher#fetch(Entity, View)} if needed. + */ + @Deprecated + T merge(T entity, @Nullable View view); + + /** + * DEPRECATED. Use {@code com.haulmont.cuba.core.sys.EntityFetcher#fetch(Entity, String)} if needed. + */ + @Deprecated + T merge(T entity, @Nullable String viewName); + + /** + * Remove the entity instance. + * What actually happens depends on {@link #isSoftDeletion} flag. + * + * @param entity entity instance + * @throws IllegalArgumentException if not an entity + */ + void remove(Entity entity); + + /** + * Find by primary key. + * + * @param entityClass entity class + * @param id entity id + * @return the found entity instance or null if the entity does not exist + * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument + * is not a valid type for that entity's primary key + */ + @Nullable + , K> T find(Class entityClass, K id); + + /** + * Find by primary key. + *

+ * Due to accepting views, this method actually executes a {@link Query} which may lead to flushing of the + * persistence context and invoking listeners on modified entities. + * + * @param entityClass entity class + * @param id entity id + * @param views array of views + * @return the found entity instance or null if the entity does not exist + * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument + * is not a valid type for that entity's primary key + */ + @Nullable + , K> T find(Class entityClass, K id, View... views); + + /** + * Find by primary key. + *

+ * Due to accepting views, this method actually executes a {@link Query} which may lead to flushing of the + * persistence context and invoking listeners on modified entities. + * + * @param entityClass entity class + * @param id entity id + * @param viewNames array of view names for this entity + * + * @return the found entity instance or null if the entity does not exist + * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument + * is not a valid type for that entity's primary key + */ + @Nullable + , K> T find(Class entityClass, K id, String... viewNames); + + /** + * Get an instance, whose state may be lazily fetched.
+ * If the requested instance does not exist in the database, + * the EntityNotFoundException is thrown when the instance + * state is first accessed.
+ * The application should not expect that the instance state will + * be available upon detachment, unless it was accessed by the + * application while the entity manager was open. + * + * @param entityClass entity class + * @param id entity id + * @return the found entity instance + * @throws IllegalArgumentException if the first argument does not denote an entity type or the second argument + * is not a valid type for that entity's primary key + * @throws javax.persistence.EntityNotFoundException if the entity state cannot be accessed + */ + , K> T getReference(Class entityClass, K id); + + /** + * Create an instance of Query for executing a Java Persistence query language statement. + * + * @return the new query instance + */ + Query createQuery(); + + /** + * Create an instance of Query for executing a Java Persistence query language statement. + * + * @param qlString a Java Persistence query string + * @return the new query instance + */ + Query createQuery(String qlString); + + /** + * Create a type-safe instance of Query for executing a Java Persistence query language statement. + * Can be used to conveniently perform select queries with runtime result type check. + * + * @param qlString a Java Persistence query string + * @param resultClass expected result class + * @return the new query instance + */ + TypedQuery createQuery(String qlString, Class resultClass); + + /** + * Create an instance of Query for executing a native SQL statement, e.g., for update or delete. + * + * @return the new query instance + */ + Query createNativeQuery(); + + /** + * Create an instance of Query for executing a native SQL statement, e.g., for update or delete.
+ * + * @param sqlString a native SQL query string + * @return the new query instance + */ + Query createNativeQuery(String sqlString); + + /** + * Create an instance of Query for executing a native SQL statement and map its result to an entity.
+ * + * @param sqlString a native SQL query string + * @param resultClass expected result class + * @return the new query instance + */ + TypedQuery createNativeQuery(String sqlString, Class resultClass); + + /** + * Reload an entity from DB according to a combined view defined by the given array of views. + *
Ensures all combined view attributes are loaded. + *
If the given entity is in managed state, the method returns the same object instance. If the entity is + * detached, the method returns a new object instance. + * + * @param entity entity instance to reload + * @param viewNames array of view names + * @return reloaded entity instance, or null if it has been deleted + */ + @Nullable + T reload(T entity, String... viewNames); + + /** + * Reload an entity from DB according to a combined view defined by the given array of views. + *
Ensures all combined view attributes are loaded. + *
If the given entity is in managed state, the method returns the same object instance. If the entity is + * detached, the method returns a new object instance. + * + * @param entity entity instance to reload + * @param viewNames array of view names + * @return reloaded entity instance + * @throws javax.persistence.EntityNotFoundException if the entity has been deleted + */ + T reloadNN(T entity, String... viewNames); + + /** + * Synchronize the persistence context to the underlying database. + */ + void flush(); + + /** + * @return true if the EntityManager is in SoftDeletion mode + */ + boolean isSoftDeletion(); + + /** + * Set SoftDeletion mode for this EntityManager. + * + * @param softDeletion mode + */ + void setSoftDeletion(boolean softDeletion); + + /** + * @return database connection associated with the current transaction. + *

Don't close this connection after use, it will be automatically closed on transaction end. + */ + Connection getConnection(); + + /** + * @return underlying implementation provided by ORM + */ + javax.persistence.EntityManager getDelegate(); + + /** + * DEPRECATED since v.6 + */ + @Deprecated + void fetch(Entity entity, View view); + + /** + * DEPRECATED since v.6. + * Use {@link #find(Class, Object, String...)} + */ + @Deprecated + @Nullable + , K> T reload(Class entityClass, K id, String... viewNames); +} diff --git a/modules/core/src/com/haulmont/cuba/core/Query.java b/modules/core/src/com/haulmont/cuba/core/Query.java index 163b0d0906..2e7b54afd8 100644 --- a/modules/core/src/com/haulmont/cuba/core/Query.java +++ b/modules/core/src/com/haulmont/cuba/core/Query.java @@ -1,252 +1,252 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import javax.annotation.Nullable; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; -import javax.persistence.TemporalType; -import java.util.List; -import java.util.Date; - -/** - * Interface used to control query execution. - * - *
Consider use of {@link TypedQuery} instead of this interface. - */ -public interface Query { - /** - * Get the query string. - * - * @return query string - */ - String getQueryString(); - - /** - * Set the query string. - * - * @param queryString query string - */ - Query setQueryString(String queryString); - - /** - * Execute a SELECT query and return the query results as a List. - * - * @return a list of the results - * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement - */ - List getResultList(); - - /** - * Execute a SELECT query that returns a single result. - * - * @return the result - * @throws javax.persistence.NoResultException if there is no result - * @throws javax.persistence.NonUniqueResultException if more than one result - * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement - */ - Object getSingleResult(); - - /** - * Execute a SELECT query.
- * Returns null if there is no result.
- * Returns first result if more than one result. - * - * @return the result - * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement - */ - @Nullable - Object getFirstResult(); - - /** - * Execute an update or delete statement. - * - * @return the number of entities updated or deleted - * @throws IllegalStateException if called for a Java Persistence query language SELECT statement - * @throws javax.persistence.TransactionRequiredException if there is no transaction - */ - int executeUpdate(); - - /** - * Set the maximum number of results to retrieve. - * - * @return the same query instance - * @throws IllegalArgumentException if argument is negative - */ - Query setMaxResults(int maxResult); - - /** - * Set the position of the first result to retrieve. - * - * @param startPosition position of the first result, numbered from 0 - * @return the same query instance - * @throws IllegalArgumentException if argument is negative - */ - Query setFirstResult(int startPosition); - - /** - * Bind an argument to a named parameter.
- *
- * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with - * number sign in native SQL queries (e.g. {@code #foo}). - * - * @param name parameter name - * @param value parameter value. Entity instance replaced with its ID. - * @return the same query instance - * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string - * or argument is of incorrect type - */ - Query setParameter(String name, Object value); - - /** - * Bind an argument to a named parameter.
- *
- * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with - * number sign in native SQL queries (e.g. {@code #foo}). - * - * @param name parameter name - * @param value parameter value - * @param implicitConversions whether to make parameter value conversions, e.g. convert an entity to its ID - * @return the same query instance - * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string - * or argument is of incorrect type - */ - Query setParameter(String name, Object value, boolean implicitConversions); - - /** - * Bind an instance of java.util.Date to a named parameter.
- *

- * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with - * number sign in native SQL queries (e.g. {@code #foo}). - * - * @param name parameter name - * @param value parameter value - * @param temporalType type of Date value - * @return the same query instance - * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string - */ - Query setParameter(String name, Date value, TemporalType temporalType); - - /** - * Bind an argument to a positional parameter. - *

- * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). - * - * @param position parameter position, starting with 1 - * @param value parameter value. Entity instance replaced with its ID. - * @return the same query instance - * @throws IllegalArgumentException if position does not correspond to positional parameter of query - * or argument is of incorrect type - */ - Query setParameter(int position, Object value); - - /** - * Bind an argument to a positional parameter. - *

- * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). - * - * @param position parameter position, starting with 1 - * @param value parameter value - * @param implicitConversions whether to make parameter value conversions, e.g. convert an entity to its ID - * @return the same query instance - * @throws IllegalArgumentException if position does not correspond to positional parameter of query - * or argument is of incorrect type - */ - Query setParameter(int position, Object value, boolean implicitConversions); - - /** - * Bind an instance of java.util.Date to a positional parameter. - *
- * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). - * - * @param position parameter position, starting with 1 - * @param value parameter value - * @param temporalType type of Date value - * @return the same query instance - * @throws IllegalArgumentException if position does not correspond to positional parameter of query - */ - Query setParameter(int position, Date value, TemporalType temporalType); - - /** - * Set the lock mode type to be used for the query execution. - * - * @param lockMode lock mode - * @return the same query instance - */ - Query setLockMode(LockModeType lockMode); - - /** - * Set View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param view view instance. If null, eager fetching is performed according to JPA mappings. - * @return the same query instance - */ - Query setView(@Nullable View view); - - /** - * Set View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param entityClass entity class to get a view instance by the name provided - * @param viewName view name - * @return the same query instance - */ - Query setView(Class entityClass, String viewName); - - /** - * Adds View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param view view instance - must not be null - * @return the same query instance - */ - Query addView(View view); - - /** - * Adds View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param entityClass entity class to get a view instance by the name provided - * @param viewName view name - must not be null - * @return the same query instance - */ - Query addView(Class entityClass, String viewName); - - /** - * Indicates that the query results should be cached. - * - * @return the same query instance - */ - Query setCacheable(boolean cacheable); - - /** - * Set the flush mode type to be used for the query execution. - * - * @param flushMode flush mode - * @return the same query instance - */ - Query setFlushMode(FlushModeType flushMode); - - /** - * @return underlying implementation provided by ORM - */ - javax.persistence.Query getDelegate(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import javax.annotation.Nullable; +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import javax.persistence.TemporalType; +import java.util.List; +import java.util.Date; + +/** + * Interface used to control query execution. + * + *
Consider use of {@link TypedQuery} instead of this interface. + */ +public interface Query { + /** + * Get the query string. + * + * @return query string + */ + String getQueryString(); + + /** + * Set the query string. + * + * @param queryString query string + */ + Query setQueryString(String queryString); + + /** + * Execute a SELECT query and return the query results as a List. + * + * @return a list of the results + * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement + */ + List getResultList(); + + /** + * Execute a SELECT query that returns a single result. + * + * @return the result + * @throws javax.persistence.NoResultException if there is no result + * @throws javax.persistence.NonUniqueResultException if more than one result + * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement + */ + Object getSingleResult(); + + /** + * Execute a SELECT query.
+ * Returns null if there is no result.
+ * Returns first result if more than one result. + * + * @return the result + * @throws IllegalStateException if called for a Java Persistence query language UPDATE or DELETE statement + */ + @Nullable + Object getFirstResult(); + + /** + * Execute an update or delete statement. + * + * @return the number of entities updated or deleted + * @throws IllegalStateException if called for a Java Persistence query language SELECT statement + * @throws javax.persistence.TransactionRequiredException if there is no transaction + */ + int executeUpdate(); + + /** + * Set the maximum number of results to retrieve. + * + * @return the same query instance + * @throws IllegalArgumentException if argument is negative + */ + Query setMaxResults(int maxResult); + + /** + * Set the position of the first result to retrieve. + * + * @param startPosition position of the first result, numbered from 0 + * @return the same query instance + * @throws IllegalArgumentException if argument is negative + */ + Query setFirstResult(int startPosition); + + /** + * Bind an argument to a named parameter.
+ *
+ * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with + * number sign in native SQL queries (e.g. {@code #foo}). + * + * @param name parameter name + * @param value parameter value. Entity instance replaced with its ID. + * @return the same query instance + * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string + * or argument is of incorrect type + */ + Query setParameter(String name, Object value); + + /** + * Bind an argument to a named parameter.
+ *
+ * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with + * number sign in native SQL queries (e.g. {@code #foo}). + * + * @param name parameter name + * @param value parameter value + * @param implicitConversions whether to make parameter value conversions, e.g. convert an entity to its ID + * @return the same query instance + * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string + * or argument is of incorrect type + */ + Query setParameter(String name, Object value, boolean implicitConversions); + + /** + * Bind an instance of java.util.Date to a named parameter.
+ *

+ * In the query text, named parameters are marked with colon (e.g. {@code :foo}) in JPQL queries or with + * number sign in native SQL queries (e.g. {@code #foo}). + * + * @param name parameter name + * @param value parameter value + * @param temporalType type of Date value + * @return the same query instance + * @throws IllegalArgumentException if parameter name does not correspond to parameter in query string + */ + Query setParameter(String name, Date value, TemporalType temporalType); + + /** + * Bind an argument to a positional parameter. + *

+ * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). + * + * @param position parameter position, starting with 1 + * @param value parameter value. Entity instance replaced with its ID. + * @return the same query instance + * @throws IllegalArgumentException if position does not correspond to positional parameter of query + * or argument is of incorrect type + */ + Query setParameter(int position, Object value); + + /** + * Bind an argument to a positional parameter. + *

+ * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). + * + * @param position parameter position, starting with 1 + * @param value parameter value + * @param implicitConversions whether to make parameter value conversions, e.g. convert an entity to its ID + * @return the same query instance + * @throws IllegalArgumentException if position does not correspond to positional parameter of query + * or argument is of incorrect type + */ + Query setParameter(int position, Object value, boolean implicitConversions); + + /** + * Bind an instance of java.util.Date to a positional parameter. + *
+ * In the query text, positional parameters are marked with ?N (e.g. {@code ?1}). + * + * @param position parameter position, starting with 1 + * @param value parameter value + * @param temporalType type of Date value + * @return the same query instance + * @throws IllegalArgumentException if position does not correspond to positional parameter of query + */ + Query setParameter(int position, Date value, TemporalType temporalType); + + /** + * Set the lock mode type to be used for the query execution. + * + * @param lockMode lock mode + * @return the same query instance + */ + Query setLockMode(LockModeType lockMode); + + /** + * Set View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param view view instance. If null, eager fetching is performed according to JPA mappings. + * @return the same query instance + */ + Query setView(@Nullable View view); + + /** + * Set View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param entityClass entity class to get a view instance by the name provided + * @param viewName view name + * @return the same query instance + */ + Query setView(Class entityClass, String viewName); + + /** + * Adds View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param view view instance - must not be null + * @return the same query instance + */ + Query addView(View view); + + /** + * Adds View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param entityClass entity class to get a view instance by the name provided + * @param viewName view name - must not be null + * @return the same query instance + */ + Query addView(Class entityClass, String viewName); + + /** + * Indicates that the query results should be cached. + * + * @return the same query instance + */ + Query setCacheable(boolean cacheable); + + /** + * Set the flush mode type to be used for the query execution. + * + * @param flushMode flush mode + * @return the same query instance + */ + Query setFlushMode(FlushModeType flushMode); + + /** + * @return underlying implementation provided by ORM + */ + javax.persistence.Query getDelegate(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/Transaction.java b/modules/core/src/com/haulmont/cuba/core/Transaction.java index ed61ba3862..1ea73519cf 100644 --- a/modules/core/src/com/haulmont/cuba/core/Transaction.java +++ b/modules/core/src/com/haulmont/cuba/core/Transaction.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -/** - * Programmatic transaction control interface. Supports the following usage scenarios. - * - *

Try-with-resources scenario: - *

{@code
- *     try (Transaction tx = persistence.createTransaction()) {
- *         // transactional code here
- *         tx.commit();
- *     }
- * }
- * - *

Lambda scenario: - *

{@code
- *     persistence.createTransaction().execute((EntityManager em) -> {
- *         // transactional code here
- *     });
- * }
- * - * @see Persistence#runInTransaction(Runnable) - * @see Persistence#callInTransaction(Callable) - */ -public interface Transaction extends AutoCloseable { - - /** - * Interface for transactional code. - * @param result type - */ - interface Callable { - /** - * Gets called within a transaction. - * - * @param em current EntityManager instance - * @return result object that in turn returns from {@link Transaction#execute(com.haulmont.cuba.core.Transaction.Callable)}. - */ - T call(EntityManager em); - } - - /** - * Interface for transactional code that is not intended to return a result. - */ - interface Runnable { - /** - * Gets called within a transaction. - * - * @param em current EntityManager instance - */ - void run(EntityManager em); - } - - /** - * Executes the action specified by the given single method object within a transaction in the main data store. - * - * @see #execute(String, Callable) - */ - T execute(Callable callable); - - /** - * Executes the action specified by the given single method object within a transaction. - *
Returns a result object created within the transaction. - *
A {@code RuntimeException} thrown in the transactional code enforces a rollback. - * - * @param storeName data store name - * @param callable transactional code in the form of {@link Callable} - * @param result type - * @return result object - */ - T execute(String storeName, Callable callable); - - /** - * Executes the action specified by the given single method object within a transaction in the main data store. - * - * @see #execute(String, Runnable) - */ - void execute(Runnable runnable); - - /** - * Executes the action specified by the given single method object within a transaction. - *
A {@code RuntimeException} thrown in the transactional code enforces a rollback. - * - * @param storeName data store name - * @param runnable transactional code in the form of {@link Runnable} - */ - void execute(String storeName, Runnable runnable); - - /** - * Commit current transaction. - */ - void commit(); - - /** - * Commit current transaction and immediately start a new one. - */ - void commitRetaining(); - - /** - * This method has to be invoked in the following construct: - *
{@code
-     *     Transaction tx = ...
-     *     try {
-     *         ...
-     *         tx.commit();
-     *     } finally {
-     *         tx.end();
-     *     }
-     * }
- * In case of successful commit this method does nothing. Otherwise it rollbacks the current transaction. - */ - void end(); - - @Override - void close(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +/** + * Programmatic transaction control interface. Supports the following usage scenarios. + * + *

Try-with-resources scenario: + *

{@code
+ *     try (Transaction tx = persistence.createTransaction()) {
+ *         // transactional code here
+ *         tx.commit();
+ *     }
+ * }
+ * + *

Lambda scenario: + *

{@code
+ *     persistence.createTransaction().execute((EntityManager em) -> {
+ *         // transactional code here
+ *     });
+ * }
+ * + * @see Persistence#runInTransaction(Runnable) + * @see Persistence#callInTransaction(Callable) + */ +public interface Transaction extends AutoCloseable { + + /** + * Interface for transactional code. + * @param result type + */ + interface Callable { + /** + * Gets called within a transaction. + * + * @param em current EntityManager instance + * @return result object that in turn returns from {@link Transaction#execute(com.haulmont.cuba.core.Transaction.Callable)}. + */ + T call(EntityManager em); + } + + /** + * Interface for transactional code that is not intended to return a result. + */ + interface Runnable { + /** + * Gets called within a transaction. + * + * @param em current EntityManager instance + */ + void run(EntityManager em); + } + + /** + * Executes the action specified by the given single method object within a transaction in the main data store. + * + * @see #execute(String, Callable) + */ + T execute(Callable callable); + + /** + * Executes the action specified by the given single method object within a transaction. + *
Returns a result object created within the transaction. + *
A {@code RuntimeException} thrown in the transactional code enforces a rollback. + * + * @param storeName data store name + * @param callable transactional code in the form of {@link Callable} + * @param result type + * @return result object + */ + T execute(String storeName, Callable callable); + + /** + * Executes the action specified by the given single method object within a transaction in the main data store. + * + * @see #execute(String, Runnable) + */ + void execute(Runnable runnable); + + /** + * Executes the action specified by the given single method object within a transaction. + *
A {@code RuntimeException} thrown in the transactional code enforces a rollback. + * + * @param storeName data store name + * @param runnable transactional code in the form of {@link Runnable} + */ + void execute(String storeName, Runnable runnable); + + /** + * Commit current transaction. + */ + void commit(); + + /** + * Commit current transaction and immediately start a new one. + */ + void commitRetaining(); + + /** + * This method has to be invoked in the following construct: + *
{@code
+     *     Transaction tx = ...
+     *     try {
+     *         ...
+     *         tx.commit();
+     *     } finally {
+     *         tx.end();
+     *     }
+     * }
+ * In case of successful commit this method does nothing. Otherwise it rollbacks the current transaction. + */ + void end(); + + @Override + void close(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/TypedQuery.java b/modules/core/src/com/haulmont/cuba/core/TypedQuery.java index c33e0fa757..e73300e02b 100644 --- a/modules/core/src/com/haulmont/cuba/core/TypedQuery.java +++ b/modules/core/src/com/haulmont/cuba/core/TypedQuery.java @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import javax.annotation.Nullable; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; -import javax.persistence.TemporalType; -import java.util.Date; -import java.util.List; - -/** - * Type-safe extension of Query interface. - */ -public interface TypedQuery extends Query { - - @Override - List getResultList(); - - @Override - T getSingleResult(); - - @Override - @Nullable - T getFirstResult(); - - @Override - TypedQuery setMaxResults(int maxResults); - - @Override - TypedQuery setFirstResult(int firstResult); - - @Override - TypedQuery setParameter(String name, Object value); - - @Override - TypedQuery setParameter(String name, Object value, boolean implicitConversions); - - @Override - TypedQuery setParameter(String name, Date value, TemporalType temporalType); - - @Override - TypedQuery setParameter(int position, Object value); - - @Override - TypedQuery setParameter(int position, Object value, boolean implicitConversions); - - @Override - TypedQuery setParameter(int position, Date value, TemporalType temporalType); - - @Override - TypedQuery setLockMode(LockModeType lockMode); - - @Override - TypedQuery setView(@Nullable View view); - - @Override - TypedQuery setView(Class entityClass, String viewName); - - @Override - TypedQuery addView(View view); - - @Override - TypedQuery addView(Class entityClass, String viewName); - - /** - * Set View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param viewName view name - must not be null - * @return the same query instance - */ - TypedQuery setViewName(String viewName); - - /** - * Adds View for this Query instance. - *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. - * - * @param viewName view name - must not be null - * @return the same query instance - */ - TypedQuery addViewName(String viewName); - - /** - * Set query results to be cached - * @param cacheable whether query is cacheable - * @return the same query instance - */ - TypedQuery setCacheable(boolean cacheable); - - /** - * Set the flush mode type to be used for the query execution. - * @param flushMode flush mode - * @return the same query instance - */ - TypedQuery setFlushMode(FlushModeType flushMode); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import javax.annotation.Nullable; +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import javax.persistence.TemporalType; +import java.util.Date; +import java.util.List; + +/** + * Type-safe extension of Query interface. + */ +public interface TypedQuery extends Query { + + @Override + List getResultList(); + + @Override + T getSingleResult(); + + @Override + @Nullable + T getFirstResult(); + + @Override + TypedQuery setMaxResults(int maxResults); + + @Override + TypedQuery setFirstResult(int firstResult); + + @Override + TypedQuery setParameter(String name, Object value); + + @Override + TypedQuery setParameter(String name, Object value, boolean implicitConversions); + + @Override + TypedQuery setParameter(String name, Date value, TemporalType temporalType); + + @Override + TypedQuery setParameter(int position, Object value); + + @Override + TypedQuery setParameter(int position, Object value, boolean implicitConversions); + + @Override + TypedQuery setParameter(int position, Date value, TemporalType temporalType); + + @Override + TypedQuery setLockMode(LockModeType lockMode); + + @Override + TypedQuery setView(@Nullable View view); + + @Override + TypedQuery setView(Class entityClass, String viewName); + + @Override + TypedQuery addView(View view); + + @Override + TypedQuery addView(Class entityClass, String viewName); + + /** + * Set View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param viewName view name - must not be null + * @return the same query instance + */ + TypedQuery setViewName(String viewName); + + /** + * Adds View for this Query instance. + *
All non-lazy view properties contained in a combination of all added views are eagerly fetched. + * + * @param viewName view name - must not be null + * @return the same query instance + */ + TypedQuery addViewName(String viewName); + + /** + * Set query results to be cached + * @param cacheable whether query is cacheable + * @return the same query instance + */ + TypedQuery setCacheable(boolean cacheable); + + /** + * Set the flush mode type to be used for the query execution. + * @param flushMode flush mode + * @return the same query instance + */ + TypedQuery setFlushMode(FlushModeType flushMode); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/AttributeSecuritySupport.java b/modules/core/src/com/haulmont/cuba/core/app/AttributeSecuritySupport.java index 8f010a31c2..0321a40375 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/AttributeSecuritySupport.java +++ b/modules/core/src/com/haulmont/cuba/core/app/AttributeSecuritySupport.java @@ -1,410 +1,410 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.google.common.collect.Sets; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.PersistenceSecurity; -import com.haulmont.cuba.core.app.events.SetupAttributeAccessEvent; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.CubaApplicationEventMulticaster; -import com.haulmont.cuba.core.sys.SecurityTokenManager; -import com.haulmont.cuba.core.sys.persistence.CubaEntityFetchGroup; -import org.eclipse.persistence.queries.FetchGroup; -import org.eclipse.persistence.queries.FetchGroupTracker; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; - -import javax.inject.Inject; -import java.util.*; - -import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.*; -import static java.lang.String.format; - -/** - * Supports enforcing entity attribute permissions on Middleware. - */ -@Component(AttributeSecuritySupport.NAME) -public class AttributeSecuritySupport { - - public static final String NAME = "cuba_AttributeSecuritySupport"; - - @Inject - protected Metadata metadata; - - @Inject - protected MetadataTools metadataTools; - - @Inject - protected PersistenceSecurity security; - - @Inject - protected ServerConfig config; - - @Inject - protected SecurityTokenManager securityTokenManager; - - @Inject - protected Events events; - - @Inject - protected EntityStates entityStates; - - @Inject - protected CubaApplicationEventMulticaster applicationEventMulticaster; - - /** - * Removes restricted attributes from a view. - * - * @param view source view - * @return restricted view - */ - public View createRestrictedView(View view) { - if (!isAuthorizationRequired()) { - return view; - } - Preconditions.checkNotNullArgument(view, "view is null"); - - View restrictedView = new View(view.getEntityClass(), - StringUtils.isEmpty(view.getName()) ? "" : view.getName() + "_restricted", - false); // do not include system properties in constructor because they will be copied later if exist - copyViewConsideringPermissions(view, restrictedView); - return restrictedView; - } - - private void copyViewConsideringPermissions(View srcView, View dstView) { - MetaClass metaClass = metadata.getClassNN(srcView.getEntityClass()); - for (ViewProperty property : srcView.getProperties()) { - if (security.isEntityAttrReadPermitted(metaClass, property.getName())) { - View viewCopy = null; - if (property.getView() != null) { - viewCopy = new View(property.getView().getEntityClass(), property.getView().getName() + "(restricted)", false); - copyViewConsideringPermissions(property.getView(), viewCopy); - } - dstView.addProperty(property.getName(), viewCopy, property.getFetchMode()); - } - } - } - - /** - * Should be called after loading an entity from the database. - * - * @param entity just loaded detached entity - */ - public void afterLoad(Entity entity) { - if (!isAuthorizationRequired()) { - return; - } - if (entity != null) { - metadataTools.traverseAttributes(entity, new FillingInaccessibleAttributesVisitor()); - } - } - - /** - * Should be called after loading a list of entities from the database. - * - * @param entities list of just loaded detached entities - */ - public void afterLoad(Collection entities) { - Preconditions.checkNotNullArgument(entities, "entities list is null"); - - for (Entity entity : entities) { - afterLoad(entity); - } - } - - /** - * Should be called before persisting a new entity. - * - * @param entity new entity - */ - public void beforePersist(Entity entity) { - if (!isAuthorizationRequired()) { - return; - } - // check only immediate attributes, otherwise persisted entity can be unusable for calling code - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - for (MetaProperty metaProperty : metaClass.getProperties()) { - if (!metadataTools.isSystem(metaProperty) - && !metaProperty.isReadOnly() - && !security.isEntityAttrUpdatePermitted(metaClass, metaProperty.getName())) { - entity.setValue(metaProperty.getName(), null); - } - } - } - - /** - * Should be called before merging an entity. - * - * @param entity detached entity - */ - public void beforeMerge(Entity entity) { - if (!isAuthorizationRequired()) { - return; - } - checkRequiredAttributes(entity); - applySecurityToFetchGroup(entity); - //apply fetch group constraints to embedded - for (MetaProperty metaProperty : entity.getMetaClass().getProperties()) { - String name = metaProperty.getName(); - if (metadataTools.isEmbedded(metaProperty) && entityStates.isLoaded(entity, name)) { - Entity embedded = entity.getValue(name); - checkRequiredAttributes(embedded); - applySecurityToFetchGroup(embedded); - } - } - } - - /** - * Should be called after merging an entity and before transaction commit. - * - * @param entity detached entity - */ - public void afterMerge(Entity entity) { - if (entity instanceof BaseGenericIdEntity) { - BaseGenericIdEntity genericIdEntity = (BaseGenericIdEntity) entity; - setupAttributeAccess(genericIdEntity); - metadataTools.traverseAttributes(genericIdEntity, new AttributeAccessVisitor(Sets.newHashSet(entity))); - } - } - - /** - * Should be called after merging an entity and transaction commit. - * - * @param entity detached entity - */ - public void afterCommit(Entity entity) { - if (!isAuthorizationRequired()) { - return; - } - if (entity != null) { - metadataTools.traverseAttributes(entity, new ClearInaccessibleAttributesVisitor()); - } - } - - public void onLoad(Collection entities, View view) { - Preconditions.checkNotNullArgument(entities, "entities list is null"); - - for (Entity entity : entities) { - onLoad(entity, view); - } - } - - public void onLoad(Entity entity, View view) { - if (entity instanceof BaseGenericIdEntity) { - BaseGenericIdEntity genericIdEntity = (BaseGenericIdEntity) entity; - setupAttributeAccess(genericIdEntity); - metadataTools.traverseAttributesByView(view, genericIdEntity, new AttributeAccessVisitor(Sets.newHashSet(entity))); - } - } - - public void setupAttributeAccess(T entity) { - if (entity instanceof BaseGenericIdEntity || entity instanceof EmbeddableEntity) { - SetupAttributeAccessEvent event = new SetupAttributeAccessEvent<>(entity); - events.publish(event); - if (event.getReadonlyAttributes() != null) { - Set attributes = event.getReadonlyAttributes(); - SecurityState state = getOrCreateSecurityState(entity); - addReadonlyAttributes(state, attributes.toArray(new String[attributes.size()])); - } - if (event.getRequiredAttributes() != null) { - Set attributes = event.getRequiredAttributes(); - SecurityState state = getOrCreateSecurityState(entity); - addRequiredAttributes(state, attributes.toArray(new String[attributes.size()])); - } - if (event.getHiddenAttributes() != null) { - Set attributes = event.getHiddenAttributes(); - SecurityState state = getOrCreateSecurityState(entity); - addHiddenAttributes(state, attributes.toArray(new String[attributes.size()])); - } - if (isAttributeAccessEnabled(event)) { - securityTokenManager.writeSecurityToken(entity); - } - } - } - - /** - * Checks if attribute access enabled for the current entity type. - * It's based on the existence of an event listener for SetupAttributeAccessEvent. - * @param entityClass - entity metaClass - */ - @SuppressWarnings("unchecked") - public boolean isAttributeAccessEnabled(MetaClass entityClass) { - return isAttributeAccessEnabled(new SetupAttributeAccessEvent(metadata.create(entityClass))); - } - - /** - * Checks if attribute access enabled for the current entity type. - * It's based on the existence of an event listener for SetupAttributeAccessEvent. - * @param event - SetupAttributeAccessEvent - */ - public boolean isAttributeAccessEnabled(SetupAttributeAccessEvent event) { - Collection listeners = applicationEventMulticaster.getApplicationListeners(event, event.getResolvableType()); - return listeners != null && listeners.size() > 0; - } - - protected void checkRequiredAttributes(Entity entity) { - SecurityState securityState = getSecurityState(entity); - if (securityState != null && !securityState.getRequiredAttributes().isEmpty()) { - for (MetaProperty metaProperty : entity.getMetaClass().getProperties()) { - String propertyName = metaProperty.getName(); - if (BaseEntityInternalAccess.isRequired(securityState, propertyName) && entity.getValue(propertyName) == null) { - throw new RowLevelSecurityException(format("Attribute [%s] is required for entity %s", propertyName, entity), - entity.getMetaClass().getName()); - } - } - } - } - - protected void applySecurityToFetchGroup(Entity entity) { - if (entity == null) { - return; - } - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - FetchGroupTracker fetchGroupTracker = (FetchGroupTracker) entity; - FetchGroup fetchGroup = fetchGroupTracker._persistence_getFetchGroup(); - SecurityState securityState = getSecurityState(entity); - if (fetchGroup != null) { - List attributesToRemove = new ArrayList<>(); - for (String attrName : fetchGroup.getAttributeNames()) { - String[] parts = attrName.split("\\."); - if (parts.length > 0 && BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, parts[0])) { - attributesToRemove.add(attrName); - } else { - MetaClass currentMetaClass = metaClass; - for (String part : parts) { - if (!security.isEntityAttrUpdatePermitted(currentMetaClass, part)) { - attributesToRemove.add(attrName); - break; - } - MetaProperty metaProperty = currentMetaClass.getPropertyNN(part); - if (metaProperty.getRange().isClass()) { - currentMetaClass = metaProperty.getRange().asClass(); - } - } - } - } - if (!attributesToRemove.isEmpty()) { - List attributeNames = new ArrayList<>(fetchGroup.getAttributeNames()); - attributeNames.removeAll(attributesToRemove); - fetchGroupTracker._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames)); - } - } else { - List attributeNames = new ArrayList<>(); - for (MetaProperty metaProperty : metaClass.getProperties()) { - String propertyName = metaProperty.getName(); - if (metadataTools.isSystem(metaProperty)) { - attributeNames.add(propertyName); - } - if (security.isEntityAttrUpdatePermitted(metaClass, propertyName) && - !BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, propertyName)) { - attributeNames.add(metaProperty.getName()); - } - } - fetchGroupTracker._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames)); - } - } - - private void addInaccessibleAttribute(Entity entity, String property) { - SecurityState securityState = getOrCreateSecurityState(entity); - String[] attributes = getInaccessibleAttributes(securityState); - attributes = attributes == null ? new String[1] : Arrays.copyOf(attributes, attributes.length + 1); - attributes[attributes.length - 1] = property; - setInaccessibleAttributes(securityState, attributes); - } - - protected boolean isAuthorizationRequired() { - return (AppContext.getSecurityContextNN().isAuthorizationRequired() || config.getDataManagerChecksSecurityOnMiddleware()) - && config.getEntityAttributePermissionChecking(); - } - - protected void setNullPropertyValue(Entity entity, MetaProperty property) { - // Using reflective access to field because the attribute can be unfetched if loading not partial entities, - // which is the case when in-memory constraints exist - BaseEntityInternalAccess.setValue(entity, property.getName(), null); - if (property.getRange().isClass()) { - BaseEntityInternalAccess.setValueForHolder(entity, property.getName(), null); - } - } - - protected class FillingInaccessibleAttributesVisitor implements EntityAttributeVisitor { - @Override - public boolean skip(MetaProperty property) { - return metadataTools.isNotPersistent(property); - } - - @Override - public void visit(Entity entity, MetaProperty property) { - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - if (!security.isEntityAttrReadPermitted(metaClass, property.getName())) { - addInaccessibleAttribute(entity, property.getName()); - if (!metadataTools.isSystem(property) && !property.isReadOnly()) { - setNullPropertyValue(entity, property); - } - } - SecurityState securityState = BaseEntityInternalAccess.getSecurityState(entity); - if (securityState != null && securityState.getHiddenAttributes().contains(property.getName())) { - addInaccessibleAttribute(entity, property.getName()); - if (!metadataTools.isSystem(property)) { - setNullPropertyValue(entity, property); - } - } - } - } - - protected class ClearInaccessibleAttributesVisitor implements EntityAttributeVisitor { - @Override - public void visit(Entity entity, MetaProperty property) { - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - String propertyName = property.getName(); - if (!security.isEntityAttrReadPermitted(metaClass, propertyName)) { - addInaccessibleAttribute(entity, propertyName); - if (!metadataTools.isSystem(property) && !property.isReadOnly()) { - setNullPropertyValue(entity, property); - } - } - SecurityState securityState = BaseEntityInternalAccess.getSecurityState(entity); - if (securityState != null && securityState.getHiddenAttributes().contains(property.getName())) { - addInaccessibleAttribute(entity, property.getName()); - if (!metadataTools.isSystem(property)) { - setNullPropertyValue(entity, property); - } - } - } - } - - protected class AttributeAccessVisitor implements EntityAttributeVisitor { - protected Set visited = new HashSet<>(); - - public AttributeAccessVisitor(Set visited) { - this.visited = visited; - } - - @Override - public void visit(Entity entity, MetaProperty property) { - if (!visited.contains(entity)) { - visited.add(entity); - setupAttributeAccess(entity); - } - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.google.common.collect.Sets; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.PersistenceSecurity; +import com.haulmont.cuba.core.app.events.SetupAttributeAccessEvent; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.CubaApplicationEventMulticaster; +import com.haulmont.cuba.core.sys.SecurityTokenManager; +import com.haulmont.cuba.core.sys.persistence.CubaEntityFetchGroup; +import org.eclipse.persistence.queries.FetchGroup; +import org.eclipse.persistence.queries.FetchGroupTracker; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.inject.Inject; +import java.util.*; + +import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.*; +import static java.lang.String.format; + +/** + * Supports enforcing entity attribute permissions on Middleware. + */ +@Component(AttributeSecuritySupport.NAME) +public class AttributeSecuritySupport { + + public static final String NAME = "cuba_AttributeSecuritySupport"; + + @Inject + protected Metadata metadata; + + @Inject + protected MetadataTools metadataTools; + + @Inject + protected PersistenceSecurity security; + + @Inject + protected ServerConfig config; + + @Inject + protected SecurityTokenManager securityTokenManager; + + @Inject + protected Events events; + + @Inject + protected EntityStates entityStates; + + @Inject + protected CubaApplicationEventMulticaster applicationEventMulticaster; + + /** + * Removes restricted attributes from a view. + * + * @param view source view + * @return restricted view + */ + public View createRestrictedView(View view) { + if (!isAuthorizationRequired()) { + return view; + } + Preconditions.checkNotNullArgument(view, "view is null"); + + View restrictedView = new View(view.getEntityClass(), + StringUtils.isEmpty(view.getName()) ? "" : view.getName() + "_restricted", + false); // do not include system properties in constructor because they will be copied later if exist + copyViewConsideringPermissions(view, restrictedView); + return restrictedView; + } + + private void copyViewConsideringPermissions(View srcView, View dstView) { + MetaClass metaClass = metadata.getClassNN(srcView.getEntityClass()); + for (ViewProperty property : srcView.getProperties()) { + if (security.isEntityAttrReadPermitted(metaClass, property.getName())) { + View viewCopy = null; + if (property.getView() != null) { + viewCopy = new View(property.getView().getEntityClass(), property.getView().getName() + "(restricted)", false); + copyViewConsideringPermissions(property.getView(), viewCopy); + } + dstView.addProperty(property.getName(), viewCopy, property.getFetchMode()); + } + } + } + + /** + * Should be called after loading an entity from the database. + * + * @param entity just loaded detached entity + */ + public void afterLoad(Entity entity) { + if (!isAuthorizationRequired()) { + return; + } + if (entity != null) { + metadataTools.traverseAttributes(entity, new FillingInaccessibleAttributesVisitor()); + } + } + + /** + * Should be called after loading a list of entities from the database. + * + * @param entities list of just loaded detached entities + */ + public void afterLoad(Collection entities) { + Preconditions.checkNotNullArgument(entities, "entities list is null"); + + for (Entity entity : entities) { + afterLoad(entity); + } + } + + /** + * Should be called before persisting a new entity. + * + * @param entity new entity + */ + public void beforePersist(Entity entity) { + if (!isAuthorizationRequired()) { + return; + } + // check only immediate attributes, otherwise persisted entity can be unusable for calling code + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + for (MetaProperty metaProperty : metaClass.getProperties()) { + if (!metadataTools.isSystem(metaProperty) + && !metaProperty.isReadOnly() + && !security.isEntityAttrUpdatePermitted(metaClass, metaProperty.getName())) { + entity.setValue(metaProperty.getName(), null); + } + } + } + + /** + * Should be called before merging an entity. + * + * @param entity detached entity + */ + public void beforeMerge(Entity entity) { + if (!isAuthorizationRequired()) { + return; + } + checkRequiredAttributes(entity); + applySecurityToFetchGroup(entity); + //apply fetch group constraints to embedded + for (MetaProperty metaProperty : entity.getMetaClass().getProperties()) { + String name = metaProperty.getName(); + if (metadataTools.isEmbedded(metaProperty) && entityStates.isLoaded(entity, name)) { + Entity embedded = entity.getValue(name); + checkRequiredAttributes(embedded); + applySecurityToFetchGroup(embedded); + } + } + } + + /** + * Should be called after merging an entity and before transaction commit. + * + * @param entity detached entity + */ + public void afterMerge(Entity entity) { + if (entity instanceof BaseGenericIdEntity) { + BaseGenericIdEntity genericIdEntity = (BaseGenericIdEntity) entity; + setupAttributeAccess(genericIdEntity); + metadataTools.traverseAttributes(genericIdEntity, new AttributeAccessVisitor(Sets.newHashSet(entity))); + } + } + + /** + * Should be called after merging an entity and transaction commit. + * + * @param entity detached entity + */ + public void afterCommit(Entity entity) { + if (!isAuthorizationRequired()) { + return; + } + if (entity != null) { + metadataTools.traverseAttributes(entity, new ClearInaccessibleAttributesVisitor()); + } + } + + public void onLoad(Collection entities, View view) { + Preconditions.checkNotNullArgument(entities, "entities list is null"); + + for (Entity entity : entities) { + onLoad(entity, view); + } + } + + public void onLoad(Entity entity, View view) { + if (entity instanceof BaseGenericIdEntity) { + BaseGenericIdEntity genericIdEntity = (BaseGenericIdEntity) entity; + setupAttributeAccess(genericIdEntity); + metadataTools.traverseAttributesByView(view, genericIdEntity, new AttributeAccessVisitor(Sets.newHashSet(entity))); + } + } + + public void setupAttributeAccess(T entity) { + if (entity instanceof BaseGenericIdEntity || entity instanceof EmbeddableEntity) { + SetupAttributeAccessEvent event = new SetupAttributeAccessEvent<>(entity); + events.publish(event); + if (event.getReadonlyAttributes() != null) { + Set attributes = event.getReadonlyAttributes(); + SecurityState state = getOrCreateSecurityState(entity); + addReadonlyAttributes(state, attributes.toArray(new String[attributes.size()])); + } + if (event.getRequiredAttributes() != null) { + Set attributes = event.getRequiredAttributes(); + SecurityState state = getOrCreateSecurityState(entity); + addRequiredAttributes(state, attributes.toArray(new String[attributes.size()])); + } + if (event.getHiddenAttributes() != null) { + Set attributes = event.getHiddenAttributes(); + SecurityState state = getOrCreateSecurityState(entity); + addHiddenAttributes(state, attributes.toArray(new String[attributes.size()])); + } + if (isAttributeAccessEnabled(event)) { + securityTokenManager.writeSecurityToken(entity); + } + } + } + + /** + * Checks if attribute access enabled for the current entity type. + * It's based on the existence of an event listener for SetupAttributeAccessEvent. + * @param entityClass - entity metaClass + */ + @SuppressWarnings("unchecked") + public boolean isAttributeAccessEnabled(MetaClass entityClass) { + return isAttributeAccessEnabled(new SetupAttributeAccessEvent(metadata.create(entityClass))); + } + + /** + * Checks if attribute access enabled for the current entity type. + * It's based on the existence of an event listener for SetupAttributeAccessEvent. + * @param event - SetupAttributeAccessEvent + */ + public boolean isAttributeAccessEnabled(SetupAttributeAccessEvent event) { + Collection listeners = applicationEventMulticaster.getApplicationListeners(event, event.getResolvableType()); + return listeners != null && listeners.size() > 0; + } + + protected void checkRequiredAttributes(Entity entity) { + SecurityState securityState = getSecurityState(entity); + if (securityState != null && !securityState.getRequiredAttributes().isEmpty()) { + for (MetaProperty metaProperty : entity.getMetaClass().getProperties()) { + String propertyName = metaProperty.getName(); + if (BaseEntityInternalAccess.isRequired(securityState, propertyName) && entity.getValue(propertyName) == null) { + throw new RowLevelSecurityException(format("Attribute [%s] is required for entity %s", propertyName, entity), + entity.getMetaClass().getName()); + } + } + } + } + + protected void applySecurityToFetchGroup(Entity entity) { + if (entity == null) { + return; + } + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + FetchGroupTracker fetchGroupTracker = (FetchGroupTracker) entity; + FetchGroup fetchGroup = fetchGroupTracker._persistence_getFetchGroup(); + SecurityState securityState = getSecurityState(entity); + if (fetchGroup != null) { + List attributesToRemove = new ArrayList<>(); + for (String attrName : fetchGroup.getAttributeNames()) { + String[] parts = attrName.split("\\."); + if (parts.length > 0 && BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, parts[0])) { + attributesToRemove.add(attrName); + } else { + MetaClass currentMetaClass = metaClass; + for (String part : parts) { + if (!security.isEntityAttrUpdatePermitted(currentMetaClass, part)) { + attributesToRemove.add(attrName); + break; + } + MetaProperty metaProperty = currentMetaClass.getPropertyNN(part); + if (metaProperty.getRange().isClass()) { + currentMetaClass = metaProperty.getRange().asClass(); + } + } + } + } + if (!attributesToRemove.isEmpty()) { + List attributeNames = new ArrayList<>(fetchGroup.getAttributeNames()); + attributeNames.removeAll(attributesToRemove); + fetchGroupTracker._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames)); + } + } else { + List attributeNames = new ArrayList<>(); + for (MetaProperty metaProperty : metaClass.getProperties()) { + String propertyName = metaProperty.getName(); + if (metadataTools.isSystem(metaProperty)) { + attributeNames.add(propertyName); + } + if (security.isEntityAttrUpdatePermitted(metaClass, propertyName) && + !BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, propertyName)) { + attributeNames.add(metaProperty.getName()); + } + } + fetchGroupTracker._persistence_setFetchGroup(new CubaEntityFetchGroup(attributeNames)); + } + } + + private void addInaccessibleAttribute(Entity entity, String property) { + SecurityState securityState = getOrCreateSecurityState(entity); + String[] attributes = getInaccessibleAttributes(securityState); + attributes = attributes == null ? new String[1] : Arrays.copyOf(attributes, attributes.length + 1); + attributes[attributes.length - 1] = property; + setInaccessibleAttributes(securityState, attributes); + } + + protected boolean isAuthorizationRequired() { + return (AppContext.getSecurityContextNN().isAuthorizationRequired() || config.getDataManagerChecksSecurityOnMiddleware()) + && config.getEntityAttributePermissionChecking(); + } + + protected void setNullPropertyValue(Entity entity, MetaProperty property) { + // Using reflective access to field because the attribute can be unfetched if loading not partial entities, + // which is the case when in-memory constraints exist + BaseEntityInternalAccess.setValue(entity, property.getName(), null); + if (property.getRange().isClass()) { + BaseEntityInternalAccess.setValueForHolder(entity, property.getName(), null); + } + } + + protected class FillingInaccessibleAttributesVisitor implements EntityAttributeVisitor { + @Override + public boolean skip(MetaProperty property) { + return metadataTools.isNotPersistent(property); + } + + @Override + public void visit(Entity entity, MetaProperty property) { + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + if (!security.isEntityAttrReadPermitted(metaClass, property.getName())) { + addInaccessibleAttribute(entity, property.getName()); + if (!metadataTools.isSystem(property) && !property.isReadOnly()) { + setNullPropertyValue(entity, property); + } + } + SecurityState securityState = BaseEntityInternalAccess.getSecurityState(entity); + if (securityState != null && securityState.getHiddenAttributes().contains(property.getName())) { + addInaccessibleAttribute(entity, property.getName()); + if (!metadataTools.isSystem(property)) { + setNullPropertyValue(entity, property); + } + } + } + } + + protected class ClearInaccessibleAttributesVisitor implements EntityAttributeVisitor { + @Override + public void visit(Entity entity, MetaProperty property) { + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + String propertyName = property.getName(); + if (!security.isEntityAttrReadPermitted(metaClass, propertyName)) { + addInaccessibleAttribute(entity, propertyName); + if (!metadataTools.isSystem(property) && !property.isReadOnly()) { + setNullPropertyValue(entity, property); + } + } + SecurityState securityState = BaseEntityInternalAccess.getSecurityState(entity); + if (securityState != null && securityState.getHiddenAttributes().contains(property.getName())) { + addInaccessibleAttribute(entity, property.getName()); + if (!metadataTools.isSystem(property)) { + setNullPropertyValue(entity, property); + } + } + } + } + + protected class AttributeAccessVisitor implements EntityAttributeVisitor { + protected Set visited = new HashSet<>(); + + public AttributeAccessVisitor(Set visited) { + this.visited = visited; + } + + @Override + public void visit(Entity entity, MetaProperty property) { + if (!visited.contains(entity)) { + visited.add(entity); + setupAttributeAccess(entity); + } + } + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/ClusterListener.java b/modules/core/src/com/haulmont/cuba/core/app/ClusterListener.java index 1a4b11073e..ca240d4ec3 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ClusterListener.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ClusterListener.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -/** - * Interface to be implemented by middleware cluster listeners. A cluster listener receives messages from other nodes - * in the cluster. - * @param type of message this listener receives - * - */ -public interface ClusterListener { - - /** - * Receive a message from other cluster nodes. - * @param message message instance - */ - void receive(T message); - - /** - * Get state of this cluster node to send it to other nodes. - * "State" here means data that must be shared between cluster nodes. - * - *

This method is invoked by clustering implementation when a new node joins the cluster and wants to receive the - * state from this active node.

- * - * @return byte array containing the state - */ - byte[] getState(); - - /** - * Set state of this cluster node receiving it from other active node. - * "State" here means data that must be shared between cluster nodes. - * - *

This method is invoked by clustering implementation once when this node joins the cluster. - * - * @param state byte array containing the state - */ - void setState(byte[] state); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +/** + * Interface to be implemented by middleware cluster listeners. A cluster listener receives messages from other nodes + * in the cluster. + * @param type of message this listener receives + * + */ +public interface ClusterListener { + + /** + * Receive a message from other cluster nodes. + * @param message message instance + */ + void receive(T message); + + /** + * Get state of this cluster node to send it to other nodes. + * "State" here means data that must be shared between cluster nodes. + * + *

This method is invoked by clustering implementation when a new node joins the cluster and wants to receive the + * state from this active node.

+ * + * @return byte array containing the state + */ + byte[] getState(); + + /** + * Set state of this cluster node receiving it from other active node. + * "State" here means data that must be shared between cluster nodes. + * + *

This method is invoked by clustering implementation once when this node joins the cluster. + * + * @param state byte array containing the state + */ + void setState(byte[] state); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/ClusterManager.java b/modules/core/src/com/haulmont/cuba/core/app/ClusterManager.java index 50fd6e73d5..327787823d 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ClusterManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ClusterManager.java @@ -1,556 +1,556 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.google.common.base.Strings; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.global.Resources; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.serialization.SerializationSupport; -import org.apache.commons.io.IOUtils; -import org.jgroups.*; -import org.jgroups.conf.XmlConfigurator; -import org.jgroups.jmx.JmxConfigurator; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.management.MBeanServer; -import java.io.*; -import java.lang.management.ManagementFactory; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.*; -import java.util.concurrent.atomic.LongAdder; - -/** - * Standard implementation of middleware clustering based on JGroups. - */ -@Component(ClusterManagerAPI.NAME) -public class ClusterManager implements ClusterManagerAPI, AppContext.Listener, Ordered { - - private final Logger log = LoggerFactory.getLogger(ClusterManager.class); - - protected Map listeners = new HashMap<>(); - - protected JChannel channel; - - protected View currentView; - - protected ThreadPoolExecutor executor; - - @Inject - protected Resources resources; - - @Inject - protected GlobalConfig globalConfig; - - @Inject - protected ClusterConfig clusterConfig; - - protected ThreadLocal forceSyncSending = new ThreadLocal<>(); - - protected Map messagesStat = new ConcurrentHashMap<>(); - - protected static final String STATE_MAGIC = "CUBA_STATE"; - - public ClusterManager() { - AppContext.addListener(this); - } - - public JChannel getChannel() { - return channel; - } - - @PostConstruct - public void init() { - int nThreads = clusterConfig.getClusterMessageSendingThreadPoolSize(); - executor = new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(clusterConfig.getClusterMessageSendingQueueCapacity()), - new ThreadFactoryBuilder().setNameFormat("ClusterManagerMessageSender-%d").build(), - new RejectedExecutionHandler() { - @Override - public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { - SendMessageRunnable sendMessageRunnable = (SendMessageRunnable) r; - log.info("Queue capacity is exceeded. Message: {}: {}", sendMessageRunnable.message.getClass(), sendMessageRunnable.message); - } - }); - } - - @Override - public void send(final Serializable message) { - if (channel == null) - return; - - Boolean sync = forceSyncSending.get(); - if (sync != null && sync) { - internalSend(message, true); - } else { - log.trace("Submitting message: {}: {} to send asynchronously", message.getClass(), message); - executor.execute(new SendMessageRunnable(message)); - } - } - - @Override - public void sendSync(Serializable message) { - if (channel == null) - return; - - internalSend(message, true); - } - - protected void internalSend(Serializable message, boolean sync) { - StopWatch sw = new Log4JStopWatch(String.format("sendClusterMessage(%s)", message.getClass().getSimpleName())); - try { - byte[] bytes = SerializationSupport.serialize(message); - log.debug("Sending message: {}: {} ({} bytes)", message.getClass(), message, bytes.length); - MessageStat stat = messagesStat.get(message.getClass().getName()); - if (stat != null) { - stat.updateSent(bytes.length); - } - Message msg = new Message(null, null, bytes); - if (sync) { - msg.setFlag(Message.Flag.RSVP); - } - try { - channel.send(msg); - } catch (Exception e) { - log.error("Error sending message", e); - } - } finally { - sw.stop(); - } - } - - @Override - public boolean getSyncSendingForCurrentThread() { - return forceSyncSending.get() == null ? false : forceSyncSending.get(); - } - - @Override - public void setSyncSendingForCurrentThread(boolean sync) { - if (sync) { - forceSyncSending.set(true); - } else { - forceSyncSending.remove(); - } - } - - @Override - public synchronized void addListener(Class messageClass, ClusterListener listener) { - String className = messageClass.getName(); - listeners.put(className, listener); - messagesStat.put(className, new MessageStat()); - } - - @Override - public synchronized void removeListener(Class messageClass, ClusterListener listener) { - String className = messageClass.getName(); - listeners.remove(className); - messagesStat.remove(className); - } - - @Override - public void applicationStarted() { - // Cluster starts in AppContextLoader.afterInitAppContext() - } - - @Override - public void applicationStopped() { - executor.shutdown(); - stop(); - } - - @Override - public void start() { - log.info("Starting cluster"); - - InputStream stream = null; - try { - String configName = AppContext.getProperty("cuba.cluster.jgroupsConfig"); - if (configName == null) { - log.info("Property 'cuba.cluster.jgroupsConfig' is not specified, using jgroups.xml"); - configName = "jgroups.xml"; - } - stream = resources.getResource(configName).getInputStream(); - - initJGroupsProperties(); - - channel = new JChannel(XmlConfigurator.getInstance(stream)); - channel.setDiscardOwnMessages(true); // do not receive a copy of our own messages - channel.setReceiver(new ClusterReceiver()); - channel.connect(getClusterName()); - try { - log.info("Receiving cluster state..."); - channel.getState(null, clusterConfig.getStateReceiveTimeout()); - } catch (Exception e) { - if (clusterConfig.getAbortOnStateReceivingFailure()) - throw e; - else { - log.error("Receiving the cluster state has failed", e); - } - } - registerJmxBeans(); - } catch (Exception e) { - channel = null; - throw new RuntimeException("Error starting cluster", e); - } finally { - IOUtils.closeQuietly(stream); - } - } - - protected void initJGroupsProperties() { - for (String name : AppContext.getPropertyNames()) { - if (name.startsWith("jgroups.")) { - String systemProp = System.getProperty(name); - if (Strings.isNullOrEmpty(systemProp)) { - //noinspection ConstantConditions - System.setProperty(name, AppContext.getProperty(name)); - } - } - } - } - - protected void registerJmxBeans() { - try { - MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); - JmxConfigurator.registerChannel(channel, mBeanServer, getMBeanDomain(), getClusterName(), true); - } catch (Exception e) { - log.error("Failed to register channel in jmx", e); - } - } - - protected void unregisterJmxBeans() { - try { - MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); - JmxConfigurator.unregisterChannel(channel, mBeanServer, getMBeanDomain(), getClusterName()); - } catch (Exception e) { - log.error("Failed to unregister channel in jmx", e); - } - } - - protected String getClusterName() { - return "cubaCluster"; - } - - protected String getMBeanDomain() { - return globalConfig.getWebContextName() + ".jgroups"; - } - - @Override - public int getActiveThreadsCount() { - return executor.getActiveCount(); - } - - @Override - public int getMessagesCount() { - return executor.getQueue().size(); - } - - @Override - public void stop() { - if (channel == null) - return; - - log.info("Stopping cluster"); - unregisterJmxBeans(); - try { - channel.close(); - } catch (Exception e) { - log.warn("Error stopping cluster", e); - } - channel = null; - currentView = null; - } - - @Override - public boolean isStarted() { - return channel != null; - } - - @Override - public boolean isMaster() { - if (currentView == null || channel == null) - return true; - - List

members = currentView.getMembers(); - if (members.size() == 0) - return true; - - Address coordinator = members.get(0); - return coordinator.equals(channel.getAddress()); - } - - @Override - public String getCurrentView() { - return currentView == null ? "" : currentView.toString(); - } - - @Override - public String printSharedStateStat() { - StringBuilder clusterStateStat = new StringBuilder(); - for (Map.Entry entry : listeners.entrySet()) { - byte[] data = null; - StopWatch sw = new StopWatch(); - try { - data = entry.getValue().getState(); - } finally { - sw.stop(); - } - clusterStateStat - .append(String.format("State: %s, size: %s bytes, serialize time: %s ms\n", - entry.getKey(), data != null ? data.length : -1, sw.getElapsedTime())); - } - return clusterStateStat.toString(); - } - - @Override - public String printMessagesStat() { - StringBuilder messagesStats = new StringBuilder(); - for (Map.Entry entry : messagesStat.entrySet()) { - MessageStat stat = entry.getValue(); - if (stat != null) { - messagesStats - .append(String.format("Class: %s; received: %s, %s bytes; sent: %s, %s bytes\n", - entry.getKey(), stat.getReceivedMessages(), stat.getReceivedBytes(), - stat.getSentMessages(), stat.getSentBytes())); - } - } - return messagesStats.toString(); - } - - @Override - public long getSentMessages(String className) { - Preconditions.checkNotNullArgument(className, "Message class is null"); - MessageStat stat = messagesStat.get(className); - if (stat != null) { - return stat.getSentMessages(); - } - return 0; - } - - @Override - public long getSentBytes(String className) { - Preconditions.checkNotNullArgument(className, "Message class is null"); - MessageStat stat = messagesStat.get(className); - if (stat != null) { - return stat.getSentBytes(); - } - return 0; - } - - @Override - public long getReceivedMessages(String className) { - Preconditions.checkNotNullArgument(className, "Message class is null"); - MessageStat stat = messagesStat.get(className); - if (stat != null) { - return stat.getReceivedMessages(); - } - return 0; - } - - @Override - public long getReceivedBytes(String className) { - Preconditions.checkNotNullArgument(className, "Message class is null"); - MessageStat stat = messagesStat.get(className); - if (stat != null) { - return stat.getReceivedBytes(); - } - return 0; - } - - @Override - public int getOrder() { - return LOWEST_PLATFORM_PRECEDENCE - 100; - } - - protected class ClusterReceiver implements Receiver { - - @Override - public void receive(Message msg) { - byte[] bytes = msg.getBuffer(); - if (bytes == null) { - log.debug("Null buffer received"); - return; - } - StopWatch sw = new Log4JStopWatch(); - String simpleClassName = null; - try { - Serializable data = (Serializable) SerializationSupport.deserialize(bytes); - String className = data.getClass().getName(); - simpleClassName = data.getClass().getSimpleName(); - log.debug("Received message: {}: {} ({} bytes)", data.getClass(), data, bytes.length); - MessageStat stat = messagesStat.get(className); - if (stat != null) { - stat.updateReceived(bytes.length); - } - ClusterListener listener = listeners.get(className); - if (listener != null) { - listener.receive(data); - } - } finally { - sw.stop(String.format("receiveClusterMessage(%s)", simpleClassName)); - } - } - - @Override - public void viewAccepted(View new_view) { - log.info("New cluster view: {}", new_view); - currentView = new_view; - } - - @Override - public void getState(OutputStream output) { - log.debug("Sending state"); - try (DataOutputStream out = new DataOutputStream(output)) { - Map state = new HashMap<>(); - for (Map.Entry entry : listeners.entrySet()) { - byte[] data; - StopWatch sw = new Log4JStopWatch(String.format("getClusterState(%s)", entry.getKey())); - try { - data = entry.getValue().getState(); - } finally { - sw.stop(); - } - if (data != null && data.length > 0) { - state.put(entry.getKey(), data); - } - } - - if (state.size() > 0) { - out.writeUTF(STATE_MAGIC); - out.writeInt(state.size()); - for (Map.Entry entry : state.entrySet()) { - log.debug("Sending state: {} ({} bytes)", entry.getKey(), entry.getValue().length); - out.writeUTF(entry.getKey()); - out.writeInt(entry.getValue().length); - out.write(entry.getValue()); - } - } - } catch (Exception e) { - log.error("Error sending state", e); - } - } - - @Override - public void suspect(Address suspected_mbr) { - log.info("Suspected member: {}", suspected_mbr); - } - - @Override - public void setState(InputStream input) { - log.debug("Receiving state"); - - try (DataInputStream in = new DataInputStream(input)) { - if (input.available() == 0) - return; - - String magic = in.readUTF(); - if (!STATE_MAGIC.equals(magic)) { - log.debug("Invalid magic in state received"); - return; - } - int count = in.readInt(); - for (int i = 0; i < count; i++) { - String name = in.readUTF(); - int len = in.readInt(); - StopWatch sw = new Log4JStopWatch(String.format("setClusterState(%s)", name)); - try { - log.debug("Receiving state: {} ({} bytes)", name, len); - byte[] data = new byte[len]; - int c = in.read(data); - if (c != len) { - log.error("Error receiving state: invalid data length"); - return; - } - ClusterListener listener = listeners.get(name); - if (listener != null) { - listener.setState(data); - } - } finally { - sw.stop(); - } - } - log.debug("State received"); - } catch (Exception e) { - log.error("Error receiving state", e); - } - } - - @Override - public void block() { - } - - @Override - public void unblock() { - } - } - - protected class SendMessageRunnable implements Runnable { - protected Serializable message; - - public SendMessageRunnable(Serializable message) { - this.message = message; - } - - @Override - public void run() { - internalSend(message, false); - } - } - - protected class MessageStat { - protected LongAdder sentBytes = new LongAdder(); - protected LongAdder receivedBytes = new LongAdder(); - protected LongAdder receivedMessages = new LongAdder(); - protected LongAdder sentMessages = new LongAdder(); - - public void updateReceived(int bytes) { - receivedMessages.increment(); - receivedBytes.add(bytes); - } - - public void updateSent(int bytes) { - sentMessages.increment(); - sentBytes.add(bytes); - } - - public long getSentBytes() { - return sentBytes.longValue(); - } - - public long getSentMessages() { - return sentMessages.longValue(); - } - - public long getReceivedBytes() { - return receivedBytes.longValue(); - } - - public long getReceivedMessages() { - return receivedMessages.longValue(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.google.common.base.Strings; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.global.Resources; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.serialization.SerializationSupport; +import org.apache.commons.io.IOUtils; +import org.jgroups.*; +import org.jgroups.conf.XmlConfigurator; +import org.jgroups.jmx.JmxConfigurator; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.management.MBeanServer; +import java.io.*; +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; +import java.util.concurrent.atomic.LongAdder; + +/** + * Standard implementation of middleware clustering based on JGroups. + */ +@Component(ClusterManagerAPI.NAME) +public class ClusterManager implements ClusterManagerAPI, AppContext.Listener, Ordered { + + private final Logger log = LoggerFactory.getLogger(ClusterManager.class); + + protected Map listeners = new HashMap<>(); + + protected JChannel channel; + + protected View currentView; + + protected ThreadPoolExecutor executor; + + @Inject + protected Resources resources; + + @Inject + protected GlobalConfig globalConfig; + + @Inject + protected ClusterConfig clusterConfig; + + protected ThreadLocal forceSyncSending = new ThreadLocal<>(); + + protected Map messagesStat = new ConcurrentHashMap<>(); + + protected static final String STATE_MAGIC = "CUBA_STATE"; + + public ClusterManager() { + AppContext.addListener(this); + } + + public JChannel getChannel() { + return channel; + } + + @PostConstruct + public void init() { + int nThreads = clusterConfig.getClusterMessageSendingThreadPoolSize(); + executor = new ThreadPoolExecutor(nThreads, nThreads, + 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(clusterConfig.getClusterMessageSendingQueueCapacity()), + new ThreadFactoryBuilder().setNameFormat("ClusterManagerMessageSender-%d").build(), + new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + SendMessageRunnable sendMessageRunnable = (SendMessageRunnable) r; + log.info("Queue capacity is exceeded. Message: {}: {}", sendMessageRunnable.message.getClass(), sendMessageRunnable.message); + } + }); + } + + @Override + public void send(final Serializable message) { + if (channel == null) + return; + + Boolean sync = forceSyncSending.get(); + if (sync != null && sync) { + internalSend(message, true); + } else { + log.trace("Submitting message: {}: {} to send asynchronously", message.getClass(), message); + executor.execute(new SendMessageRunnable(message)); + } + } + + @Override + public void sendSync(Serializable message) { + if (channel == null) + return; + + internalSend(message, true); + } + + protected void internalSend(Serializable message, boolean sync) { + StopWatch sw = new Log4JStopWatch(String.format("sendClusterMessage(%s)", message.getClass().getSimpleName())); + try { + byte[] bytes = SerializationSupport.serialize(message); + log.debug("Sending message: {}: {} ({} bytes)", message.getClass(), message, bytes.length); + MessageStat stat = messagesStat.get(message.getClass().getName()); + if (stat != null) { + stat.updateSent(bytes.length); + } + Message msg = new Message(null, null, bytes); + if (sync) { + msg.setFlag(Message.Flag.RSVP); + } + try { + channel.send(msg); + } catch (Exception e) { + log.error("Error sending message", e); + } + } finally { + sw.stop(); + } + } + + @Override + public boolean getSyncSendingForCurrentThread() { + return forceSyncSending.get() == null ? false : forceSyncSending.get(); + } + + @Override + public void setSyncSendingForCurrentThread(boolean sync) { + if (sync) { + forceSyncSending.set(true); + } else { + forceSyncSending.remove(); + } + } + + @Override + public synchronized void addListener(Class messageClass, ClusterListener listener) { + String className = messageClass.getName(); + listeners.put(className, listener); + messagesStat.put(className, new MessageStat()); + } + + @Override + public synchronized void removeListener(Class messageClass, ClusterListener listener) { + String className = messageClass.getName(); + listeners.remove(className); + messagesStat.remove(className); + } + + @Override + public void applicationStarted() { + // Cluster starts in AppContextLoader.afterInitAppContext() + } + + @Override + public void applicationStopped() { + executor.shutdown(); + stop(); + } + + @Override + public void start() { + log.info("Starting cluster"); + + InputStream stream = null; + try { + String configName = AppContext.getProperty("cuba.cluster.jgroupsConfig"); + if (configName == null) { + log.info("Property 'cuba.cluster.jgroupsConfig' is not specified, using jgroups.xml"); + configName = "jgroups.xml"; + } + stream = resources.getResource(configName).getInputStream(); + + initJGroupsProperties(); + + channel = new JChannel(XmlConfigurator.getInstance(stream)); + channel.setDiscardOwnMessages(true); // do not receive a copy of our own messages + channel.setReceiver(new ClusterReceiver()); + channel.connect(getClusterName()); + try { + log.info("Receiving cluster state..."); + channel.getState(null, clusterConfig.getStateReceiveTimeout()); + } catch (Exception e) { + if (clusterConfig.getAbortOnStateReceivingFailure()) + throw e; + else { + log.error("Receiving the cluster state has failed", e); + } + } + registerJmxBeans(); + } catch (Exception e) { + channel = null; + throw new RuntimeException("Error starting cluster", e); + } finally { + IOUtils.closeQuietly(stream); + } + } + + protected void initJGroupsProperties() { + for (String name : AppContext.getPropertyNames()) { + if (name.startsWith("jgroups.")) { + String systemProp = System.getProperty(name); + if (Strings.isNullOrEmpty(systemProp)) { + //noinspection ConstantConditions + System.setProperty(name, AppContext.getProperty(name)); + } + } + } + } + + protected void registerJmxBeans() { + try { + MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); + JmxConfigurator.registerChannel(channel, mBeanServer, getMBeanDomain(), getClusterName(), true); + } catch (Exception e) { + log.error("Failed to register channel in jmx", e); + } + } + + protected void unregisterJmxBeans() { + try { + MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); + JmxConfigurator.unregisterChannel(channel, mBeanServer, getMBeanDomain(), getClusterName()); + } catch (Exception e) { + log.error("Failed to unregister channel in jmx", e); + } + } + + protected String getClusterName() { + return "cubaCluster"; + } + + protected String getMBeanDomain() { + return globalConfig.getWebContextName() + ".jgroups"; + } + + @Override + public int getActiveThreadsCount() { + return executor.getActiveCount(); + } + + @Override + public int getMessagesCount() { + return executor.getQueue().size(); + } + + @Override + public void stop() { + if (channel == null) + return; + + log.info("Stopping cluster"); + unregisterJmxBeans(); + try { + channel.close(); + } catch (Exception e) { + log.warn("Error stopping cluster", e); + } + channel = null; + currentView = null; + } + + @Override + public boolean isStarted() { + return channel != null; + } + + @Override + public boolean isMaster() { + if (currentView == null || channel == null) + return true; + + List
members = currentView.getMembers(); + if (members.size() == 0) + return true; + + Address coordinator = members.get(0); + return coordinator.equals(channel.getAddress()); + } + + @Override + public String getCurrentView() { + return currentView == null ? "" : currentView.toString(); + } + + @Override + public String printSharedStateStat() { + StringBuilder clusterStateStat = new StringBuilder(); + for (Map.Entry entry : listeners.entrySet()) { + byte[] data = null; + StopWatch sw = new StopWatch(); + try { + data = entry.getValue().getState(); + } finally { + sw.stop(); + } + clusterStateStat + .append(String.format("State: %s, size: %s bytes, serialize time: %s ms\n", + entry.getKey(), data != null ? data.length : -1, sw.getElapsedTime())); + } + return clusterStateStat.toString(); + } + + @Override + public String printMessagesStat() { + StringBuilder messagesStats = new StringBuilder(); + for (Map.Entry entry : messagesStat.entrySet()) { + MessageStat stat = entry.getValue(); + if (stat != null) { + messagesStats + .append(String.format("Class: %s; received: %s, %s bytes; sent: %s, %s bytes\n", + entry.getKey(), stat.getReceivedMessages(), stat.getReceivedBytes(), + stat.getSentMessages(), stat.getSentBytes())); + } + } + return messagesStats.toString(); + } + + @Override + public long getSentMessages(String className) { + Preconditions.checkNotNullArgument(className, "Message class is null"); + MessageStat stat = messagesStat.get(className); + if (stat != null) { + return stat.getSentMessages(); + } + return 0; + } + + @Override + public long getSentBytes(String className) { + Preconditions.checkNotNullArgument(className, "Message class is null"); + MessageStat stat = messagesStat.get(className); + if (stat != null) { + return stat.getSentBytes(); + } + return 0; + } + + @Override + public long getReceivedMessages(String className) { + Preconditions.checkNotNullArgument(className, "Message class is null"); + MessageStat stat = messagesStat.get(className); + if (stat != null) { + return stat.getReceivedMessages(); + } + return 0; + } + + @Override + public long getReceivedBytes(String className) { + Preconditions.checkNotNullArgument(className, "Message class is null"); + MessageStat stat = messagesStat.get(className); + if (stat != null) { + return stat.getReceivedBytes(); + } + return 0; + } + + @Override + public int getOrder() { + return LOWEST_PLATFORM_PRECEDENCE - 100; + } + + protected class ClusterReceiver implements Receiver { + + @Override + public void receive(Message msg) { + byte[] bytes = msg.getBuffer(); + if (bytes == null) { + log.debug("Null buffer received"); + return; + } + StopWatch sw = new Log4JStopWatch(); + String simpleClassName = null; + try { + Serializable data = (Serializable) SerializationSupport.deserialize(bytes); + String className = data.getClass().getName(); + simpleClassName = data.getClass().getSimpleName(); + log.debug("Received message: {}: {} ({} bytes)", data.getClass(), data, bytes.length); + MessageStat stat = messagesStat.get(className); + if (stat != null) { + stat.updateReceived(bytes.length); + } + ClusterListener listener = listeners.get(className); + if (listener != null) { + listener.receive(data); + } + } finally { + sw.stop(String.format("receiveClusterMessage(%s)", simpleClassName)); + } + } + + @Override + public void viewAccepted(View new_view) { + log.info("New cluster view: {}", new_view); + currentView = new_view; + } + + @Override + public void getState(OutputStream output) { + log.debug("Sending state"); + try (DataOutputStream out = new DataOutputStream(output)) { + Map state = new HashMap<>(); + for (Map.Entry entry : listeners.entrySet()) { + byte[] data; + StopWatch sw = new Log4JStopWatch(String.format("getClusterState(%s)", entry.getKey())); + try { + data = entry.getValue().getState(); + } finally { + sw.stop(); + } + if (data != null && data.length > 0) { + state.put(entry.getKey(), data); + } + } + + if (state.size() > 0) { + out.writeUTF(STATE_MAGIC); + out.writeInt(state.size()); + for (Map.Entry entry : state.entrySet()) { + log.debug("Sending state: {} ({} bytes)", entry.getKey(), entry.getValue().length); + out.writeUTF(entry.getKey()); + out.writeInt(entry.getValue().length); + out.write(entry.getValue()); + } + } + } catch (Exception e) { + log.error("Error sending state", e); + } + } + + @Override + public void suspect(Address suspected_mbr) { + log.info("Suspected member: {}", suspected_mbr); + } + + @Override + public void setState(InputStream input) { + log.debug("Receiving state"); + + try (DataInputStream in = new DataInputStream(input)) { + if (input.available() == 0) + return; + + String magic = in.readUTF(); + if (!STATE_MAGIC.equals(magic)) { + log.debug("Invalid magic in state received"); + return; + } + int count = in.readInt(); + for (int i = 0; i < count; i++) { + String name = in.readUTF(); + int len = in.readInt(); + StopWatch sw = new Log4JStopWatch(String.format("setClusterState(%s)", name)); + try { + log.debug("Receiving state: {} ({} bytes)", name, len); + byte[] data = new byte[len]; + int c = in.read(data); + if (c != len) { + log.error("Error receiving state: invalid data length"); + return; + } + ClusterListener listener = listeners.get(name); + if (listener != null) { + listener.setState(data); + } + } finally { + sw.stop(); + } + } + log.debug("State received"); + } catch (Exception e) { + log.error("Error receiving state", e); + } + } + + @Override + public void block() { + } + + @Override + public void unblock() { + } + } + + protected class SendMessageRunnable implements Runnable { + protected Serializable message; + + public SendMessageRunnable(Serializable message) { + this.message = message; + } + + @Override + public void run() { + internalSend(message, false); + } + } + + protected class MessageStat { + protected LongAdder sentBytes = new LongAdder(); + protected LongAdder receivedBytes = new LongAdder(); + protected LongAdder receivedMessages = new LongAdder(); + protected LongAdder sentMessages = new LongAdder(); + + public void updateReceived(int bytes) { + receivedMessages.increment(); + receivedBytes.add(bytes); + } + + public void updateSent(int bytes) { + sentMessages.increment(); + sentBytes.add(bytes); + } + + public long getSentBytes() { + return sentBytes.longValue(); + } + + public long getSentMessages() { + return sentMessages.longValue(); + } + + public long getReceivedBytes() { + return receivedBytes.longValue(); + } + + public long getReceivedMessages() { + return receivedMessages.longValue(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ClusterManagerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/ClusterManagerAPI.java index 8583d1f23b..e39a5119b2 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ClusterManagerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ClusterManagerAPI.java @@ -1,154 +1,154 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import java.io.Serializable; - -/** - * Interface defining methods for communication in a middleware cluster. - */ -public interface ClusterManagerAPI { - - String NAME = "cuba_ClusterManager"; - - /** - * Send a message to all active cluster nodes. - * - * @param message serializable message - */ - void send(Serializable message); - - /** - * Send a message to all active cluster nodes synchronously. - * - * @param message serializable message - */ - void sendSync(Serializable message); - - /** - * @return whether the synchronous sending is forced for the current thread - * @see #setSyncSendingForCurrentThread(boolean) - */ - boolean getSyncSendingForCurrentThread(); - - /** - * Forces synchronous sending for the current thread. It means that the {@link #send(Serializable)} method will - * send the message in the current thread and block until returning from the clustering implementation. - * - * @param sync true to force synchronous sending - */ - void setSyncSendingForCurrentThread(boolean sync); - - /** - * Subscribe to messages from other cluster nodes. - * - * @param messageClass the class of messages we want to be notified - * @param listener listener instance - */ - void addListener(Class messageClass, ClusterListener listener); - - /** - * Unsubscribe from messages from other cluster nodes. - * - * @param messageClass the class of messages we don't want to be notified anymore - * @param listener listener instance - */ - void removeListener(Class messageClass, ClusterListener listener); - - /** - * Inform whether the current node is currently the master node in the cluster. A middleware cluster always - * elects one of its members as master, ususally it is the oldest one. - * - * @return true if the current node is the master - */ - boolean isMaster(); - - /** - * Return a string representation of a set of active nodes in the cluster. This string depends on clustering - * implementation and should not be parsed or otherwise analyzed in the application. - * - * @return string representation of a set of active nodes - */ - String getCurrentView(); - - /** - * Join a cluster. - */ - void start(); - - /** - * Leave the cluster. - */ - void stop(); - - /** - * @return true if clustering is started on this node - */ - boolean isStarted(); - - /** - * @return threads count that are actively sending cluster messages - */ - int getActiveThreadsCount(); - - /** - * @return cluster messages count queued to send - */ - int getMessagesCount(); - - /** - * Shared state statistics - * - * @return statistics - */ - String printSharedStateStat(); - - /** - * Sent/received messages statistics - * - * @return statistics - */ - String printMessagesStat(); - - /** - * Get sent messages count for specified {@code className} - * - * @return messages count - */ - long getSentMessages(String className); - - /** - * Get sent bytes for specified {@code className} - * - * @return size in bytes - */ - long getSentBytes(String className); - - /** - * Get received messages count for specified {@code className} - * - * @return messages count - */ - long getReceivedMessages(String className); - - /** - * Get received bytes for specified {@code className} - * - * @return size in bytes - */ - long getReceivedBytes(String className); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import java.io.Serializable; + +/** + * Interface defining methods for communication in a middleware cluster. + */ +public interface ClusterManagerAPI { + + String NAME = "cuba_ClusterManager"; + + /** + * Send a message to all active cluster nodes. + * + * @param message serializable message + */ + void send(Serializable message); + + /** + * Send a message to all active cluster nodes synchronously. + * + * @param message serializable message + */ + void sendSync(Serializable message); + + /** + * @return whether the synchronous sending is forced for the current thread + * @see #setSyncSendingForCurrentThread(boolean) + */ + boolean getSyncSendingForCurrentThread(); + + /** + * Forces synchronous sending for the current thread. It means that the {@link #send(Serializable)} method will + * send the message in the current thread and block until returning from the clustering implementation. + * + * @param sync true to force synchronous sending + */ + void setSyncSendingForCurrentThread(boolean sync); + + /** + * Subscribe to messages from other cluster nodes. + * + * @param messageClass the class of messages we want to be notified + * @param listener listener instance + */ + void addListener(Class messageClass, ClusterListener listener); + + /** + * Unsubscribe from messages from other cluster nodes. + * + * @param messageClass the class of messages we don't want to be notified anymore + * @param listener listener instance + */ + void removeListener(Class messageClass, ClusterListener listener); + + /** + * Inform whether the current node is currently the master node in the cluster. A middleware cluster always + * elects one of its members as master, ususally it is the oldest one. + * + * @return true if the current node is the master + */ + boolean isMaster(); + + /** + * Return a string representation of a set of active nodes in the cluster. This string depends on clustering + * implementation and should not be parsed or otherwise analyzed in the application. + * + * @return string representation of a set of active nodes + */ + String getCurrentView(); + + /** + * Join a cluster. + */ + void start(); + + /** + * Leave the cluster. + */ + void stop(); + + /** + * @return true if clustering is started on this node + */ + boolean isStarted(); + + /** + * @return threads count that are actively sending cluster messages + */ + int getActiveThreadsCount(); + + /** + * @return cluster messages count queued to send + */ + int getMessagesCount(); + + /** + * Shared state statistics + * + * @return statistics + */ + String printSharedStateStat(); + + /** + * Sent/received messages statistics + * + * @return statistics + */ + String printMessagesStat(); + + /** + * Get sent messages count for specified {@code className} + * + * @return messages count + */ + long getSentMessages(String className); + + /** + * Get sent bytes for specified {@code className} + * + * @return size in bytes + */ + long getSentBytes(String className); + + /** + * Get received messages count for specified {@code className} + * + * @return messages count + */ + long getReceivedMessages(String className); + + /** + * Get received bytes for specified {@code className} + * + * @return size in bytes + */ + long getReceivedBytes(String className); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorage.java b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorage.java index f86ffb7120..3e032ca723 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorage.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorage.java @@ -1,185 +1,185 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.bali.db.ResultSetHandler; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.entity.Config; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.io.Serializable; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Supports configuration parameters framework functionality. - * - */ -@Component(ConfigStorageAPI.NAME) -public class ConfigStorage implements ConfigStorageAPI { - - @Inject - protected Persistence persistence; - - protected ClusterManagerAPI clusterManager; - - protected Map cache; - - protected ReadWriteLock lock = new ReentrantReadWriteLock(); - protected Lock readLock = lock.readLock(); - protected Lock writeLock = lock.writeLock(); - - private Logger log = LoggerFactory.getLogger(ConfigStorage.class); - - private static class InvalidateCacheMsg implements Serializable { - private static final long serialVersionUID = -3116358584797500962L; - } - - @Inject - public void setClusterManager(ClusterManagerAPI clusterManager) { - this.clusterManager = clusterManager; - clusterManager.addListener(InvalidateCacheMsg.class, new ClusterListenerAdapter() { - @Override - public void receive(InvalidateCacheMsg message) { - internalClearCache(); - } - }); - } - - @Override - public void clearCache() { - internalClearCache(); - clusterManager.send(new InvalidateCacheMsg()); - } - - private void internalClearCache() { - writeLock.lock(); - try { - cache = null; - } finally { - writeLock.unlock(); - } - } - - @Override - public Map getDbProperties() { - readLock.lock(); - try { - loadCache(); - return new HashMap<>(cache); - } finally { - readLock.unlock(); - } - } - - @Override - public String getDbProperty(String name) { - readLock.lock(); - try { - loadCache(); - return cache.get(name); - } finally { - readLock.unlock(); - } - } - - protected void loadCache() { - if (cache == null) { - lock.readLock().unlock(); - lock.writeLock().lock(); - try { - if (cache == null) { - log.info("Loading DB-stored app properties cache"); - // Don't use transactions here because of loop possibility from EntityLog - QueryRunner queryRunner = new QueryRunner(persistence.getDataSource()); - try { - cache = queryRunner.query("select NAME, VALUE from SYS_CONFIG", - new ResultSetHandler>() { - @Override - public Map handle(ResultSet rs) throws SQLException { - HashMap map = new HashMap<>(); - while (rs.next()) { - map.put(rs.getString(1), rs.getString(2)); - } - return map; - } - }); - } catch (SQLException e) { - throw new RuntimeException("Error loading DB-stored app properties cache", e); - } - } - } finally { - lock.readLock().lock(); - lock.writeLock().unlock(); - } - } - } - - @Override - public void setDbProperty(String name, String value) { - Preconditions.checkNotNullArgument(name, "name is null"); - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - Config instance = getConfigInstance(name); - if (value != null) { - if (instance == null) { - Metadata metadata = AppBeans.get(Metadata.NAME); - - instance = metadata.create(Config.class); - instance.setName(name.trim()); - instance.setValue(value.trim()); - em.persist(instance); - } else { - instance.setValue(value); - } - } else { - if (instance != null) - em.remove(instance); - } - tx.commit(); - } finally { - tx.end(); - } - clearCache(); - } - - private Config getConfigInstance(String name) { - EntityManager em = persistence.getEntityManager(); - TypedQuery query = em.createQuery("select c from sys$Config c where c.name = ?1", Config.class); - query.setParameter(1, name); - query.setView(null); - List list = query.getResultList(); - if (list.isEmpty()) - return null; - else - return list.get(0); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.bali.db.ResultSetHandler; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.entity.Config; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.io.Serializable; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Supports configuration parameters framework functionality. + * + */ +@Component(ConfigStorageAPI.NAME) +public class ConfigStorage implements ConfigStorageAPI { + + @Inject + protected Persistence persistence; + + protected ClusterManagerAPI clusterManager; + + protected Map cache; + + protected ReadWriteLock lock = new ReentrantReadWriteLock(); + protected Lock readLock = lock.readLock(); + protected Lock writeLock = lock.writeLock(); + + private Logger log = LoggerFactory.getLogger(ConfigStorage.class); + + private static class InvalidateCacheMsg implements Serializable { + private static final long serialVersionUID = -3116358584797500962L; + } + + @Inject + public void setClusterManager(ClusterManagerAPI clusterManager) { + this.clusterManager = clusterManager; + clusterManager.addListener(InvalidateCacheMsg.class, new ClusterListenerAdapter() { + @Override + public void receive(InvalidateCacheMsg message) { + internalClearCache(); + } + }); + } + + @Override + public void clearCache() { + internalClearCache(); + clusterManager.send(new InvalidateCacheMsg()); + } + + private void internalClearCache() { + writeLock.lock(); + try { + cache = null; + } finally { + writeLock.unlock(); + } + } + + @Override + public Map getDbProperties() { + readLock.lock(); + try { + loadCache(); + return new HashMap<>(cache); + } finally { + readLock.unlock(); + } + } + + @Override + public String getDbProperty(String name) { + readLock.lock(); + try { + loadCache(); + return cache.get(name); + } finally { + readLock.unlock(); + } + } + + protected void loadCache() { + if (cache == null) { + lock.readLock().unlock(); + lock.writeLock().lock(); + try { + if (cache == null) { + log.info("Loading DB-stored app properties cache"); + // Don't use transactions here because of loop possibility from EntityLog + QueryRunner queryRunner = new QueryRunner(persistence.getDataSource()); + try { + cache = queryRunner.query("select NAME, VALUE from SYS_CONFIG", + new ResultSetHandler>() { + @Override + public Map handle(ResultSet rs) throws SQLException { + HashMap map = new HashMap<>(); + while (rs.next()) { + map.put(rs.getString(1), rs.getString(2)); + } + return map; + } + }); + } catch (SQLException e) { + throw new RuntimeException("Error loading DB-stored app properties cache", e); + } + } + } finally { + lock.readLock().lock(); + lock.writeLock().unlock(); + } + } + } + + @Override + public void setDbProperty(String name, String value) { + Preconditions.checkNotNullArgument(name, "name is null"); + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + Config instance = getConfigInstance(name); + if (value != null) { + if (instance == null) { + Metadata metadata = AppBeans.get(Metadata.NAME); + + instance = metadata.create(Config.class); + instance.setName(name.trim()); + instance.setValue(value.trim()); + em.persist(instance); + } else { + instance.setValue(value); + } + } else { + if (instance != null) + em.remove(instance); + } + tx.commit(); + } finally { + tx.end(); + } + clearCache(); + } + + private Config getConfigInstance(String name) { + EntityManager em = persistence.getEntityManager(); + TypedQuery query = em.createQuery("select c from sys$Config c where c.name = ?1", Config.class); + query.setParameter(1, name); + query.setView(null); + List list = query.getResultList(); + if (list.isEmpty()) + return null; + else + return list.get(0); + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageAPI.java b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageAPI.java index d1aa6b97e5..02971d5404 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageAPI.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import javax.annotation.Nullable; -import java.util.Map; - -/** - * Supports configuration parameters framework functionality. - * - */ -public interface ConfigStorageAPI { - - String NAME = "cuba_ConfigStorage"; - - /** - * Loads all properties stored in the database. - * - * @return the properties map - */ - Map getDbProperties(); - - /** - * Loads a property from the database. - * - * @param name property name - * @return property value or null if not found - */ - @Nullable - String getDbProperty(String name); - - /** - * Saves a property into the database. - * - *

If an active transaction exists, it will be used without creating a new one. This allows you to include - * saving properties into your business logic. If you want to separate the property saving, just start a new - * transaction prior to calling this method.

- * - * @param name property name - * @param value property value - */ - void setDbProperty(String name, String value); - - /** - * Clear properties cache. Invoke this method if you changed the properties directly in the database. - */ - void clearCache(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import javax.annotation.Nullable; +import java.util.Map; + +/** + * Supports configuration parameters framework functionality. + * + */ +public interface ConfigStorageAPI { + + String NAME = "cuba_ConfigStorage"; + + /** + * Loads all properties stored in the database. + * + * @return the properties map + */ + Map getDbProperties(); + + /** + * Loads a property from the database. + * + * @param name property name + * @return property value or null if not found + */ + @Nullable + String getDbProperty(String name); + + /** + * Saves a property into the database. + * + *

If an active transaction exists, it will be used without creating a new one. This allows you to include + * saving properties into your business logic. If you want to separate the property saving, just start a new + * transaction prior to calling this method.

+ * + * @param name property name + * @param value property value + */ + void setDbProperty(String name, String value); + + /** + * Clear properties cache. Invoke this method if you changed the properties directly in the database. + */ + void clearCache(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageServiceBean.java index 670c3ee4ce..44b9d12a16 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ConfigStorageServiceBean.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.config.AppPropertiesLocator; -import com.haulmont.cuba.core.config.AppPropertyEntity; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.List; -import java.util.Map; - -@Service(ConfigStorageService.NAME) -public class ConfigStorageServiceBean implements ConfigStorageService { - - @Inject - private ConfigStorageAPI api; - - @Inject - private AppPropertiesLocator appPropertiesLocator; - - @Override - public Map getDbProperties() { - return api.getDbProperties(); - } - - @Override - public String getDbProperty(String name) { - return api.getDbProperty(name); - } - - @Override - public void setDbProperty(String name, String value) { - api.setDbProperty(name, value); - } - - @Override - public List getAppProperties() { - return appPropertiesLocator.getAppProperties(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.config.AppPropertiesLocator; +import com.haulmont.cuba.core.config.AppPropertyEntity; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.List; +import java.util.Map; + +@Service(ConfigStorageService.NAME) +public class ConfigStorageServiceBean implements ConfigStorageService { + + @Inject + private ConfigStorageAPI api; + + @Inject + private AppPropertiesLocator appPropertiesLocator; + + @Override + public Map getDbProperties() { + return api.getDbProperties(); + } + + @Override + public String getDbProperty(String name) { + return api.getDbProperty(name); + } + + @Override + public void setDbProperty(String name, String value) { + api.setDbProperty(name, value); + } + + @Override + public List getAppProperties() { + return appPropertiesLocator.getAppProperties(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/DataServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/DataServiceBean.java index 6ee55adeb3..3814289a38 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/DataServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/DataServiceBean.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.KeyValueEntity; -import com.haulmont.cuba.core.global.CommitContext; -import com.haulmont.cuba.core.global.DataManager; -import com.haulmont.cuba.core.global.LoadContext; -import com.haulmont.cuba.core.global.ValueLoadContext; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.List; -import java.util.Set; - -@Service(DataService.NAME) -public class DataServiceBean implements DataService { - - @Inject - protected DataManager dataManager; - - @Override - public Set commit(CommitContext context) { - return dataManager.secure().commit(context); - } - - @Override - @Nullable - public E load(LoadContext context) { - return dataManager.secure().load(context); - } - - @Override - public List loadList(LoadContext context) { - return dataManager.secure().loadList(context); - } - - @Override - public long getCount(LoadContext context) { - return dataManager.secure().getCount(context); - } - - @Override - public List loadValues(ValueLoadContext context) { - return dataManager.secure().loadValues(context); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.KeyValueEntity; +import com.haulmont.cuba.core.global.CommitContext; +import com.haulmont.cuba.core.global.DataManager; +import com.haulmont.cuba.core.global.LoadContext; +import com.haulmont.cuba.core.global.ValueLoadContext; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.List; +import java.util.Set; + +@Service(DataService.NAME) +public class DataServiceBean implements DataService { + + @Inject + protected DataManager dataManager; + + @Override + public Set commit(CommitContext context) { + return dataManager.secure().commit(context); + } + + @Override + @Nullable + public E load(LoadContext context) { + return dataManager.secure().load(context); + } + + @Override + public List loadList(LoadContext context) { + return dataManager.secure().loadList(context); + } + + @Override + public long getCount(LoadContext context) { + return dataManager.secure().getCount(context); + } + + @Override + public List loadValues(ValueLoadContext context) { + return dataManager.secure().loadValues(context); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EmailSender.java b/modules/core/src/com/haulmont/cuba/core/app/EmailSender.java index b2abbe5266..cd35615f57 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EmailSender.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EmailSender.java @@ -1,226 +1,226 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.SendingAttachment; -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.EmailHeader; -import com.haulmont.cuba.core.global.FileTypesHelper; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.sys.CubaMailSender; -import org.apache.commons.codec.EncoderException; -import org.apache.commons.codec.net.QCodec; -import org.apache.commons.lang.StringUtils; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.mail.javamail.JavaMailSender; - -import javax.activation.DataHandler; -import javax.activation.DataSource; -import org.springframework.stereotype.Component; -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Part; -import javax.mail.internet.*; -import java.io.*; -import java.nio.charset.StandardCharsets; - -@Component(EmailSenderAPI.NAME) -public class EmailSender implements EmailSenderAPI { - - private Logger log = LoggerFactory.getLogger(EmailSender.class); - - protected JavaMailSender mailSender; - - @Inject - protected TimeSource timeSource; - - @Resource(name = CubaMailSender.NAME) - public void setMailSender(JavaMailSender mailSender) { - this.mailSender = mailSender; - } - - @Override - public void sendEmail(SendingMessage sendingMessage) throws MessagingException { - MimeMessage msg = createMimeMessage(sendingMessage); - - StopWatch sw = new Log4JStopWatch("EmailSender.send"); - mailSender.send(msg); - sw.stop(); - - log.info("Email '" + msg.getSubject() + "' to '" + sendingMessage.getAddress() + "' has been sent successfully"); - } - - protected MimeMessage createMimeMessage(SendingMessage sendingMessage) throws MessagingException { - MimeMessage msg = mailSender.createMimeMessage(); - assignRecipient(sendingMessage, msg); - msg.setSubject(sendingMessage.getCaption(), StandardCharsets.UTF_8.name()); - msg.setSentDate(timeSource.currentTimestamp()); - - assignFromAddress(sendingMessage, msg); - addHeaders(sendingMessage, msg); - - MimeMultipart content = new MimeMultipart("mixed"); - MimeMultipart textPart = new MimeMultipart("related"); - - setMimeMessageContent(sendingMessage, content, textPart); - - for (SendingAttachment attachment : sendingMessage.getAttachments()) { - MimeBodyPart attachmentPart = createAttachmentPart(attachment); - - if (attachment.getContentId() == null) { - content.addBodyPart(attachmentPart); - } else - textPart.addBodyPart(attachmentPart); - } - - msg.setContent(content); - msg.saveChanges(); - return msg; - } - - protected void setMimeMessageContent(SendingMessage sendingMessage, MimeMultipart content, MimeMultipart textPart) - throws MessagingException { - MimeBodyPart textBodyPart = new MimeBodyPart(); - MimeBodyPart contentBodyPart = new MimeBodyPart(); - String bodyContentType = getContentBodyType(sendingMessage); - - contentBodyPart.setContent(sendingMessage.getContentText(), bodyContentType); - textPart.addBodyPart(contentBodyPart); - textBodyPart.setContent(textPart); - content.addBodyPart(textBodyPart); - } - - protected void assignRecipient(SendingMessage sendingMessage, MimeMessage message) throws MessagingException { - InternetAddress internetAddress = new InternetAddress(sendingMessage.getAddress().trim()); - message.setRecipient(Message.RecipientType.TO, internetAddress); - } - - protected String getContentBodyType(SendingMessage sendingMessage) { - String text = sendingMessage.getContentText(); - String bodyContentType; - if (text.trim().startsWith("")) { - bodyContentType = "text/html; charset=UTF-8"; - } else { - bodyContentType = "text/plain; charset=UTF-8"; - } - return bodyContentType; - } - - protected void assignFromAddress(SendingMessage sendingMessage, MimeMessage msg) throws MessagingException { - InternetAddress[] internetAddresses = InternetAddress.parse(sendingMessage.getFrom()); - for (InternetAddress internetAddress : internetAddresses) { - if (StringUtils.isNotEmpty(internetAddress.getPersonal())) { - try { - internetAddress.setPersonal(internetAddress.getPersonal(), StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new MessagingException("Unsupported encoding type", e); - } - } - } - - if (internetAddresses.length == 1) { - msg.setFrom(internetAddresses[0]); - } else { - msg.addFrom(internetAddresses); - } - } - - private void addHeaders(SendingMessage sendingMessage, MimeMessage message) throws MessagingException { - if (sendingMessage.getHeaders() == null) - return; - String[] splitHeaders = sendingMessage.getHeaders().split(SendingMessage.HEADERS_SEPARATOR); - for (String header : splitHeaders) { - EmailHeader emailHeader = EmailHeader.parse(header); - if (emailHeader != null) { - message.addHeader(emailHeader.getName(), emailHeader.getValue()); - } else { - log.warn("Can't parse email header: '" + header + "'"); - } - } - } - - protected MimeBodyPart createAttachmentPart(SendingAttachment attachment) throws MessagingException { - DataSource source = new MyByteArrayDataSource(attachment.getContent()); - - String mimeType = FileTypesHelper.getMIMEType(attachment.getName()); - String encodedFileName = encodeAttachmentName(attachment); - - String contentId = attachment.getContentId(); - if (contentId == null) { - contentId = encodedFileName; - } - - String disposition = attachment.getDisposition() != null ? attachment.getDisposition() : Part.INLINE; - String charset = MimeUtility.mimeCharset(attachment.getEncoding() != null ? - attachment.getEncoding() : StandardCharsets.UTF_8.name()); - String contentTypeValue = String.format("%s; charset=%s; name=%s", mimeType, charset, encodedFileName); - - MimeBodyPart attachmentPart = new MimeBodyPart(); - attachmentPart.setDataHandler(new DataHandler(source)); - attachmentPart.setHeader("Content-ID", "<" + contentId + ">"); - attachmentPart.setHeader("Content-Type", contentTypeValue); - attachmentPart.setFileName(encodedFileName); - attachmentPart.setDisposition(disposition); - - return attachmentPart; - } - - protected String encodeAttachmentName(SendingAttachment attachment) { - String encodedFileName; - try { - QCodec qCodec = new QCodec(); - encodedFileName = qCodec.encode(attachment.getName()); - } catch (EncoderException e) { - encodedFileName = attachment.getName(); - } - return encodedFileName; - } - - protected static class MyByteArrayDataSource implements DataSource { - private byte[] data; - - public MyByteArrayDataSource(byte[] data) { - this.data = data; - } - - @Override - public String getContentType() { - return "application/octet-stream"; - } - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(data); - } - - @Override - public String getName() { - return "ByteArray"; - } - - @Override - public OutputStream getOutputStream() throws IOException { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.SendingAttachment; +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.EmailHeader; +import com.haulmont.cuba.core.global.FileTypesHelper; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.sys.CubaMailSender; +import org.apache.commons.codec.EncoderException; +import org.apache.commons.codec.net.QCodec; +import org.apache.commons.lang.StringUtils; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.mail.javamail.JavaMailSender; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import org.springframework.stereotype.Component; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Part; +import javax.mail.internet.*; +import java.io.*; +import java.nio.charset.StandardCharsets; + +@Component(EmailSenderAPI.NAME) +public class EmailSender implements EmailSenderAPI { + + private Logger log = LoggerFactory.getLogger(EmailSender.class); + + protected JavaMailSender mailSender; + + @Inject + protected TimeSource timeSource; + + @Resource(name = CubaMailSender.NAME) + public void setMailSender(JavaMailSender mailSender) { + this.mailSender = mailSender; + } + + @Override + public void sendEmail(SendingMessage sendingMessage) throws MessagingException { + MimeMessage msg = createMimeMessage(sendingMessage); + + StopWatch sw = new Log4JStopWatch("EmailSender.send"); + mailSender.send(msg); + sw.stop(); + + log.info("Email '" + msg.getSubject() + "' to '" + sendingMessage.getAddress() + "' has been sent successfully"); + } + + protected MimeMessage createMimeMessage(SendingMessage sendingMessage) throws MessagingException { + MimeMessage msg = mailSender.createMimeMessage(); + assignRecipient(sendingMessage, msg); + msg.setSubject(sendingMessage.getCaption(), StandardCharsets.UTF_8.name()); + msg.setSentDate(timeSource.currentTimestamp()); + + assignFromAddress(sendingMessage, msg); + addHeaders(sendingMessage, msg); + + MimeMultipart content = new MimeMultipart("mixed"); + MimeMultipart textPart = new MimeMultipart("related"); + + setMimeMessageContent(sendingMessage, content, textPart); + + for (SendingAttachment attachment : sendingMessage.getAttachments()) { + MimeBodyPart attachmentPart = createAttachmentPart(attachment); + + if (attachment.getContentId() == null) { + content.addBodyPart(attachmentPart); + } else + textPart.addBodyPart(attachmentPart); + } + + msg.setContent(content); + msg.saveChanges(); + return msg; + } + + protected void setMimeMessageContent(SendingMessage sendingMessage, MimeMultipart content, MimeMultipart textPart) + throws MessagingException { + MimeBodyPart textBodyPart = new MimeBodyPart(); + MimeBodyPart contentBodyPart = new MimeBodyPart(); + String bodyContentType = getContentBodyType(sendingMessage); + + contentBodyPart.setContent(sendingMessage.getContentText(), bodyContentType); + textPart.addBodyPart(contentBodyPart); + textBodyPart.setContent(textPart); + content.addBodyPart(textBodyPart); + } + + protected void assignRecipient(SendingMessage sendingMessage, MimeMessage message) throws MessagingException { + InternetAddress internetAddress = new InternetAddress(sendingMessage.getAddress().trim()); + message.setRecipient(Message.RecipientType.TO, internetAddress); + } + + protected String getContentBodyType(SendingMessage sendingMessage) { + String text = sendingMessage.getContentText(); + String bodyContentType; + if (text.trim().startsWith("")) { + bodyContentType = "text/html; charset=UTF-8"; + } else { + bodyContentType = "text/plain; charset=UTF-8"; + } + return bodyContentType; + } + + protected void assignFromAddress(SendingMessage sendingMessage, MimeMessage msg) throws MessagingException { + InternetAddress[] internetAddresses = InternetAddress.parse(sendingMessage.getFrom()); + for (InternetAddress internetAddress : internetAddresses) { + if (StringUtils.isNotEmpty(internetAddress.getPersonal())) { + try { + internetAddress.setPersonal(internetAddress.getPersonal(), StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new MessagingException("Unsupported encoding type", e); + } + } + } + + if (internetAddresses.length == 1) { + msg.setFrom(internetAddresses[0]); + } else { + msg.addFrom(internetAddresses); + } + } + + private void addHeaders(SendingMessage sendingMessage, MimeMessage message) throws MessagingException { + if (sendingMessage.getHeaders() == null) + return; + String[] splitHeaders = sendingMessage.getHeaders().split(SendingMessage.HEADERS_SEPARATOR); + for (String header : splitHeaders) { + EmailHeader emailHeader = EmailHeader.parse(header); + if (emailHeader != null) { + message.addHeader(emailHeader.getName(), emailHeader.getValue()); + } else { + log.warn("Can't parse email header: '" + header + "'"); + } + } + } + + protected MimeBodyPart createAttachmentPart(SendingAttachment attachment) throws MessagingException { + DataSource source = new MyByteArrayDataSource(attachment.getContent()); + + String mimeType = FileTypesHelper.getMIMEType(attachment.getName()); + String encodedFileName = encodeAttachmentName(attachment); + + String contentId = attachment.getContentId(); + if (contentId == null) { + contentId = encodedFileName; + } + + String disposition = attachment.getDisposition() != null ? attachment.getDisposition() : Part.INLINE; + String charset = MimeUtility.mimeCharset(attachment.getEncoding() != null ? + attachment.getEncoding() : StandardCharsets.UTF_8.name()); + String contentTypeValue = String.format("%s; charset=%s; name=%s", mimeType, charset, encodedFileName); + + MimeBodyPart attachmentPart = new MimeBodyPart(); + attachmentPart.setDataHandler(new DataHandler(source)); + attachmentPart.setHeader("Content-ID", "<" + contentId + ">"); + attachmentPart.setHeader("Content-Type", contentTypeValue); + attachmentPart.setFileName(encodedFileName); + attachmentPart.setDisposition(disposition); + + return attachmentPart; + } + + protected String encodeAttachmentName(SendingAttachment attachment) { + String encodedFileName; + try { + QCodec qCodec = new QCodec(); + encodedFileName = qCodec.encode(attachment.getName()); + } catch (EncoderException e) { + encodedFileName = attachment.getName(); + } + return encodedFileName; + } + + protected static class MyByteArrayDataSource implements DataSource { + private byte[] data; + + public MyByteArrayDataSource(byte[] data) { + this.data = data; + } + + @Override + public String getContentType() { + return "application/octet-stream"; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(data); + } + + @Override + public String getName() { + return "ByteArray"; + } + + @Override + public OutputStream getOutputStream() throws IOException { + return null; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EmailSenderAPI.java b/modules/core/src/com/haulmont/cuba/core/app/EmailSenderAPI.java index a8de01b536..d88861433f 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EmailSenderAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EmailSenderAPI.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.SendingMessage; - -import javax.mail.MessagingException; - -/** - * Adapter to javax.mail email sending API. - *
- * Should not be used from application code, use {@link EmailerAPI}. - */ -public interface EmailSenderAPI { - String NAME = "cuba_EmailSender"; - - /** - * Sends email with help of {@link org.springframework.mail.javamail.JavaMailSender}. - * Message body and attachments' content must be loaded from file storage. - *
- * Use {@link EmailerAPI} instead if you need email to be delivered reliably and stored to email history. - * - * @throws MessagingException if delivery fails - */ - void sendEmail(SendingMessage sendingMessage) throws MessagingException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.SendingMessage; + +import javax.mail.MessagingException; + +/** + * Adapter to javax.mail email sending API. + *
+ * Should not be used from application code, use {@link EmailerAPI}. + */ +public interface EmailSenderAPI { + String NAME = "cuba_EmailSender"; + + /** + * Sends email with help of {@link org.springframework.mail.javamail.JavaMailSender}. + * Message body and attachments' content must be loaded from file storage. + *
+ * Use {@link EmailerAPI} instead if you need email to be delivered reliably and stored to email history. + * + * @throws MessagingException if delivery fails + */ + void sendEmail(SendingMessage sendingMessage) throws MessagingException; } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EmailServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/EmailServiceBean.java index 25b9292fbe..137b306c0c 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EmailServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EmailServiceBean.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.EmailAttachment; -import com.haulmont.cuba.core.global.EmailException; -import com.haulmont.cuba.core.global.EmailInfo; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.Date; - -@Service(EmailService.NAME) -public class EmailServiceBean implements EmailService { - - @Inject - protected EmailerAPI emailer; - - @Override - public void sendEmail(String address, String caption, String body, EmailAttachment... attachment) throws EmailException { - emailer.sendEmail(address, caption, body, attachment); - } - - @Override - public void sendEmail(EmailInfo info) throws EmailException { - emailer.sendEmail(info); - } - - @Override - public void sendEmailAsync(EmailInfo info, Integer attemptsCount, Date deadline) { - emailer.sendEmailAsync(info, attemptsCount, deadline); - } - - @Override - public void sendEmailAsync(EmailInfo info) { - emailer.sendEmailAsync(info); - } - - @Override - public String loadContentText(SendingMessage sendingMessage) { - return emailer.loadContentText(sendingMessage); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.EmailAttachment; +import com.haulmont.cuba.core.global.EmailException; +import com.haulmont.cuba.core.global.EmailInfo; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.Date; + +@Service(EmailService.NAME) +public class EmailServiceBean implements EmailService { + + @Inject + protected EmailerAPI emailer; + + @Override + public void sendEmail(String address, String caption, String body, EmailAttachment... attachment) throws EmailException { + emailer.sendEmail(address, caption, body, attachment); + } + + @Override + public void sendEmail(EmailInfo info) throws EmailException { + emailer.sendEmail(info); + } + + @Override + public void sendEmailAsync(EmailInfo info, Integer attemptsCount, Date deadline) { + emailer.sendEmailAsync(info, attemptsCount, deadline); + } + + @Override + public void sendEmailAsync(EmailInfo info) { + emailer.sendEmailAsync(info); + } + + @Override + public String loadContentText(SendingMessage sendingMessage) { + return emailer.loadContentText(sendingMessage); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/Emailer.java b/modules/core/src/com/haulmont/cuba/core/app/Emailer.java index 5d5da69600..780dd28167 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/Emailer.java +++ b/modules/core/src/com/haulmont/cuba/core/app/Emailer.java @@ -1,710 +1,710 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.entity.SendingAttachment; -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.security.app.Authentication; -import com.sun.mail.smtp.SMTPAddressFailedException; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.time.DateUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.task.TaskExecutor; -import org.springframework.mail.MailSendException; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.mail.internet.AddressException; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.RejectedExecutionException; - -@Component(EmailerAPI.NAME) -public class Emailer implements EmailerAPI { - - protected static final String BODY_FILE_EXTENSION = "txt"; - - private Logger log = LoggerFactory.getLogger(Emailer.class); - - protected EmailerConfig config; - - protected volatile int callCount = 0; - - @Resource(name = "mailSendTaskExecutor") - protected TaskExecutor mailSendTaskExecutor; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected TimeSource timeSource; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected Authentication authentication; - - @Inject - protected EmailSenderAPI emailSender; - - @Inject - protected Resources resources; - - @Inject - protected FileStorageAPI fileStorage; - - @Inject - public void setConfig(Configuration configuration) { - this.config = configuration.getConfig(EmailerConfig.class); - } - - protected String getEmailerLogin() { - return config.getEmailerUserLogin(); - } - - @Override - public void sendEmail(String addresses, String caption, String body, EmailAttachment... attachments) - throws EmailException { - sendEmail(new EmailInfo(addresses, caption, null, body, attachments)); - } - - @Override - public void sendEmail(EmailInfo info) throws EmailException { - prepareEmailInfo(info); - persistAndSendEmail(info); - } - - @Override - public List sendEmailAsync(EmailInfo info) { - //noinspection UnnecessaryLocalVariable - List result = sendEmailAsync(info, null, null); - return result; - } - - @Override - public List sendEmailAsync(EmailInfo info, Integer attemptsCount, Date deadline) { - prepareEmailInfo(info); - List messages = splitEmail(info, attemptsCount, deadline); - persistMessages(messages, SendingStatus.QUEUE); - return messages; - } - - protected void prepareEmailInfo(EmailInfo emailInfo) { - processBodyTemplate(emailInfo); - - if (emailInfo.getFrom() == null) { - String defaultFromAddress = config.getFromAddress(); - if (defaultFromAddress == null) { - throw new IllegalStateException("cuba.email.fromAddress not set in the system"); - } - emailInfo.setFrom(defaultFromAddress); - } - } - - protected void processBodyTemplate(EmailInfo info) { - String templatePath = info.getTemplatePath(); - if (templatePath == null) { - return; - } - - Map params = info.getTemplateParameters() == null - ? Collections.emptyMap() - : info.getTemplateParameters(); - String templateContents = resources.getResourceAsString(templatePath); - if (templateContents == null) { - throw new IllegalArgumentException("Could not find template by path: " + templatePath); - } - String body = TemplateHelper.processTemplate(templateContents, params); - info.setBody(body); - } - - protected List splitEmail(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline) { - List sendingMessageList = new ArrayList<>(); - String[] splitAddresses = info.getAddresses().split("[,;]"); - for (String address : splitAddresses) { - address = address.trim(); - if (StringUtils.isNotBlank(address)) { - SendingMessage sendingMessage = convertToSendingMessage(address, info.getFrom(), info.getCaption(), - info.getBody(), info.getHeaders(), info.getAttachments(), attemptsCount, deadline); - - sendingMessageList.add(sendingMessage); - } - } - return sendingMessageList; - } - - protected void sendSendingMessage(SendingMessage sendingMessage) { - Objects.requireNonNull(sendingMessage, "sendingMessage is null"); - Objects.requireNonNull(sendingMessage.getAddress(), "sendingMessage.address is null"); - Objects.requireNonNull(sendingMessage.getCaption(), "sendingMessage.caption is null"); - Objects.requireNonNull(sendingMessage.getContentText(), "sendingMessage.contentText is null"); - Objects.requireNonNull(sendingMessage.getFrom(), "sendingMessage.from is null"); - try { - emailSender.sendEmail(sendingMessage); - markAsSent(sendingMessage); - } catch (Exception e) { - log.warn("Unable to send email to '" + sendingMessage.getAddress() + "'", e); - if (isNeedToRetry(e)) { - returnToQueue(sendingMessage); - } else { - markAsNonSent(sendingMessage); - } - } - } - - protected void persistAndSendEmail(EmailInfo emailInfo) throws EmailException { - Objects.requireNonNull(emailInfo.getAddresses(), "addresses are null"); - Objects.requireNonNull(emailInfo.getCaption(), "caption is null"); - Objects.requireNonNull(emailInfo.getBody(), "body is null"); - Objects.requireNonNull(emailInfo.getFrom(), "from is null"); - - List messages = splitEmail(emailInfo, null, null); - - List failedAddresses = new ArrayList<>(); - List errorMessages = new ArrayList<>(); - - for (SendingMessage sendingMessage : messages) { - SendingMessage persistedMessage = persistMessageIfPossible(sendingMessage); - - try { - emailSender.sendEmail(sendingMessage); - if (persistedMessage != null) { - markAsSent(persistedMessage); - } - } catch (Exception e) { - log.warn("Unable to send email to '" + sendingMessage.getAddress() + "'", e); - failedAddresses.add(sendingMessage.getAddress()); - errorMessages.add(e.getMessage()); - if (persistedMessage != null) { - markAsNonSent(persistedMessage); - } - } - } - - if (!failedAddresses.isEmpty()) { - throw new EmailException(failedAddresses, errorMessages); - } - } - - /* - * Try to persist message and catch all errors to allow actual delivery - * in case of database or file storage failure. - */ - @Nullable - protected SendingMessage persistMessageIfPossible(SendingMessage sendingMessage) { - // A copy of sendingMessage is created - // to avoid additional overhead to load body and attachments back from FS - try { - SendingMessage clonedMessage = createClone(sendingMessage); - persistMessages(Collections.singletonList(clonedMessage), SendingStatus.SENDING); - return clonedMessage; - } catch (Exception e) { - log.error("Failed to persist message " + sendingMessage.getCaption(), e); - return null; - } - } - - protected SendingMessage createClone(SendingMessage srcMessage) { - SendingMessage clonedMessage = metadata.getTools().copy(srcMessage); - List clonedList = new ArrayList<>(); - for (SendingAttachment srcAttach : srcMessage.getAttachments()) { - SendingAttachment clonedAttach = (SendingAttachment) metadata.getTools().copy(srcAttach); - clonedAttach.setMessage(null); - clonedAttach.setMessage(clonedMessage); - clonedList.add(clonedAttach); - } - clonedMessage.setAttachments(clonedList); - return clonedMessage; - } - - @Override - public String processQueuedEmails() { - if (applicationNotStartedYet()) { - return null; - } - - int callsToSkip = config.getDelayCallCount(); - if (callCount < callsToSkip) { - callCount++; - return null; - } - - String resultMessage; - try { - authentication.begin(getEmailerLogin()); - try { - resultMessage = sendQueuedEmails(); - } finally { - authentication.end(); - } - } catch (Throwable e) { - log.error("Error", e); - resultMessage = e.getMessage(); - } - return resultMessage; - } - - protected boolean applicationNotStartedYet() { - return !AppContext.isStarted(); - } - - protected String sendQueuedEmails() { - List messagesToSend = loadEmailsToSend(); - - for (SendingMessage msg : messagesToSend) { - submitExecutorTask(msg); - } - - if (messagesToSend.isEmpty()) { - return ""; - } - - return String.format("Processed %d emails", messagesToSend.size()); - } - - protected boolean shouldMarkNotSent(SendingMessage sendingMessage) { - Date deadline = sendingMessage.getDeadline(); - if (deadline != null && deadline.before(timeSource.currentTimestamp())) { - return true; - } - - Integer messageAttemptsLimit = sendingMessage.getAttemptsCount(); - int defaultLimit = config.getDefaultSendingAttemptsCount(); - int attemptsLimit = messageAttemptsLimit != null ? messageAttemptsLimit : defaultLimit; - //noinspection UnnecessaryLocalVariable - boolean res = sendingMessage.getAttemptsMade() != null && sendingMessage.getAttemptsMade() >= attemptsLimit; - return res; - } - - protected void submitExecutorTask(SendingMessage msg) { - try { - Runnable mailSendTask = new EmailSendTask(msg); - mailSendTaskExecutor.execute(mailSendTask); - } catch (RejectedExecutionException e) { - returnToQueue(msg); - } catch (Exception e) { - log.error("Exception while sending email: ", e); - if (isNeedToRetry(e)) { - returnToQueue(msg); - } else { - markAsNonSent(msg); - } - } - } - - protected List loadEmailsToSend() { - Date sendTimeoutTime = DateUtils.addSeconds(timeSource.currentTimestamp(), -config.getSendingTimeoutSec()); - - List emailsToSend = new ArrayList<>(); - - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - TypedQuery query = em.createQuery( - "select sm from sys$SendingMessage sm" + - " where sm.status = :statusQueue or (sm.status = :statusSending and sm.updateTs < :time)" + - " order by sm.createTs", - SendingMessage.class - ); - query.setParameter("statusQueue", SendingStatus.QUEUE.getId()); - query.setParameter("time", sendTimeoutTime); - query.setParameter("statusSending", SendingStatus.SENDING.getId()); - - View view = metadata.getViewRepository().getView(SendingMessage.class, "sendingMessage.loadFromQueue"); - view.setLoadPartialEntities(true); // because SendingAttachment.content has FetchType.LAZY - query.setView(view); - - query.setMaxResults(config.getMessageQueueCapacity()); - - List resList = query.getResultList(); - - for (SendingMessage msg : resList) { - if (shouldMarkNotSent(msg)) { - msg.setStatus(SendingStatus.NOTSENT); - } else { - msg.setStatus(SendingStatus.SENDING); - emailsToSend.add(msg); - } - } - tx.commit(); - } - - for (SendingMessage message : emailsToSend) { - loadBodyAndAttachments(message); - } - return emailsToSend; - } - - @Override - public String loadContentText(SendingMessage sendingMessage) { - SendingMessage msg; - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - msg = em.reload(sendingMessage, "sendingMessage.loadContentText"); - tx.commit(); - } - Objects.requireNonNull(msg, "Sending message not found: " + sendingMessage.getId()); - if (msg.getContentTextFile() != null) { - byte[] bodyContent; - try { - bodyContent = fileStorage.loadFile(msg.getContentTextFile()); - } catch (FileStorageException e) { - throw new RuntimeException(e); - } - //noinspection UnnecessaryLocalVariable - String res = bodyTextFromByteArray(bodyContent); - return res; - } else { - return msg.getContentText(); - } - } - - protected void loadBodyAndAttachments(SendingMessage message) { - try { - if (message.getContentTextFile() != null) { - byte[] bodyContent = fileStorage.loadFile(message.getContentTextFile()); - String body = bodyTextFromByteArray(bodyContent); - message.setContentText(body); - } - - for (SendingAttachment attachment : message.getAttachments()) { - if (attachment.getContentFile() != null) { - byte[] content = fileStorage.loadFile(attachment.getContentFile()); - attachment.setContent(content); - } - } - } catch (FileStorageException e) { - log.error("Failed to load body or attachments for " + message); - } - } - - protected void persistMessages(List sendingMessageList, SendingStatus status) { - MessagePersistingContext context = new MessagePersistingContext(); - - try { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - for (SendingMessage message : sendingMessageList) { - message.setStatus(status); - - try { - persistSendingMessage(em, message, context); - } catch (FileStorageException e) { - throw new RuntimeException("Failed to store message " + message.getCaption(), e); - } - } - tx.commit(); - } - context.finished(); - } finally { - removeOrphanFiles(context); - } - } - - protected void removeOrphanFiles(MessagePersistingContext context) { - for (FileDescriptor file : context.files) { - try { - fileStorage.removeFile(file); - } catch (Exception e) { - log.error("Failed to remove file " + file); - } - } - } - - protected void persistSendingMessage(EntityManager em, SendingMessage message, - MessagePersistingContext context) throws FileStorageException { - boolean useFileStorage = config.isFileStorageUsed(); - - if (useFileStorage) { - byte[] bodyBytes = bodyTextToBytes(message); - - FileDescriptor contentTextFile = createBodyFileDescriptor(message, bodyBytes); - fileStorage.saveFile(contentTextFile, bodyBytes); - context.files.add(contentTextFile); - - em.persist(contentTextFile); - message.setContentTextFile(contentTextFile); - message.setContentText(null); - } - - em.persist(message); - - for (SendingAttachment attachment : message.getAttachments()) { - if (useFileStorage) { - FileDescriptor contentFile = createAttachmentFileDescriptor(attachment); - - fileStorage.saveFile(contentFile, attachment.getContent()); - context.files.add(contentFile); - em.persist(contentFile); - - attachment.setContentFile(contentFile); - attachment.setContent(null); - } - - em.persist(attachment); - } - } - - protected FileDescriptor createAttachmentFileDescriptor(SendingAttachment attachment) { - FileDescriptor contentFile = metadata.create(FileDescriptor.class); - contentFile.setCreateDate(timeSource.currentTimestamp()); - contentFile.setName(attachment.getName()); - contentFile.setExtension(FilenameUtils.getExtension(attachment.getName())); - contentFile.setSize((long) attachment.getContent().length); - return contentFile; - } - - protected FileDescriptor createBodyFileDescriptor(SendingMessage message, byte[] bodyBytes) { - FileDescriptor contentTextFile = metadata.create(FileDescriptor.class); - contentTextFile.setCreateDate(timeSource.currentTimestamp()); - contentTextFile.setName("Email_" + message.getId() + "." + BODY_FILE_EXTENSION); - contentTextFile.setExtension(BODY_FILE_EXTENSION); - contentTextFile.setSize((long) bodyBytes.length); - return contentTextFile; - } - - protected void returnToQueue(SendingMessage sendingMessage) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - SendingMessage msg = em.merge(sendingMessage); - - msg.setAttemptsMade(msg.getAttemptsMade() + 1); - msg.setStatus(SendingStatus.QUEUE); - - tx.commit(); - } catch (Exception e) { - log.error("Error returning message to '{}' to the queue", sendingMessage.getAddress(), e); - } - } - - protected void markAsSent(SendingMessage sendingMessage) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - SendingMessage msg = em.merge(sendingMessage); - - msg.setStatus(SendingStatus.SENT); - msg.setAttemptsMade(msg.getAttemptsMade() + 1); - msg.setDateSent(timeSource.currentTimestamp()); - - tx.commit(); - } catch (Exception e) { - log.error("Error marking message to '{}' as sent", sendingMessage.getAddress(), e); - } - } - - protected void markAsNonSent(SendingMessage sendingMessage) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - SendingMessage msg = em.merge(sendingMessage); - - msg.setStatus(SendingStatus.NOTSENT); - msg.setAttemptsMade(msg.getAttemptsMade() + 1); - - tx.commit(); - } catch (Exception e) { - log.error("Error marking message to '{}' as not sent", sendingMessage.getAddress(), e); - } - } - - protected SendingMessage convertToSendingMessage(String address, String from, String caption, String body, @Nullable List headers, - @Nullable EmailAttachment[] attachments, - @Nullable Integer attemptsCount, @Nullable Date deadline) { - SendingMessage sendingMessage = metadata.create(SendingMessage.class); - - sendingMessage.setAddress(address); - sendingMessage.setFrom(from); - sendingMessage.setContentText(body); - sendingMessage.setCaption(caption); - sendingMessage.setAttemptsCount(attemptsCount); - sendingMessage.setDeadline(deadline); - sendingMessage.setAttemptsMade(0); - - if (attachments != null && attachments.length > 0) { - StringBuilder attachmentsName = new StringBuilder(); - List sendingAttachments = new ArrayList<>(attachments.length); - for (EmailAttachment ea : attachments) { - attachmentsName.append(ea.getName()).append(";"); - - SendingAttachment sendingAttachment = toSendingAttachment(ea); - sendingAttachment.setMessage(sendingMessage); - sendingAttachments.add(sendingAttachment); - } - sendingMessage.setAttachments(sendingAttachments); - sendingMessage.setAttachmentsName(attachmentsName.toString()); - } else { - sendingMessage.setAttachments(Collections.emptyList()); - } - - if (headers != null && !headers.isEmpty()) { - StringBuilder headersLine = new StringBuilder(); - for (EmailHeader header : headers) { - headersLine.append(header.toString()).append(SendingMessage.HEADERS_SEPARATOR); - } - sendingMessage.setHeaders(headersLine.toString()); - } else { - sendingMessage.setHeaders(null); - } - - replaceRecipientIfNecessary(sendingMessage); - - return sendingMessage; - } - - protected void replaceRecipientIfNecessary(SendingMessage msg) { - if (config.getSendAllToAdmin()) { - String adminAddress = config.getAdminAddress(); - log.warn(String.format( - "Replacing actual email recipient '%s' by admin address '%s'", msg.getAddress(), adminAddress - )); - msg.setAddress(adminAddress); - } - } - - protected SendingAttachment toSendingAttachment(EmailAttachment ea) { - SendingAttachment sendingAttachment = metadata.create(SendingAttachment.class); - sendingAttachment.setContent(ea.getData()); - sendingAttachment.setContentId(ea.getContentId()); - sendingAttachment.setName(ea.getName()); - sendingAttachment.setEncoding(ea.getEncoding()); - sendingAttachment.setDisposition(ea.getDisposition()); - return sendingAttachment; - } - - protected byte[] bodyTextToBytes(SendingMessage message) { - byte[] bodyBytes = message.getContentText().getBytes(StandardCharsets.UTF_8); - return bodyBytes; - } - - protected String bodyTextFromByteArray(byte[] bodyContent) { - return new String(bodyContent, StandardCharsets.UTF_8); - } - - protected boolean isNeedToRetry(Exception e) { - if (e instanceof MailSendException) { - if (e.getCause() instanceof SMTPAddressFailedException) { - return false; - } - } else if (e instanceof AddressException) { - return false; - } - return true; - } - - @Override - public void migrateEmailsToFileStorage(List messages) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - for (SendingMessage msg : messages) { - migrateMessage(em, msg); - } - tx.commit(); - } - } - - @Override - public void migrateAttachmentsToFileStorage(List attachments) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - for (SendingAttachment attachment : attachments) { - migrateAttachment(em, attachment); - } - - tx.commit(); - } - } - - protected void migrateMessage(EntityManager em, SendingMessage msg) { - msg = em.merge(msg); - byte[] bodyBytes = bodyTextToBytes(msg); - FileDescriptor bodyFile = createBodyFileDescriptor(msg, bodyBytes); - - try { - fileStorage.saveFile(bodyFile, bodyBytes); - } catch (FileStorageException e) { - throw new RuntimeException(e); - } - em.persist(bodyFile); - msg.setContentTextFile(bodyFile); - msg.setContentText(null); - } - - protected void migrateAttachment(EntityManager em, SendingAttachment attachment) { - attachment = em.merge(attachment); - FileDescriptor contentFile = createAttachmentFileDescriptor(attachment); - - try { - fileStorage.saveFile(contentFile, attachment.getContent()); - } catch (FileStorageException e) { - throw new RuntimeException(e); - } - em.persist(contentFile); - attachment.setContentFile(contentFile); - attachment.setContent(null); - } - - protected static class EmailSendTask implements Runnable { - - private SendingMessage sendingMessage; - private Logger log = LoggerFactory.getLogger(EmailSendTask.class); - - public EmailSendTask(SendingMessage message) { - sendingMessage = message; - } - - @Override - public void run() { - try { - Authentication authentication = AppBeans.get(Authentication.NAME); - Emailer emailer = AppBeans.get(EmailerAPI.NAME); - - authentication.begin(emailer.getEmailerLogin()); - try { - emailer.sendSendingMessage(sendingMessage); - } finally { - authentication.end(); - } - } catch (Exception e) { - log.error("Exception while sending email: ", e); - } - } - } - - protected static class MessagePersistingContext { - public final List files = new ArrayList<>(); - - public void finished() { - files.clear(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.entity.SendingAttachment; +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.security.app.Authentication; +import com.sun.mail.smtp.SMTPAddressFailedException; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.time.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.task.TaskExecutor; +import org.springframework.mail.MailSendException; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.mail.internet.AddressException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.RejectedExecutionException; + +@Component(EmailerAPI.NAME) +public class Emailer implements EmailerAPI { + + protected static final String BODY_FILE_EXTENSION = "txt"; + + private Logger log = LoggerFactory.getLogger(Emailer.class); + + protected EmailerConfig config; + + protected volatile int callCount = 0; + + @Resource(name = "mailSendTaskExecutor") + protected TaskExecutor mailSendTaskExecutor; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected TimeSource timeSource; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected Authentication authentication; + + @Inject + protected EmailSenderAPI emailSender; + + @Inject + protected Resources resources; + + @Inject + protected FileStorageAPI fileStorage; + + @Inject + public void setConfig(Configuration configuration) { + this.config = configuration.getConfig(EmailerConfig.class); + } + + protected String getEmailerLogin() { + return config.getEmailerUserLogin(); + } + + @Override + public void sendEmail(String addresses, String caption, String body, EmailAttachment... attachments) + throws EmailException { + sendEmail(new EmailInfo(addresses, caption, null, body, attachments)); + } + + @Override + public void sendEmail(EmailInfo info) throws EmailException { + prepareEmailInfo(info); + persistAndSendEmail(info); + } + + @Override + public List sendEmailAsync(EmailInfo info) { + //noinspection UnnecessaryLocalVariable + List result = sendEmailAsync(info, null, null); + return result; + } + + @Override + public List sendEmailAsync(EmailInfo info, Integer attemptsCount, Date deadline) { + prepareEmailInfo(info); + List messages = splitEmail(info, attemptsCount, deadline); + persistMessages(messages, SendingStatus.QUEUE); + return messages; + } + + protected void prepareEmailInfo(EmailInfo emailInfo) { + processBodyTemplate(emailInfo); + + if (emailInfo.getFrom() == null) { + String defaultFromAddress = config.getFromAddress(); + if (defaultFromAddress == null) { + throw new IllegalStateException("cuba.email.fromAddress not set in the system"); + } + emailInfo.setFrom(defaultFromAddress); + } + } + + protected void processBodyTemplate(EmailInfo info) { + String templatePath = info.getTemplatePath(); + if (templatePath == null) { + return; + } + + Map params = info.getTemplateParameters() == null + ? Collections.emptyMap() + : info.getTemplateParameters(); + String templateContents = resources.getResourceAsString(templatePath); + if (templateContents == null) { + throw new IllegalArgumentException("Could not find template by path: " + templatePath); + } + String body = TemplateHelper.processTemplate(templateContents, params); + info.setBody(body); + } + + protected List splitEmail(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline) { + List sendingMessageList = new ArrayList<>(); + String[] splitAddresses = info.getAddresses().split("[,;]"); + for (String address : splitAddresses) { + address = address.trim(); + if (StringUtils.isNotBlank(address)) { + SendingMessage sendingMessage = convertToSendingMessage(address, info.getFrom(), info.getCaption(), + info.getBody(), info.getHeaders(), info.getAttachments(), attemptsCount, deadline); + + sendingMessageList.add(sendingMessage); + } + } + return sendingMessageList; + } + + protected void sendSendingMessage(SendingMessage sendingMessage) { + Objects.requireNonNull(sendingMessage, "sendingMessage is null"); + Objects.requireNonNull(sendingMessage.getAddress(), "sendingMessage.address is null"); + Objects.requireNonNull(sendingMessage.getCaption(), "sendingMessage.caption is null"); + Objects.requireNonNull(sendingMessage.getContentText(), "sendingMessage.contentText is null"); + Objects.requireNonNull(sendingMessage.getFrom(), "sendingMessage.from is null"); + try { + emailSender.sendEmail(sendingMessage); + markAsSent(sendingMessage); + } catch (Exception e) { + log.warn("Unable to send email to '" + sendingMessage.getAddress() + "'", e); + if (isNeedToRetry(e)) { + returnToQueue(sendingMessage); + } else { + markAsNonSent(sendingMessage); + } + } + } + + protected void persistAndSendEmail(EmailInfo emailInfo) throws EmailException { + Objects.requireNonNull(emailInfo.getAddresses(), "addresses are null"); + Objects.requireNonNull(emailInfo.getCaption(), "caption is null"); + Objects.requireNonNull(emailInfo.getBody(), "body is null"); + Objects.requireNonNull(emailInfo.getFrom(), "from is null"); + + List messages = splitEmail(emailInfo, null, null); + + List failedAddresses = new ArrayList<>(); + List errorMessages = new ArrayList<>(); + + for (SendingMessage sendingMessage : messages) { + SendingMessage persistedMessage = persistMessageIfPossible(sendingMessage); + + try { + emailSender.sendEmail(sendingMessage); + if (persistedMessage != null) { + markAsSent(persistedMessage); + } + } catch (Exception e) { + log.warn("Unable to send email to '" + sendingMessage.getAddress() + "'", e); + failedAddresses.add(sendingMessage.getAddress()); + errorMessages.add(e.getMessage()); + if (persistedMessage != null) { + markAsNonSent(persistedMessage); + } + } + } + + if (!failedAddresses.isEmpty()) { + throw new EmailException(failedAddresses, errorMessages); + } + } + + /* + * Try to persist message and catch all errors to allow actual delivery + * in case of database or file storage failure. + */ + @Nullable + protected SendingMessage persistMessageIfPossible(SendingMessage sendingMessage) { + // A copy of sendingMessage is created + // to avoid additional overhead to load body and attachments back from FS + try { + SendingMessage clonedMessage = createClone(sendingMessage); + persistMessages(Collections.singletonList(clonedMessage), SendingStatus.SENDING); + return clonedMessage; + } catch (Exception e) { + log.error("Failed to persist message " + sendingMessage.getCaption(), e); + return null; + } + } + + protected SendingMessage createClone(SendingMessage srcMessage) { + SendingMessage clonedMessage = metadata.getTools().copy(srcMessage); + List clonedList = new ArrayList<>(); + for (SendingAttachment srcAttach : srcMessage.getAttachments()) { + SendingAttachment clonedAttach = (SendingAttachment) metadata.getTools().copy(srcAttach); + clonedAttach.setMessage(null); + clonedAttach.setMessage(clonedMessage); + clonedList.add(clonedAttach); + } + clonedMessage.setAttachments(clonedList); + return clonedMessage; + } + + @Override + public String processQueuedEmails() { + if (applicationNotStartedYet()) { + return null; + } + + int callsToSkip = config.getDelayCallCount(); + if (callCount < callsToSkip) { + callCount++; + return null; + } + + String resultMessage; + try { + authentication.begin(getEmailerLogin()); + try { + resultMessage = sendQueuedEmails(); + } finally { + authentication.end(); + } + } catch (Throwable e) { + log.error("Error", e); + resultMessage = e.getMessage(); + } + return resultMessage; + } + + protected boolean applicationNotStartedYet() { + return !AppContext.isStarted(); + } + + protected String sendQueuedEmails() { + List messagesToSend = loadEmailsToSend(); + + for (SendingMessage msg : messagesToSend) { + submitExecutorTask(msg); + } + + if (messagesToSend.isEmpty()) { + return ""; + } + + return String.format("Processed %d emails", messagesToSend.size()); + } + + protected boolean shouldMarkNotSent(SendingMessage sendingMessage) { + Date deadline = sendingMessage.getDeadline(); + if (deadline != null && deadline.before(timeSource.currentTimestamp())) { + return true; + } + + Integer messageAttemptsLimit = sendingMessage.getAttemptsCount(); + int defaultLimit = config.getDefaultSendingAttemptsCount(); + int attemptsLimit = messageAttemptsLimit != null ? messageAttemptsLimit : defaultLimit; + //noinspection UnnecessaryLocalVariable + boolean res = sendingMessage.getAttemptsMade() != null && sendingMessage.getAttemptsMade() >= attemptsLimit; + return res; + } + + protected void submitExecutorTask(SendingMessage msg) { + try { + Runnable mailSendTask = new EmailSendTask(msg); + mailSendTaskExecutor.execute(mailSendTask); + } catch (RejectedExecutionException e) { + returnToQueue(msg); + } catch (Exception e) { + log.error("Exception while sending email: ", e); + if (isNeedToRetry(e)) { + returnToQueue(msg); + } else { + markAsNonSent(msg); + } + } + } + + protected List loadEmailsToSend() { + Date sendTimeoutTime = DateUtils.addSeconds(timeSource.currentTimestamp(), -config.getSendingTimeoutSec()); + + List emailsToSend = new ArrayList<>(); + + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + TypedQuery query = em.createQuery( + "select sm from sys$SendingMessage sm" + + " where sm.status = :statusQueue or (sm.status = :statusSending and sm.updateTs < :time)" + + " order by sm.createTs", + SendingMessage.class + ); + query.setParameter("statusQueue", SendingStatus.QUEUE.getId()); + query.setParameter("time", sendTimeoutTime); + query.setParameter("statusSending", SendingStatus.SENDING.getId()); + + View view = metadata.getViewRepository().getView(SendingMessage.class, "sendingMessage.loadFromQueue"); + view.setLoadPartialEntities(true); // because SendingAttachment.content has FetchType.LAZY + query.setView(view); + + query.setMaxResults(config.getMessageQueueCapacity()); + + List resList = query.getResultList(); + + for (SendingMessage msg : resList) { + if (shouldMarkNotSent(msg)) { + msg.setStatus(SendingStatus.NOTSENT); + } else { + msg.setStatus(SendingStatus.SENDING); + emailsToSend.add(msg); + } + } + tx.commit(); + } + + for (SendingMessage message : emailsToSend) { + loadBodyAndAttachments(message); + } + return emailsToSend; + } + + @Override + public String loadContentText(SendingMessage sendingMessage) { + SendingMessage msg; + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + msg = em.reload(sendingMessage, "sendingMessage.loadContentText"); + tx.commit(); + } + Objects.requireNonNull(msg, "Sending message not found: " + sendingMessage.getId()); + if (msg.getContentTextFile() != null) { + byte[] bodyContent; + try { + bodyContent = fileStorage.loadFile(msg.getContentTextFile()); + } catch (FileStorageException e) { + throw new RuntimeException(e); + } + //noinspection UnnecessaryLocalVariable + String res = bodyTextFromByteArray(bodyContent); + return res; + } else { + return msg.getContentText(); + } + } + + protected void loadBodyAndAttachments(SendingMessage message) { + try { + if (message.getContentTextFile() != null) { + byte[] bodyContent = fileStorage.loadFile(message.getContentTextFile()); + String body = bodyTextFromByteArray(bodyContent); + message.setContentText(body); + } + + for (SendingAttachment attachment : message.getAttachments()) { + if (attachment.getContentFile() != null) { + byte[] content = fileStorage.loadFile(attachment.getContentFile()); + attachment.setContent(content); + } + } + } catch (FileStorageException e) { + log.error("Failed to load body or attachments for " + message); + } + } + + protected void persistMessages(List sendingMessageList, SendingStatus status) { + MessagePersistingContext context = new MessagePersistingContext(); + + try { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + for (SendingMessage message : sendingMessageList) { + message.setStatus(status); + + try { + persistSendingMessage(em, message, context); + } catch (FileStorageException e) { + throw new RuntimeException("Failed to store message " + message.getCaption(), e); + } + } + tx.commit(); + } + context.finished(); + } finally { + removeOrphanFiles(context); + } + } + + protected void removeOrphanFiles(MessagePersistingContext context) { + for (FileDescriptor file : context.files) { + try { + fileStorage.removeFile(file); + } catch (Exception e) { + log.error("Failed to remove file " + file); + } + } + } + + protected void persistSendingMessage(EntityManager em, SendingMessage message, + MessagePersistingContext context) throws FileStorageException { + boolean useFileStorage = config.isFileStorageUsed(); + + if (useFileStorage) { + byte[] bodyBytes = bodyTextToBytes(message); + + FileDescriptor contentTextFile = createBodyFileDescriptor(message, bodyBytes); + fileStorage.saveFile(contentTextFile, bodyBytes); + context.files.add(contentTextFile); + + em.persist(contentTextFile); + message.setContentTextFile(contentTextFile); + message.setContentText(null); + } + + em.persist(message); + + for (SendingAttachment attachment : message.getAttachments()) { + if (useFileStorage) { + FileDescriptor contentFile = createAttachmentFileDescriptor(attachment); + + fileStorage.saveFile(contentFile, attachment.getContent()); + context.files.add(contentFile); + em.persist(contentFile); + + attachment.setContentFile(contentFile); + attachment.setContent(null); + } + + em.persist(attachment); + } + } + + protected FileDescriptor createAttachmentFileDescriptor(SendingAttachment attachment) { + FileDescriptor contentFile = metadata.create(FileDescriptor.class); + contentFile.setCreateDate(timeSource.currentTimestamp()); + contentFile.setName(attachment.getName()); + contentFile.setExtension(FilenameUtils.getExtension(attachment.getName())); + contentFile.setSize((long) attachment.getContent().length); + return contentFile; + } + + protected FileDescriptor createBodyFileDescriptor(SendingMessage message, byte[] bodyBytes) { + FileDescriptor contentTextFile = metadata.create(FileDescriptor.class); + contentTextFile.setCreateDate(timeSource.currentTimestamp()); + contentTextFile.setName("Email_" + message.getId() + "." + BODY_FILE_EXTENSION); + contentTextFile.setExtension(BODY_FILE_EXTENSION); + contentTextFile.setSize((long) bodyBytes.length); + return contentTextFile; + } + + protected void returnToQueue(SendingMessage sendingMessage) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + SendingMessage msg = em.merge(sendingMessage); + + msg.setAttemptsMade(msg.getAttemptsMade() + 1); + msg.setStatus(SendingStatus.QUEUE); + + tx.commit(); + } catch (Exception e) { + log.error("Error returning message to '{}' to the queue", sendingMessage.getAddress(), e); + } + } + + protected void markAsSent(SendingMessage sendingMessage) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + SendingMessage msg = em.merge(sendingMessage); + + msg.setStatus(SendingStatus.SENT); + msg.setAttemptsMade(msg.getAttemptsMade() + 1); + msg.setDateSent(timeSource.currentTimestamp()); + + tx.commit(); + } catch (Exception e) { + log.error("Error marking message to '{}' as sent", sendingMessage.getAddress(), e); + } + } + + protected void markAsNonSent(SendingMessage sendingMessage) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + SendingMessage msg = em.merge(sendingMessage); + + msg.setStatus(SendingStatus.NOTSENT); + msg.setAttemptsMade(msg.getAttemptsMade() + 1); + + tx.commit(); + } catch (Exception e) { + log.error("Error marking message to '{}' as not sent", sendingMessage.getAddress(), e); + } + } + + protected SendingMessage convertToSendingMessage(String address, String from, String caption, String body, @Nullable List headers, + @Nullable EmailAttachment[] attachments, + @Nullable Integer attemptsCount, @Nullable Date deadline) { + SendingMessage sendingMessage = metadata.create(SendingMessage.class); + + sendingMessage.setAddress(address); + sendingMessage.setFrom(from); + sendingMessage.setContentText(body); + sendingMessage.setCaption(caption); + sendingMessage.setAttemptsCount(attemptsCount); + sendingMessage.setDeadline(deadline); + sendingMessage.setAttemptsMade(0); + + if (attachments != null && attachments.length > 0) { + StringBuilder attachmentsName = new StringBuilder(); + List sendingAttachments = new ArrayList<>(attachments.length); + for (EmailAttachment ea : attachments) { + attachmentsName.append(ea.getName()).append(";"); + + SendingAttachment sendingAttachment = toSendingAttachment(ea); + sendingAttachment.setMessage(sendingMessage); + sendingAttachments.add(sendingAttachment); + } + sendingMessage.setAttachments(sendingAttachments); + sendingMessage.setAttachmentsName(attachmentsName.toString()); + } else { + sendingMessage.setAttachments(Collections.emptyList()); + } + + if (headers != null && !headers.isEmpty()) { + StringBuilder headersLine = new StringBuilder(); + for (EmailHeader header : headers) { + headersLine.append(header.toString()).append(SendingMessage.HEADERS_SEPARATOR); + } + sendingMessage.setHeaders(headersLine.toString()); + } else { + sendingMessage.setHeaders(null); + } + + replaceRecipientIfNecessary(sendingMessage); + + return sendingMessage; + } + + protected void replaceRecipientIfNecessary(SendingMessage msg) { + if (config.getSendAllToAdmin()) { + String adminAddress = config.getAdminAddress(); + log.warn(String.format( + "Replacing actual email recipient '%s' by admin address '%s'", msg.getAddress(), adminAddress + )); + msg.setAddress(adminAddress); + } + } + + protected SendingAttachment toSendingAttachment(EmailAttachment ea) { + SendingAttachment sendingAttachment = metadata.create(SendingAttachment.class); + sendingAttachment.setContent(ea.getData()); + sendingAttachment.setContentId(ea.getContentId()); + sendingAttachment.setName(ea.getName()); + sendingAttachment.setEncoding(ea.getEncoding()); + sendingAttachment.setDisposition(ea.getDisposition()); + return sendingAttachment; + } + + protected byte[] bodyTextToBytes(SendingMessage message) { + byte[] bodyBytes = message.getContentText().getBytes(StandardCharsets.UTF_8); + return bodyBytes; + } + + protected String bodyTextFromByteArray(byte[] bodyContent) { + return new String(bodyContent, StandardCharsets.UTF_8); + } + + protected boolean isNeedToRetry(Exception e) { + if (e instanceof MailSendException) { + if (e.getCause() instanceof SMTPAddressFailedException) { + return false; + } + } else if (e instanceof AddressException) { + return false; + } + return true; + } + + @Override + public void migrateEmailsToFileStorage(List messages) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + for (SendingMessage msg : messages) { + migrateMessage(em, msg); + } + tx.commit(); + } + } + + @Override + public void migrateAttachmentsToFileStorage(List attachments) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + for (SendingAttachment attachment : attachments) { + migrateAttachment(em, attachment); + } + + tx.commit(); + } + } + + protected void migrateMessage(EntityManager em, SendingMessage msg) { + msg = em.merge(msg); + byte[] bodyBytes = bodyTextToBytes(msg); + FileDescriptor bodyFile = createBodyFileDescriptor(msg, bodyBytes); + + try { + fileStorage.saveFile(bodyFile, bodyBytes); + } catch (FileStorageException e) { + throw new RuntimeException(e); + } + em.persist(bodyFile); + msg.setContentTextFile(bodyFile); + msg.setContentText(null); + } + + protected void migrateAttachment(EntityManager em, SendingAttachment attachment) { + attachment = em.merge(attachment); + FileDescriptor contentFile = createAttachmentFileDescriptor(attachment); + + try { + fileStorage.saveFile(contentFile, attachment.getContent()); + } catch (FileStorageException e) { + throw new RuntimeException(e); + } + em.persist(contentFile); + attachment.setContentFile(contentFile); + attachment.setContent(null); + } + + protected static class EmailSendTask implements Runnable { + + private SendingMessage sendingMessage; + private Logger log = LoggerFactory.getLogger(EmailSendTask.class); + + public EmailSendTask(SendingMessage message) { + sendingMessage = message; + } + + @Override + public void run() { + try { + Authentication authentication = AppBeans.get(Authentication.NAME); + Emailer emailer = AppBeans.get(EmailerAPI.NAME); + + authentication.begin(emailer.getEmailerLogin()); + try { + emailer.sendSendingMessage(sendingMessage); + } finally { + authentication.end(); + } + } catch (Exception e) { + log.error("Exception while sending email: ", e); + } + } + } + + protected static class MessagePersistingContext { + public final List files = new ArrayList<>(); + + public void finished() { + files.clear(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EmailerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/EmailerAPI.java index 95a162eb55..8735336be3 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EmailerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EmailerAPI.java @@ -1,111 +1,111 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.SendingAttachment; -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.EmailAttachment; -import com.haulmont.cuba.core.global.EmailException; -import com.haulmont.cuba.core.global.EmailInfo; - -import javax.annotation.Nullable; -import java.util.Date; -import java.util.List; - -/** - * Provides application with emailing functionality. - *
- * Sending email can be synchronous (caller's thread is blocked until email is delivered to SMTP server) - * or asynchronous (email is persisted in a DB queue and sent later by scheduled task). - *
- * In order to send emails asynchronously, you should register a scheduled task that periodically invokes - * {@link #processQueuedEmails()} method. - */ -public interface EmailerAPI { - - String NAME = "cuba_Emailer"; - - /** - * Send email synchronously. - * - * @param address comma or semicolon separated list of addresses - * @param caption email subject - * @param body email body - * @param attachments email attachments - * @throws EmailException in case of any errors - */ - void sendEmail(String address, String caption, String body, EmailAttachment... attachments) throws EmailException; - - /** - * Send email synchronously. - * - * @param info email details - * @throws EmailException in case of any errors - */ - void sendEmail(EmailInfo info) throws EmailException; - - /** - * Send email asynchronously, with limited number of attempts. - * - * @param info email details - * @param attemptsCount count of attempts to send (1 attempt per scheduler tick). If not specified, - * {@link com.haulmont.cuba.core.app.EmailerConfig#getDefaultSendingAttemptsCount()} is used - * @param deadline Emailer tries to send message till deadline. - * If deadline has come and message has not been sent, status of this message is changed to - * {@link com.haulmont.cuba.core.global.SendingStatus#NOTSENT} - * @return list of created {@link SendingMessage}s - */ - List sendEmailAsync(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline); - - /** - * Send email asynchronously. - *

- * This method creates a list of {@link SendingMessage} instances, saves it to the database and returns immediately. - * The actual sending is performed by the {@link #processQueuedEmails()} method which should be invoked by a - * scheduled task. - * - * @param info email details - * @return list of created {@link SendingMessage}s - */ - List sendEmailAsync(EmailInfo info); - - /** - * Send emails added to the queue. - *

- * This method should be called periodically from a scheduled task. - * - * @return short message describing how many emails were sent, or error message - */ - String processQueuedEmails(); - - /** - * Migrate list of existing messages to be stored in file storage, in a single transaction. - */ - void migrateEmailsToFileStorage(List messages); - - /** - * Migrate list of existing email attachments to be stored in file storage, in a single transaction. - */ - void migrateAttachmentsToFileStorage(List attachments); - - /** - * Loads content text for given message. - * - * @return email content text - */ - String loadContentText(SendingMessage sendingMessage); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.SendingAttachment; +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.EmailAttachment; +import com.haulmont.cuba.core.global.EmailException; +import com.haulmont.cuba.core.global.EmailInfo; + +import javax.annotation.Nullable; +import java.util.Date; +import java.util.List; + +/** + * Provides application with emailing functionality. + *
+ * Sending email can be synchronous (caller's thread is blocked until email is delivered to SMTP server) + * or asynchronous (email is persisted in a DB queue and sent later by scheduled task). + *
+ * In order to send emails asynchronously, you should register a scheduled task that periodically invokes + * {@link #processQueuedEmails()} method. + */ +public interface EmailerAPI { + + String NAME = "cuba_Emailer"; + + /** + * Send email synchronously. + * + * @param address comma or semicolon separated list of addresses + * @param caption email subject + * @param body email body + * @param attachments email attachments + * @throws EmailException in case of any errors + */ + void sendEmail(String address, String caption, String body, EmailAttachment... attachments) throws EmailException; + + /** + * Send email synchronously. + * + * @param info email details + * @throws EmailException in case of any errors + */ + void sendEmail(EmailInfo info) throws EmailException; + + /** + * Send email asynchronously, with limited number of attempts. + * + * @param info email details + * @param attemptsCount count of attempts to send (1 attempt per scheduler tick). If not specified, + * {@link com.haulmont.cuba.core.app.EmailerConfig#getDefaultSendingAttemptsCount()} is used + * @param deadline Emailer tries to send message till deadline. + * If deadline has come and message has not been sent, status of this message is changed to + * {@link com.haulmont.cuba.core.global.SendingStatus#NOTSENT} + * @return list of created {@link SendingMessage}s + */ + List sendEmailAsync(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline); + + /** + * Send email asynchronously. + *

+ * This method creates a list of {@link SendingMessage} instances, saves it to the database and returns immediately. + * The actual sending is performed by the {@link #processQueuedEmails()} method which should be invoked by a + * scheduled task. + * + * @param info email details + * @return list of created {@link SendingMessage}s + */ + List sendEmailAsync(EmailInfo info); + + /** + * Send emails added to the queue. + *

+ * This method should be called periodically from a scheduled task. + * + * @return short message describing how many emails were sent, or error message + */ + String processQueuedEmails(); + + /** + * Migrate list of existing messages to be stored in file storage, in a single transaction. + */ + void migrateEmailsToFileStorage(List messages); + + /** + * Migrate list of existing email attachments to be stored in file storage, in a single transaction. + */ + void migrateAttachmentsToFileStorage(List attachments); + + /** + * Loads content text for given message. + * + * @return email content text + */ + String loadContentText(SendingMessage sendingMessage); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EmailerConfig.java b/modules/core/src/com/haulmont/cuba/core/app/EmailerConfig.java index 9a68b241ce..069ff81e77 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EmailerConfig.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EmailerConfig.java @@ -1,190 +1,190 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.Default; -import com.haulmont.cuba.core.config.defaults.DefaultBoolean; -import com.haulmont.cuba.core.config.defaults.DefaultInt; - -/** - * Configuration parameters interface used for sending emails. - */ -@Source(type = SourceType.DATABASE) -public interface EmailerConfig extends Config { - - /** - * Default "from" address - */ - @Property("cuba.email.fromAddress") - @Default("DoNotReply@localhost") - String getFromAddress(); - - void setFromAddress(String fromAddress); - - /** - * SMTP server address. - */ - @Property("cuba.email.smtpHost") - @Default("test.host") - String getSmtpHost(); - - void setSmtpHost(String smtpHost); - /** - * SMTP server port. - */ - @Property("cuba.email.smtpPort") - @Default("25") - int getSmtpPort(); - - void setSmtpPort(int smtpPort); - - /** - * Whether to authenticate on SMTP server. - */ - @Property("cuba.email.smtpAuthRequired") - @DefaultBoolean(false) - boolean getSmtpAuthRequired(); - - void setSmtpAuthRequired(boolean smtpAuthRequired); - - /** - * Whether to use STARTTLS command during the SMTP server authentication. - */ - @Property("cuba.email.smtpStarttlsEnable") - @DefaultBoolean(false) - boolean getSmtpStarttlsEnable(); - - void setSmtpStarttlsEnable(boolean smtpStarttlsEnable); - - /** - * User name for the SMTP server authentication. - */ - @Property("cuba.email.smtpUser") - String getSmtpUser(); - - void setSmtpUser(String smtpUser); - - /** - * User password for the SMTP server authentication. - */ - @Property("cuba.email.smtpPassword") - String getSmtpPassword(); - - /** - * SMTP connection timeout value in seconds. - */ - @Property("cuba.email.smtpConnectionTimeoutSec") - @DefaultInt(20) - int getSmtpConnectionTimeoutSec(); - - void setSmtpConnectionTimeoutSec(int smtpConnectionTimeoutSec); - - /** - * If set to true, use SSL to connect - * - */ - @Property("cuba.email.smtpSslEnabled") - @DefaultBoolean(false) - boolean getSmtpSslEnabled(); - - void setSmtpSslEnabled(boolean smtpSslEnabled); - - /** - * SMTP I/O timeout value in seconds. - */ - @Property("cuba.email.smtpTimeoutSec") - @DefaultInt(60) - int getSmtpTimeoutSec(); - - void setSmtpTimeoutSec(int smtpTimeoutSec); - - /** - * How many scheduler ticks to skip after server startup. - * Actual sending will start with the next call. - *
This reduces the server load on startup. - */ - @Property("cuba.email.delayCallCount") - @Default("2") - int getDelayCallCount(); - - void setDelayCallCount(int delayCallCount); - - /** - * Scheduler will process no more than given number of queued messages per every scheduler tick. - */ - @Property("cuba.email.messageQueueCapacity") - @Default("100") - int getMessageQueueCapacity(); - - /** - * Max number of attempts to send a message, after which the message's status is set to NOT_SENT. - */ - @Property("cuba.email.defaultSendingAttemptsCount") - @DefaultInt(10) - int getDefaultSendingAttemptsCount(); - - /** - * Timeout in seconds for message in {@link com.haulmont.cuba.core.global.SendingStatus#SENDING} status - * to be successfully sent or failed. After this time passes, emailer will try to resend email again. - */ - @Property("cuba.email.sendingTimeoutSec") - @DefaultInt(240) - int getSendingTimeoutSec(); - - /** - * All emails go to this address if {@link #getSendAllToAdmin()} is enabled, regardless of actual recipient. - */ - @Property("cuba.email.adminAddress") - @Default("admin@localhost") - String getAdminAddress(); - - void setAdminAddress(String adminAddress); - - /** - * If this parameter is set to true, all email messages go to {@link #getAdminAddress()}. - */ - @Property("cuba.email.sendAllToAdmin") - @DefaultBoolean(false) - boolean getSendAllToAdmin(); - - void setSendAllToAdmin(boolean sendAllToAdmin); - - /** - * When turned on, email body text and attachments will be stored in file storage - * instead of BLOB columns in database. - * Should be used if application stores lots of emails and/or email attachments. - * - * @see com.haulmont.cuba.core.entity.SendingMessage#contentTextFile - * @see com.haulmont.cuba.core.entity.SendingAttachment#contentFile - */ - @Property("cuba.email.useFileStorage") - @DefaultBoolean(false) - boolean isFileStorageUsed(); - - void setFileStorageUsed(boolean fileStorageUsed); - - /** - * User login used by asynchronous sending mechanism to be able to store information in the database. - */ - @Property("cuba.emailerUserLogin") - @Default("admin") - String getEmailerUserLogin(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.Default; +import com.haulmont.cuba.core.config.defaults.DefaultBoolean; +import com.haulmont.cuba.core.config.defaults.DefaultInt; + +/** + * Configuration parameters interface used for sending emails. + */ +@Source(type = SourceType.DATABASE) +public interface EmailerConfig extends Config { + + /** + * Default "from" address + */ + @Property("cuba.email.fromAddress") + @Default("DoNotReply@localhost") + String getFromAddress(); + + void setFromAddress(String fromAddress); + + /** + * SMTP server address. + */ + @Property("cuba.email.smtpHost") + @Default("test.host") + String getSmtpHost(); + + void setSmtpHost(String smtpHost); + /** + * SMTP server port. + */ + @Property("cuba.email.smtpPort") + @Default("25") + int getSmtpPort(); + + void setSmtpPort(int smtpPort); + + /** + * Whether to authenticate on SMTP server. + */ + @Property("cuba.email.smtpAuthRequired") + @DefaultBoolean(false) + boolean getSmtpAuthRequired(); + + void setSmtpAuthRequired(boolean smtpAuthRequired); + + /** + * Whether to use STARTTLS command during the SMTP server authentication. + */ + @Property("cuba.email.smtpStarttlsEnable") + @DefaultBoolean(false) + boolean getSmtpStarttlsEnable(); + + void setSmtpStarttlsEnable(boolean smtpStarttlsEnable); + + /** + * User name for the SMTP server authentication. + */ + @Property("cuba.email.smtpUser") + String getSmtpUser(); + + void setSmtpUser(String smtpUser); + + /** + * User password for the SMTP server authentication. + */ + @Property("cuba.email.smtpPassword") + String getSmtpPassword(); + + /** + * SMTP connection timeout value in seconds. + */ + @Property("cuba.email.smtpConnectionTimeoutSec") + @DefaultInt(20) + int getSmtpConnectionTimeoutSec(); + + void setSmtpConnectionTimeoutSec(int smtpConnectionTimeoutSec); + + /** + * If set to true, use SSL to connect + * + */ + @Property("cuba.email.smtpSslEnabled") + @DefaultBoolean(false) + boolean getSmtpSslEnabled(); + + void setSmtpSslEnabled(boolean smtpSslEnabled); + + /** + * SMTP I/O timeout value in seconds. + */ + @Property("cuba.email.smtpTimeoutSec") + @DefaultInt(60) + int getSmtpTimeoutSec(); + + void setSmtpTimeoutSec(int smtpTimeoutSec); + + /** + * How many scheduler ticks to skip after server startup. + * Actual sending will start with the next call. + *
This reduces the server load on startup. + */ + @Property("cuba.email.delayCallCount") + @Default("2") + int getDelayCallCount(); + + void setDelayCallCount(int delayCallCount); + + /** + * Scheduler will process no more than given number of queued messages per every scheduler tick. + */ + @Property("cuba.email.messageQueueCapacity") + @Default("100") + int getMessageQueueCapacity(); + + /** + * Max number of attempts to send a message, after which the message's status is set to NOT_SENT. + */ + @Property("cuba.email.defaultSendingAttemptsCount") + @DefaultInt(10) + int getDefaultSendingAttemptsCount(); + + /** + * Timeout in seconds for message in {@link com.haulmont.cuba.core.global.SendingStatus#SENDING} status + * to be successfully sent or failed. After this time passes, emailer will try to resend email again. + */ + @Property("cuba.email.sendingTimeoutSec") + @DefaultInt(240) + int getSendingTimeoutSec(); + + /** + * All emails go to this address if {@link #getSendAllToAdmin()} is enabled, regardless of actual recipient. + */ + @Property("cuba.email.adminAddress") + @Default("admin@localhost") + String getAdminAddress(); + + void setAdminAddress(String adminAddress); + + /** + * If this parameter is set to true, all email messages go to {@link #getAdminAddress()}. + */ + @Property("cuba.email.sendAllToAdmin") + @DefaultBoolean(false) + boolean getSendAllToAdmin(); + + void setSendAllToAdmin(boolean sendAllToAdmin); + + /** + * When turned on, email body text and attachments will be stored in file storage + * instead of BLOB columns in database. + * Should be used if application stores lots of emails and/or email attachments. + * + * @see com.haulmont.cuba.core.entity.SendingMessage#contentTextFile + * @see com.haulmont.cuba.core.entity.SendingAttachment#contentFile + */ + @Property("cuba.email.useFileStorage") + @DefaultBoolean(false) + boolean isFileStorageUsed(); + + void setFileStorageUsed(boolean fileStorageUsed); + + /** + * User login used by asynchronous sending mechanism to be able to store information in the database. + */ + @Property("cuba.emailerUserLogin") + @Default("admin") + String getEmailerUserLogin(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EntityDiffManager.java b/modules/core/src/com/haulmont/cuba/core/app/EntityDiffManager.java index ad587b6113..a027b144e5 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EntityDiffManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EntityDiffManager.java @@ -1,356 +1,356 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.Range; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.EmbeddableEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.ViewHelper; -import org.apache.commons.lang.ObjectUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.*; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Diff algorithm for Entities. - * - */ -@Component("cuba_EntityDiffManager") -public class EntityDiffManager { - - @Inject - private EntitySnapshotAPI snapshotAPI; - - @Inject - private MetadataTools metadataTools; - - @Inject - private ExtendedEntities extendedEntities; - - @Inject - private Metadata metadata; - - private Logger log = LoggerFactory.getLogger(EntityDiffManager.class); - - public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { - - // Sort snapshots by date, first - old, second - new - long firstTime = 0; - if (first != null && first.getSnapshotDate() != null) - firstTime = first.getSnapshotDate().getTime(); - - long secondTime = 0; - if (second != null && second.getSnapshotDate() != null) - secondTime = second.getSnapshotDate().getTime(); - - if (secondTime < firstTime) { - EntitySnapshot temp = first; - first = second; - second = temp; - } - - checkNotNull(second, "Diff could not be create for null snapshot"); - - // Extract views - View firstView = first != null ? snapshotAPI.extractView(first) : null; - View secondView = snapshotAPI.extractView(second); - - // Get view for diff - View diffView; - if (firstView != null) - diffView = ViewHelper.intersectViews(firstView, secondView); - else - diffView = secondView; - - // Diff - return getDifferenceByView(first, second, diffView); - } - - private EntityDiff getDifferenceByView(EntitySnapshot first, EntitySnapshot second, View diffView) { - EntityDiff result = new EntityDiff(diffView); - result.setBeforeSnapshot(first); - result.setAfterSnapshot(second); - - if (!diffView.getProperties().isEmpty()) { - Entity firstEntity = first != null ? snapshotAPI.extractEntity(first) : null; - Entity secondEntity = snapshotAPI.extractEntity(second); - - result.setBeforeEntity(firstEntity); - result.setAfterEntity(secondEntity); - - Stack diffBranch = new Stack<>(); - diffBranch.push(second); - - List propertyDiffs = getPropertyDiffs(diffView, firstEntity, secondEntity, diffBranch); - result.setPropertyDiffs(propertyDiffs); - } - return result; - } - - /** - * Get diffs for entity properties - * - * @param diffView View - * @param firstEntity First entity - * @param secondEntity Second entity - * @param diffBranch Diff branch - * @return Diff list - */ - private List getPropertyDiffs(View diffView, Entity firstEntity, Entity secondEntity, - Stack diffBranch) { - List propertyDiffs = new LinkedList<>(); - - MetaClass viewMetaClass = metadata.getSession().getClass(diffView.getEntityClass()); - MetaClass metaClass = extendedEntities.getEffectiveMetaClass(viewMetaClass); - - Collection metaProperties = metadataTools.getViewPropertyPaths(diffView, metaClass); - - for (MetaPropertyPath metaPropertyPath : metaProperties) { - MetaProperty metaProperty = metaPropertyPath.getMetaProperty(); - - if (!metadataTools.isNotPersistent(metaProperty) && !metadataTools.isSystem(metaProperty)) { - ViewProperty viewProperty = diffView.getProperty(metaProperty.getName()); - - Object firstValue = firstEntity != null ? getPropertyValue(firstEntity, metaPropertyPath) : null; - Object secondValue = secondEntity != null ? getPropertyValue(secondEntity, metaPropertyPath) : null; - - EntityPropertyDiff diff = getPropertyDifference(firstValue, secondValue, metaProperty, viewProperty, diffBranch); - if (diff != null) - propertyDiffs.add(diff); - } - } - - Comparator comparator = new Comparator() { - @Override - public int compare(EntityPropertyDiff o1, EntityPropertyDiff o2) { - return o1.getName().compareTo(o2.getName()); - } - }; - Collections.sort(propertyDiffs, comparator); - - return propertyDiffs; - } - - /** - * Return difference between property values - * - * @param firstValue First value - * @param secondValue Second value - * @param metaProperty Meta Property - * @param viewProperty View property - * @param diffBranch Branch with passed diffs - * @return Diff - */ - private EntityPropertyDiff getPropertyDifference(Object firstValue, Object secondValue, - MetaProperty metaProperty, ViewProperty viewProperty, - Stack diffBranch) { - EntityPropertyDiff propertyDiff = null; - - Range range = metaProperty.getRange(); - if (range.isDatatype() || range.isEnum()) { - // datatype - if (!ObjectUtils.equals(firstValue, secondValue)) - propertyDiff = new EntityBasicPropertyDiff(viewProperty, metaProperty, firstValue, secondValue); - - } else if (range.getCardinality().isMany()) { - propertyDiff = getCollectionDiff(firstValue, secondValue, viewProperty, metaProperty, diffBranch); - - } else if (range.isClass()) { - propertyDiff = getClassDiff(firstValue, secondValue, viewProperty, metaProperty, diffBranch); - } - - return propertyDiff; - } - - private EntityPropertyDiff getClassDiff(@Nullable Object firstValue, @Nullable Object secondValue, - ViewProperty viewProperty, MetaProperty metaProperty, - Stack diffBranch) { - EntityPropertyDiff propertyDiff = null; - if (viewProperty.getView() != null) { - // check exist value in diff branch - if (!diffBranch.contains(secondValue)) { - - if (secondValue != null) { - // added or modified - propertyDiff = generateClassDiffFor(secondValue, firstValue, secondValue, - viewProperty, metaProperty, diffBranch); - } else { - if (firstValue != null) { - // removed or set null - propertyDiff = generateClassDiffFor(firstValue, firstValue, null /*secondValue*/, - viewProperty, metaProperty, diffBranch); - } - } - } - } else { - if ((firstValue != null) || (secondValue != null)) - log.debug("Not null values for (null) view ignored, property: " + metaProperty.getName() + - "in class" + metaProperty.getDeclaringClass().getCanonicalName()); - } - return propertyDiff; - } - - /** - * Generate class difference for selected not null object - * - * @param diffObject Object - * @param firstValue First value - * @param secondValue Second value - * @param viewProperty View property - * @param metaProperty Meta property - * @param diffBranch Diff branch - * @return Property difference - */ - private EntityPropertyDiff generateClassDiffFor(Object diffObject, - @Nullable Object firstValue, @Nullable Object secondValue, - ViewProperty viewProperty, MetaProperty metaProperty, - Stack diffBranch) { - // link - boolean isLinkChange = !ObjectUtils.equals(firstValue, secondValue); - isLinkChange = !(diffObject instanceof EmbeddableEntity) && isLinkChange; - - EntityClassPropertyDiff classPropertyDiff = new EntityClassPropertyDiff(firstValue, secondValue, - viewProperty, metaProperty, isLinkChange); - - boolean isInternalChange = false; - diffBranch.push(diffObject); - - List propertyDiffs = - getPropertyDiffs(viewProperty.getView(), (Entity) firstValue, (Entity) secondValue, diffBranch); - - diffBranch.pop(); - - if (!propertyDiffs.isEmpty()) { - isInternalChange = true; - classPropertyDiff.setPropertyDiffs(propertyDiffs); - } - - if (isInternalChange || isLinkChange) - return classPropertyDiff; - else - return null; - } - - private EntityPropertyDiff getCollectionDiff(Object firstValue, Object secondValue, - ViewProperty viewProperty, MetaProperty metaProperty, - Stack diffBranch) { - EntityPropertyDiff propertyDiff = null; - - Collection addedEntities = new LinkedList<>(); - Collection removedEntities = new LinkedList<>(); - Collection> modifiedEntities = new LinkedList<>(); - - // collection - Collection firstCollection = getCollection(firstValue); - Collection secondCollection = getCollection(secondValue); - - // added or modified - for (Object item : secondCollection) { - Entity secondEntity = (Entity) item; - Entity firstEntity = getRelatedItem(firstCollection, secondEntity); - if (firstEntity == null) - addedEntities.add(secondEntity); - else - modifiedEntities.add(new Pair(firstEntity, secondEntity)); - } - - // removed - for (Object item : firstCollection) { - Entity firstEntity = (Entity) item; - Entity secondEntity = getRelatedItem(secondCollection, firstEntity); - if (secondEntity == null) - removedEntities.add(firstEntity); - } - - boolean changed = !(addedEntities.isEmpty() && removedEntities.isEmpty() && modifiedEntities.isEmpty()); - if (changed) { - EntityCollectionPropertyDiff diff = new EntityCollectionPropertyDiff(viewProperty, metaProperty); - - for (Entity entity : addedEntities) { - EntityPropertyDiff addedDiff = getClassDiff(null, entity, viewProperty, metaProperty, diffBranch); - if (addedDiff != null) { - addedDiff.setName(InstanceUtils.getInstanceName(entity)); - addedDiff.setItemState(EntityPropertyDiff.ItemState.Added); - diff.getAddedEntities().add(addedDiff); - } - } - // check modified - for (Pair entityPair : modifiedEntities) { - EntityPropertyDiff modifiedDiff = getClassDiff(entityPair.getFirst(), entityPair.getSecond(), - viewProperty, metaProperty, diffBranch); - if (modifiedDiff != null) { - modifiedDiff.setName(InstanceUtils.getInstanceName(entityPair.getSecond())); - modifiedDiff.setItemState(EntityPropertyDiff.ItemState.Modified); - diff.getModifiedEntities().add(modifiedDiff); - } - } - // check removed - for (Entity entity : removedEntities) { - EntityPropertyDiff removedDiff = getClassDiff(entity, null, viewProperty, metaProperty, diffBranch); - if (removedDiff != null) { - removedDiff.setName(InstanceUtils.getInstanceName(entity)); - removedDiff.setItemState(EntityPropertyDiff.ItemState.Removed); - diff.getRemovedEntities().add(removedDiff); - } - } - - boolean empty = diff.getAddedEntities().isEmpty() - && diff.getModifiedEntities().isEmpty() - && diff.getRemovedEntities().isEmpty(); - if (!empty) - propertyDiff = diff; - } - return propertyDiff; - } - - private Entity getRelatedItem(Collection collection, Entity entity) { - for (Object item : collection) { - Entity itemEntity = (Entity) item; - if (entity.getId().equals(itemEntity.getId())) - return itemEntity; - } - return null; - } - - private Collection getCollection(Object value) { - Collection collection; - if (value == null) - collection = Collections.emptyList(); - else - collection = (Collection) value; - return collection; - } - - private Object getPropertyValue(Entity entity, MetaPropertyPath propertyPath) { - return entity.getValue(propertyPath.toString()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.Range; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.EmbeddableEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.ViewHelper; +import org.apache.commons.lang.ObjectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.*; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Diff algorithm for Entities. + * + */ +@Component("cuba_EntityDiffManager") +public class EntityDiffManager { + + @Inject + private EntitySnapshotAPI snapshotAPI; + + @Inject + private MetadataTools metadataTools; + + @Inject + private ExtendedEntities extendedEntities; + + @Inject + private Metadata metadata; + + private Logger log = LoggerFactory.getLogger(EntityDiffManager.class); + + public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { + + // Sort snapshots by date, first - old, second - new + long firstTime = 0; + if (first != null && first.getSnapshotDate() != null) + firstTime = first.getSnapshotDate().getTime(); + + long secondTime = 0; + if (second != null && second.getSnapshotDate() != null) + secondTime = second.getSnapshotDate().getTime(); + + if (secondTime < firstTime) { + EntitySnapshot temp = first; + first = second; + second = temp; + } + + checkNotNull(second, "Diff could not be create for null snapshot"); + + // Extract views + View firstView = first != null ? snapshotAPI.extractView(first) : null; + View secondView = snapshotAPI.extractView(second); + + // Get view for diff + View diffView; + if (firstView != null) + diffView = ViewHelper.intersectViews(firstView, secondView); + else + diffView = secondView; + + // Diff + return getDifferenceByView(first, second, diffView); + } + + private EntityDiff getDifferenceByView(EntitySnapshot first, EntitySnapshot second, View diffView) { + EntityDiff result = new EntityDiff(diffView); + result.setBeforeSnapshot(first); + result.setAfterSnapshot(second); + + if (!diffView.getProperties().isEmpty()) { + Entity firstEntity = first != null ? snapshotAPI.extractEntity(first) : null; + Entity secondEntity = snapshotAPI.extractEntity(second); + + result.setBeforeEntity(firstEntity); + result.setAfterEntity(secondEntity); + + Stack diffBranch = new Stack<>(); + diffBranch.push(second); + + List propertyDiffs = getPropertyDiffs(diffView, firstEntity, secondEntity, diffBranch); + result.setPropertyDiffs(propertyDiffs); + } + return result; + } + + /** + * Get diffs for entity properties + * + * @param diffView View + * @param firstEntity First entity + * @param secondEntity Second entity + * @param diffBranch Diff branch + * @return Diff list + */ + private List getPropertyDiffs(View diffView, Entity firstEntity, Entity secondEntity, + Stack diffBranch) { + List propertyDiffs = new LinkedList<>(); + + MetaClass viewMetaClass = metadata.getSession().getClass(diffView.getEntityClass()); + MetaClass metaClass = extendedEntities.getEffectiveMetaClass(viewMetaClass); + + Collection metaProperties = metadataTools.getViewPropertyPaths(diffView, metaClass); + + for (MetaPropertyPath metaPropertyPath : metaProperties) { + MetaProperty metaProperty = metaPropertyPath.getMetaProperty(); + + if (!metadataTools.isNotPersistent(metaProperty) && !metadataTools.isSystem(metaProperty)) { + ViewProperty viewProperty = diffView.getProperty(metaProperty.getName()); + + Object firstValue = firstEntity != null ? getPropertyValue(firstEntity, metaPropertyPath) : null; + Object secondValue = secondEntity != null ? getPropertyValue(secondEntity, metaPropertyPath) : null; + + EntityPropertyDiff diff = getPropertyDifference(firstValue, secondValue, metaProperty, viewProperty, diffBranch); + if (diff != null) + propertyDiffs.add(diff); + } + } + + Comparator comparator = new Comparator() { + @Override + public int compare(EntityPropertyDiff o1, EntityPropertyDiff o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + Collections.sort(propertyDiffs, comparator); + + return propertyDiffs; + } + + /** + * Return difference between property values + * + * @param firstValue First value + * @param secondValue Second value + * @param metaProperty Meta Property + * @param viewProperty View property + * @param diffBranch Branch with passed diffs + * @return Diff + */ + private EntityPropertyDiff getPropertyDifference(Object firstValue, Object secondValue, + MetaProperty metaProperty, ViewProperty viewProperty, + Stack diffBranch) { + EntityPropertyDiff propertyDiff = null; + + Range range = metaProperty.getRange(); + if (range.isDatatype() || range.isEnum()) { + // datatype + if (!ObjectUtils.equals(firstValue, secondValue)) + propertyDiff = new EntityBasicPropertyDiff(viewProperty, metaProperty, firstValue, secondValue); + + } else if (range.getCardinality().isMany()) { + propertyDiff = getCollectionDiff(firstValue, secondValue, viewProperty, metaProperty, diffBranch); + + } else if (range.isClass()) { + propertyDiff = getClassDiff(firstValue, secondValue, viewProperty, metaProperty, diffBranch); + } + + return propertyDiff; + } + + private EntityPropertyDiff getClassDiff(@Nullable Object firstValue, @Nullable Object secondValue, + ViewProperty viewProperty, MetaProperty metaProperty, + Stack diffBranch) { + EntityPropertyDiff propertyDiff = null; + if (viewProperty.getView() != null) { + // check exist value in diff branch + if (!diffBranch.contains(secondValue)) { + + if (secondValue != null) { + // added or modified + propertyDiff = generateClassDiffFor(secondValue, firstValue, secondValue, + viewProperty, metaProperty, diffBranch); + } else { + if (firstValue != null) { + // removed or set null + propertyDiff = generateClassDiffFor(firstValue, firstValue, null /*secondValue*/, + viewProperty, metaProperty, diffBranch); + } + } + } + } else { + if ((firstValue != null) || (secondValue != null)) + log.debug("Not null values for (null) view ignored, property: " + metaProperty.getName() + + "in class" + metaProperty.getDeclaringClass().getCanonicalName()); + } + return propertyDiff; + } + + /** + * Generate class difference for selected not null object + * + * @param diffObject Object + * @param firstValue First value + * @param secondValue Second value + * @param viewProperty View property + * @param metaProperty Meta property + * @param diffBranch Diff branch + * @return Property difference + */ + private EntityPropertyDiff generateClassDiffFor(Object diffObject, + @Nullable Object firstValue, @Nullable Object secondValue, + ViewProperty viewProperty, MetaProperty metaProperty, + Stack diffBranch) { + // link + boolean isLinkChange = !ObjectUtils.equals(firstValue, secondValue); + isLinkChange = !(diffObject instanceof EmbeddableEntity) && isLinkChange; + + EntityClassPropertyDiff classPropertyDiff = new EntityClassPropertyDiff(firstValue, secondValue, + viewProperty, metaProperty, isLinkChange); + + boolean isInternalChange = false; + diffBranch.push(diffObject); + + List propertyDiffs = + getPropertyDiffs(viewProperty.getView(), (Entity) firstValue, (Entity) secondValue, diffBranch); + + diffBranch.pop(); + + if (!propertyDiffs.isEmpty()) { + isInternalChange = true; + classPropertyDiff.setPropertyDiffs(propertyDiffs); + } + + if (isInternalChange || isLinkChange) + return classPropertyDiff; + else + return null; + } + + private EntityPropertyDiff getCollectionDiff(Object firstValue, Object secondValue, + ViewProperty viewProperty, MetaProperty metaProperty, + Stack diffBranch) { + EntityPropertyDiff propertyDiff = null; + + Collection addedEntities = new LinkedList<>(); + Collection removedEntities = new LinkedList<>(); + Collection> modifiedEntities = new LinkedList<>(); + + // collection + Collection firstCollection = getCollection(firstValue); + Collection secondCollection = getCollection(secondValue); + + // added or modified + for (Object item : secondCollection) { + Entity secondEntity = (Entity) item; + Entity firstEntity = getRelatedItem(firstCollection, secondEntity); + if (firstEntity == null) + addedEntities.add(secondEntity); + else + modifiedEntities.add(new Pair(firstEntity, secondEntity)); + } + + // removed + for (Object item : firstCollection) { + Entity firstEntity = (Entity) item; + Entity secondEntity = getRelatedItem(secondCollection, firstEntity); + if (secondEntity == null) + removedEntities.add(firstEntity); + } + + boolean changed = !(addedEntities.isEmpty() && removedEntities.isEmpty() && modifiedEntities.isEmpty()); + if (changed) { + EntityCollectionPropertyDiff diff = new EntityCollectionPropertyDiff(viewProperty, metaProperty); + + for (Entity entity : addedEntities) { + EntityPropertyDiff addedDiff = getClassDiff(null, entity, viewProperty, metaProperty, diffBranch); + if (addedDiff != null) { + addedDiff.setName(InstanceUtils.getInstanceName(entity)); + addedDiff.setItemState(EntityPropertyDiff.ItemState.Added); + diff.getAddedEntities().add(addedDiff); + } + } + // check modified + for (Pair entityPair : modifiedEntities) { + EntityPropertyDiff modifiedDiff = getClassDiff(entityPair.getFirst(), entityPair.getSecond(), + viewProperty, metaProperty, diffBranch); + if (modifiedDiff != null) { + modifiedDiff.setName(InstanceUtils.getInstanceName(entityPair.getSecond())); + modifiedDiff.setItemState(EntityPropertyDiff.ItemState.Modified); + diff.getModifiedEntities().add(modifiedDiff); + } + } + // check removed + for (Entity entity : removedEntities) { + EntityPropertyDiff removedDiff = getClassDiff(entity, null, viewProperty, metaProperty, diffBranch); + if (removedDiff != null) { + removedDiff.setName(InstanceUtils.getInstanceName(entity)); + removedDiff.setItemState(EntityPropertyDiff.ItemState.Removed); + diff.getRemovedEntities().add(removedDiff); + } + } + + boolean empty = diff.getAddedEntities().isEmpty() + && diff.getModifiedEntities().isEmpty() + && diff.getRemovedEntities().isEmpty(); + if (!empty) + propertyDiff = diff; + } + return propertyDiff; + } + + private Entity getRelatedItem(Collection collection, Entity entity) { + for (Object item : collection) { + Entity itemEntity = (Entity) item; + if (entity.getId().equals(itemEntity.getId())) + return itemEntity; + } + return null; + } + + private Collection getCollection(Object value) { + Collection collection; + if (value == null) + collection = Collections.emptyList(); + else + collection = (Collection) value; + return collection; + } + + private Object getPropertyValue(Entity entity, MetaPropertyPath propertyPath) { + return entity.getValue(propertyPath.toString()); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EntityLogServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/EntityLogServiceBean.java index 09bea8d691..f429bd8913 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EntityLogServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EntityLogServiceBean.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.security.app.EntityLogAPI; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; - -@Service(EntityLogService.NAME) -public class EntityLogServiceBean implements EntityLogService { - - @Inject - private EntityLogAPI entityLogAPI; - - @Override - public boolean isEnabled() { - return entityLogAPI.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - entityLogAPI.setEnabled(enabled); - } - - @Override - public void invalidateCache() { - entityLogAPI.invalidateCache(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.security.app.EntityLogAPI; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; + +@Service(EntityLogService.NAME) +public class EntityLogServiceBean implements EntityLogService { + + @Inject + private EntityLogAPI entityLogAPI; + + @Override + public boolean isEnabled() { + return entityLogAPI.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + entityLogAPI.setEnabled(enabled); + } + + @Override + public void invalidateCache() { + entityLogAPI.invalidateCache(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotAPI.java b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotAPI.java index bbc1290135..0fb5bffda9 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotAPI.java @@ -1,112 +1,112 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.User; - -import javax.annotation.Nullable; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * Creates and analyzes entity snapshots. - */ -public interface EntitySnapshotAPI { - - String NAME = "cuba_EntitySnapshotManager"; - - /** - * Load snapshots for entity - * - * @param metaClass Entity metaclass - * @param id Entity Id - * @return Snapshot list sorted by snapshotDate desc - */ - List getSnapshots(MetaClass metaClass, Object id); - - /** - * Translate snapshots for archival classes - * - * @param metaClass Metaclass - * @param id Entity Id - * @param classMapping Map of [OldClass -> NewClass] for migration - */ - void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping); - - /** - * Create snapshot for Entity and store it to database - * - * @param entity Entity - * @param view View - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view); - - /** - * Create snapshot for Entity with specific date and store it to database - * - * @param entity Entity - * @param view View - * @param snapshotDate Date - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate); - - /** - * Create snapshot for Entity with specific date and author and store it to database - * - * @param entity Entity - * @param view View - * @param snapshotDate Date - * @param author Author - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author); - - /** - * Restore entity by snapshot - * - * @param snapshot Snapshot - * @return Entity instance - */ - Entity extractEntity(EntitySnapshot snapshot); - - /** - * Restore view from snapshot - * - * @param snapshot Snapshot - * @return View instance - */ - View extractView(EntitySnapshot snapshot); - - /** - * Diff two versions of entity - * - * @param first First version - * @param second Second version - * @return Diffs - */ - EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.User; + +import javax.annotation.Nullable; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Creates and analyzes entity snapshots. + */ +public interface EntitySnapshotAPI { + + String NAME = "cuba_EntitySnapshotManager"; + + /** + * Load snapshots for entity + * + * @param metaClass Entity metaclass + * @param id Entity Id + * @return Snapshot list sorted by snapshotDate desc + */ + List getSnapshots(MetaClass metaClass, Object id); + + /** + * Translate snapshots for archival classes + * + * @param metaClass Metaclass + * @param id Entity Id + * @param classMapping Map of [OldClass -> NewClass] for migration + */ + void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping); + + /** + * Create snapshot for Entity and store it to database + * + * @param entity Entity + * @param view View + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view); + + /** + * Create snapshot for Entity with specific date and store it to database + * + * @param entity Entity + * @param view View + * @param snapshotDate Date + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate); + + /** + * Create snapshot for Entity with specific date and author and store it to database + * + * @param entity Entity + * @param view View + * @param snapshotDate Date + * @param author Author + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author); + + /** + * Restore entity by snapshot + * + * @param snapshot Snapshot + * @return Entity instance + */ + Entity extractEntity(EntitySnapshot snapshot); + + /** + * Restore view from snapshot + * + * @param snapshot Snapshot + * @return View instance + */ + View extractView(EntitySnapshot snapshot); + + /** + * Diff two versions of entity + * + * @param first First version + * @param second Second version + * @return Diffs + */ + EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotManager.java b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotManager.java index 3dddb26a36..268a3fe1fc 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotManager.java @@ -1,340 +1,340 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.app.serialization.EntitySerializationAPI; -import com.haulmont.cuba.core.app.serialization.ViewSerializationAPI; -import com.haulmont.cuba.core.app.serialization.ViewSerializationOption; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.User; -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; -import com.thoughtworks.xstream.mapper.MapperWrapper; -import org.dom4j.*; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.*; - -import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; - -@Component(EntitySnapshotAPI.NAME) -public class EntitySnapshotManager implements EntitySnapshotAPI { - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected EntityDiffManager diffManager; - - @Inject - protected ExtendedEntities extendedEntities; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected TimeSource timeSource; - - @Inject - protected EntitySerializationAPI entitySerializationAPI; - - @Inject - protected ViewSerializationAPI viewSerializationAPI; - - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - - @Inject - protected DataManager dataManager; - - @Override - public List getSnapshots(MetaClass metaClass, Object id) { - metaClass = extendedEntities.getOriginalOrThisMetaClass(metaClass); - Entity entity = dataManager.load(new LoadContext<>(metaClass).setId(id).setView(View.LOCAL)); - checkCompositePrimaryKey(entity); - List resultList = null; - View view = metadata.getViewRepository().getView(EntitySnapshot.class, "entitySnapshot.browse"); - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - TypedQuery query = em.createQuery(format( - "select s from sys$EntitySnapshot s where s.entity.%s = :entityId and s.entityMetaClass = :metaClass " + - "order by s.snapshotDate desc", referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), EntitySnapshot.class); - query.setParameter("entityId", referenceToEntitySupport.getReferenceId(entity)); - query.setParameter("metaClass", metaClass.getName()); - query.setView(view); - resultList = query.getResultList(); - - tx.commit(); - } finally { - tx.end(); - } - - return resultList; - } - - @Override - public void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping) { - metaClass = extendedEntities.getOriginalOrThisMetaClass(metaClass); - // load snapshots - List snapshotList = getSnapshots(metaClass, id); - Class javaClass = metaClass.getJavaClass(); - - MetaClass mappedMetaClass = null; - if (classMapping.containsKey(javaClass)) { - Class mappedClass = classMapping.get(javaClass); - mappedMetaClass = extendedEntities.getOriginalOrThisMetaClass(metadata.getClass(mappedClass)); - } - - for (EntitySnapshot snapshot : snapshotList) { - if (mappedMetaClass != null) { - snapshot.setEntityMetaClass(mappedMetaClass.getName()); - } - - String snapshotXml = snapshot.getSnapshotXml(); - String viewXml = snapshot.getViewXml(); - - snapshot.setSnapshotXml(processSnapshotXml(snapshotXml, classMapping)); - snapshot.setViewXml(processViewXml(viewXml, classMapping)); - } - - // Save snapshots to db - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - for (EntitySnapshot snapshot : snapshotList) { - em.merge(snapshot); - } - - tx.commit(); - } finally { - tx.end(); - } - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view) { - return createSnapshot(entity, view, timeSource.currentTimestamp()); - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) { - User user = userSessionSource.getUserSession().getUser(); - return createSnapshot(entity, view, snapshotDate, user); - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) { - Preconditions.checkNotNullArgument(entity); - Preconditions.checkNotNullArgument(view); - Preconditions.checkNotNullArgument(snapshotDate); - - checkCompositePrimaryKey(entity); - - Class viewEntityClass = view.getEntityClass(); - Class entityClass = entity.getClass(); - - if (!viewEntityClass.isAssignableFrom(entityClass)) { - throw new IllegalStateException("View could not be used with this propertyValue"); - } - - MetaClass metaClass = extendedEntities.getOriginalOrThisMetaClass(metadata.getClass(entity.getClass())); - - EntitySnapshot snapshot = metadata.create(EntitySnapshot.class); - snapshot.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); - snapshot.setEntityMetaClass(metaClass.getName()); - snapshot.setViewXml(viewSerializationAPI.toJson(view, ViewSerializationOption.COMPACT_FORMAT)); - snapshot.setSnapshotXml(entitySerializationAPI.toJson(entity)); - snapshot.setSnapshotDate(snapshotDate); - snapshot.setAuthor(author); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - em.persist(snapshot); - - tx.commit(); - } finally { - tx.end(); - } - - return snapshot; - } - - @Override - public Entity extractEntity(EntitySnapshot snapshot) { - String rawResult = snapshot.getSnapshotXml(); - BaseGenericIdEntity entity; - if (isXml(rawResult)) { - entity = (BaseGenericIdEntity) fromXML(snapshot.getSnapshotXml()); - } else { - entity = entitySerializationAPI.entityFromJson(rawResult, metadata.getClass(snapshot.getEntityMetaClass())); - } - return entity; - } - - @Override - public View extractView(EntitySnapshot snapshot) { - String rawResult = snapshot.getViewXml(); - View view; - if (isXml(rawResult)) { - view = (View) fromXML(rawResult); - } else { - view = viewSerializationAPI.fromJson(rawResult); - } - return view; - } - - @Override - public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { - return diffManager.getDifference(first, second); - } - - protected Object fromXML(String xml) { - final List exclUpdateFields = Arrays.asList("updateTs", "updatedBy"); - XStream xStream = new XStream() { - @Override - protected MapperWrapper wrapMapper(MapperWrapper next) { - return new MapperWrapper(next) { - @Override - public boolean shouldSerializeMember(Class definedIn, String fieldName) { - boolean result = super.shouldSerializeMember(definedIn, fieldName); - if (!result) { - return false; - } - if (fieldName != null) { - if (exclUpdateFields.contains(fieldName) - && Updatable.class.isAssignableFrom(definedIn)) { - return false; - } - if ("uuid".equals(fieldName)) { - if (!HasUuid.class.isAssignableFrom(definedIn) - && BaseGenericIdEntity.class.isAssignableFrom(definedIn)) { - return false; - } - } - } - return true; - } - }; - } - }; - xStream.getConverterRegistry().removeConverter(ExternalizableConverter.class); - xStream.omitField(BaseGenericIdEntity.class, "createTs"); - xStream.omitField(BaseGenericIdEntity.class, "createdBy"); - - return xStream.fromXML(xml); - } - - protected boolean isXml(String value) { - return value != null && value.trim().startsWith("<"); - } - - protected void checkCompositePrimaryKey(Entity entity) { - if (metadata.getTools().hasCompositePrimaryKey(entity.getMetaClass()) && !(entity instanceof HasUuid)) { - throw new UnsupportedOperationException(format("Entity %s has no persistent UUID attribute", entity)); - } - } - - protected void replaceInXmlTree(Element element, Map classMapping) { - for (int i = 0; i < element.nodeCount(); i++) { - Node node = element.node(i); - if (node instanceof Element) { - Element childElement = (Element) node; - replaceClasses(childElement, classMapping); - replaceInXmlTree(childElement, classMapping); - } - } - } - - protected void replaceClasses(Element element, Map classMapping) { - // translate XML - for (Map.Entry classEntry : classMapping.entrySet()) { - Class beforeClass = classEntry.getKey(); - Class afterClass = classEntry.getValue(); - - checkNotNull(beforeClass); - checkNotNull(afterClass); - - // If BeforeClass != AfterClass - if (!beforeClass.equals(afterClass)) { - String beforeClassName = beforeClass.getCanonicalName(); - String afterClassName = afterClass.getCanonicalName(); - - if (beforeClassName.equals(element.getName())) { - element.setName(afterClassName); - } - - Attribute classAttribute = element.attribute("class"); - if ((classAttribute != null) && beforeClassName.equals(classAttribute.getValue())) { - classAttribute.setValue(afterClassName); - } - } - } - } - - protected String processViewXml(String viewXml, Map classMapping) { - if (!isXml(viewXml)) { - return viewXml; - } - for (Map.Entry classEntry : classMapping.entrySet()) { - Class beforeClass = classEntry.getKey(); - Class afterClass = classEntry.getValue(); - - checkNotNull(beforeClass); - checkNotNull(afterClass); - - String beforeClassName = beforeClass.getCanonicalName(); - String afterClassName = afterClass.getCanonicalName(); - - viewXml = viewXml.replaceAll(beforeClassName, afterClassName); - } - return viewXml; - } - - protected String processSnapshotXml(String snapshotXml, Map classMapping) { - if (!isXml(snapshotXml)) { - return snapshotXml; - } - Document document; - try { - document = DocumentHelper.parseText(snapshotXml); - } catch (DocumentException e) { - throw new RuntimeException("Couldn't parse snapshot xml content", e); - } - replaceClasses(document.getRootElement(), classMapping); - replaceInXmlTree(document.getRootElement(), classMapping); - return document.asXML(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.app.serialization.EntitySerializationAPI; +import com.haulmont.cuba.core.app.serialization.ViewSerializationAPI; +import com.haulmont.cuba.core.app.serialization.ViewSerializationOption; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.User; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; +import com.thoughtworks.xstream.mapper.MapperWrapper; +import org.dom4j.*; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.*; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; + +@Component(EntitySnapshotAPI.NAME) +public class EntitySnapshotManager implements EntitySnapshotAPI { + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected EntityDiffManager diffManager; + + @Inject + protected ExtendedEntities extendedEntities; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected TimeSource timeSource; + + @Inject + protected EntitySerializationAPI entitySerializationAPI; + + @Inject + protected ViewSerializationAPI viewSerializationAPI; + + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + + @Inject + protected DataManager dataManager; + + @Override + public List getSnapshots(MetaClass metaClass, Object id) { + metaClass = extendedEntities.getOriginalOrThisMetaClass(metaClass); + Entity entity = dataManager.load(new LoadContext<>(metaClass).setId(id).setView(View.LOCAL)); + checkCompositePrimaryKey(entity); + List resultList = null; + View view = metadata.getViewRepository().getView(EntitySnapshot.class, "entitySnapshot.browse"); + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + TypedQuery query = em.createQuery(format( + "select s from sys$EntitySnapshot s where s.entity.%s = :entityId and s.entityMetaClass = :metaClass " + + "order by s.snapshotDate desc", referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), EntitySnapshot.class); + query.setParameter("entityId", referenceToEntitySupport.getReferenceId(entity)); + query.setParameter("metaClass", metaClass.getName()); + query.setView(view); + resultList = query.getResultList(); + + tx.commit(); + } finally { + tx.end(); + } + + return resultList; + } + + @Override + public void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping) { + metaClass = extendedEntities.getOriginalOrThisMetaClass(metaClass); + // load snapshots + List snapshotList = getSnapshots(metaClass, id); + Class javaClass = metaClass.getJavaClass(); + + MetaClass mappedMetaClass = null; + if (classMapping.containsKey(javaClass)) { + Class mappedClass = classMapping.get(javaClass); + mappedMetaClass = extendedEntities.getOriginalOrThisMetaClass(metadata.getClass(mappedClass)); + } + + for (EntitySnapshot snapshot : snapshotList) { + if (mappedMetaClass != null) { + snapshot.setEntityMetaClass(mappedMetaClass.getName()); + } + + String snapshotXml = snapshot.getSnapshotXml(); + String viewXml = snapshot.getViewXml(); + + snapshot.setSnapshotXml(processSnapshotXml(snapshotXml, classMapping)); + snapshot.setViewXml(processViewXml(viewXml, classMapping)); + } + + // Save snapshots to db + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + for (EntitySnapshot snapshot : snapshotList) { + em.merge(snapshot); + } + + tx.commit(); + } finally { + tx.end(); + } + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view) { + return createSnapshot(entity, view, timeSource.currentTimestamp()); + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) { + User user = userSessionSource.getUserSession().getUser(); + return createSnapshot(entity, view, snapshotDate, user); + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) { + Preconditions.checkNotNullArgument(entity); + Preconditions.checkNotNullArgument(view); + Preconditions.checkNotNullArgument(snapshotDate); + + checkCompositePrimaryKey(entity); + + Class viewEntityClass = view.getEntityClass(); + Class entityClass = entity.getClass(); + + if (!viewEntityClass.isAssignableFrom(entityClass)) { + throw new IllegalStateException("View could not be used with this propertyValue"); + } + + MetaClass metaClass = extendedEntities.getOriginalOrThisMetaClass(metadata.getClass(entity.getClass())); + + EntitySnapshot snapshot = metadata.create(EntitySnapshot.class); + snapshot.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); + snapshot.setEntityMetaClass(metaClass.getName()); + snapshot.setViewXml(viewSerializationAPI.toJson(view, ViewSerializationOption.COMPACT_FORMAT)); + snapshot.setSnapshotXml(entitySerializationAPI.toJson(entity)); + snapshot.setSnapshotDate(snapshotDate); + snapshot.setAuthor(author); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + em.persist(snapshot); + + tx.commit(); + } finally { + tx.end(); + } + + return snapshot; + } + + @Override + public Entity extractEntity(EntitySnapshot snapshot) { + String rawResult = snapshot.getSnapshotXml(); + BaseGenericIdEntity entity; + if (isXml(rawResult)) { + entity = (BaseGenericIdEntity) fromXML(snapshot.getSnapshotXml()); + } else { + entity = entitySerializationAPI.entityFromJson(rawResult, metadata.getClass(snapshot.getEntityMetaClass())); + } + return entity; + } + + @Override + public View extractView(EntitySnapshot snapshot) { + String rawResult = snapshot.getViewXml(); + View view; + if (isXml(rawResult)) { + view = (View) fromXML(rawResult); + } else { + view = viewSerializationAPI.fromJson(rawResult); + } + return view; + } + + @Override + public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { + return diffManager.getDifference(first, second); + } + + protected Object fromXML(String xml) { + final List exclUpdateFields = Arrays.asList("updateTs", "updatedBy"); + XStream xStream = new XStream() { + @Override + protected MapperWrapper wrapMapper(MapperWrapper next) { + return new MapperWrapper(next) { + @Override + public boolean shouldSerializeMember(Class definedIn, String fieldName) { + boolean result = super.shouldSerializeMember(definedIn, fieldName); + if (!result) { + return false; + } + if (fieldName != null) { + if (exclUpdateFields.contains(fieldName) + && Updatable.class.isAssignableFrom(definedIn)) { + return false; + } + if ("uuid".equals(fieldName)) { + if (!HasUuid.class.isAssignableFrom(definedIn) + && BaseGenericIdEntity.class.isAssignableFrom(definedIn)) { + return false; + } + } + } + return true; + } + }; + } + }; + xStream.getConverterRegistry().removeConverter(ExternalizableConverter.class); + xStream.omitField(BaseGenericIdEntity.class, "createTs"); + xStream.omitField(BaseGenericIdEntity.class, "createdBy"); + + return xStream.fromXML(xml); + } + + protected boolean isXml(String value) { + return value != null && value.trim().startsWith("<"); + } + + protected void checkCompositePrimaryKey(Entity entity) { + if (metadata.getTools().hasCompositePrimaryKey(entity.getMetaClass()) && !(entity instanceof HasUuid)) { + throw new UnsupportedOperationException(format("Entity %s has no persistent UUID attribute", entity)); + } + } + + protected void replaceInXmlTree(Element element, Map classMapping) { + for (int i = 0; i < element.nodeCount(); i++) { + Node node = element.node(i); + if (node instanceof Element) { + Element childElement = (Element) node; + replaceClasses(childElement, classMapping); + replaceInXmlTree(childElement, classMapping); + } + } + } + + protected void replaceClasses(Element element, Map classMapping) { + // translate XML + for (Map.Entry classEntry : classMapping.entrySet()) { + Class beforeClass = classEntry.getKey(); + Class afterClass = classEntry.getValue(); + + checkNotNull(beforeClass); + checkNotNull(afterClass); + + // If BeforeClass != AfterClass + if (!beforeClass.equals(afterClass)) { + String beforeClassName = beforeClass.getCanonicalName(); + String afterClassName = afterClass.getCanonicalName(); + + if (beforeClassName.equals(element.getName())) { + element.setName(afterClassName); + } + + Attribute classAttribute = element.attribute("class"); + if ((classAttribute != null) && beforeClassName.equals(classAttribute.getValue())) { + classAttribute.setValue(afterClassName); + } + } + } + } + + protected String processViewXml(String viewXml, Map classMapping) { + if (!isXml(viewXml)) { + return viewXml; + } + for (Map.Entry classEntry : classMapping.entrySet()) { + Class beforeClass = classEntry.getKey(); + Class afterClass = classEntry.getValue(); + + checkNotNull(beforeClass); + checkNotNull(afterClass); + + String beforeClassName = beforeClass.getCanonicalName(); + String afterClassName = afterClass.getCanonicalName(); + + viewXml = viewXml.replaceAll(beforeClassName, afterClassName); + } + return viewXml; + } + + protected String processSnapshotXml(String snapshotXml, Map classMapping) { + if (!isXml(snapshotXml)) { + return snapshotXml; + } + Document document; + try { + document = DocumentHelper.parseText(snapshotXml); + } catch (DocumentException e) { + throw new RuntimeException("Couldn't parse snapshot xml content", e); + } + replaceClasses(document.getRootElement(), classMapping); + replaceInXmlTree(document.getRootElement(), classMapping); + return document.asXML(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotServiceBean.java index 2e87b4f540..7ab1d4c72a 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/EntitySnapshotServiceBean.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.User; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@Service(EntitySnapshotService.NAME) -public class EntitySnapshotServiceBean implements EntitySnapshotService { - - @Inject - protected EntitySnapshotAPI snapshotAPI; - - @Override - public List getSnapshots(MetaClass metaClass, Object id) { - return snapshotAPI.getSnapshots(metaClass, id); - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view) { - return snapshotAPI.createSnapshot(entity, view); - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) { - return snapshotAPI.createSnapshot(entity, view, snapshotDate); - } - - @Override - public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) { - return snapshotAPI.createSnapshot(entity, view, snapshotDate, author); - } - - @Override - public Entity extractEntity(EntitySnapshot snapshot) { - return snapshotAPI.extractEntity(snapshot); - } - - @Override - public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { - return snapshotAPI.getDifference(first, second); - } - - @Override - public void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping) { - snapshotAPI.migrateSnapshots(metaClass, id, classMapping); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.User; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Service(EntitySnapshotService.NAME) +public class EntitySnapshotServiceBean implements EntitySnapshotService { + + @Inject + protected EntitySnapshotAPI snapshotAPI; + + @Override + public List getSnapshots(MetaClass metaClass, Object id) { + return snapshotAPI.getSnapshots(metaClass, id); + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view) { + return snapshotAPI.createSnapshot(entity, view); + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate) { + return snapshotAPI.createSnapshot(entity, view, snapshotDate); + } + + @Override + public EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author) { + return snapshotAPI.createSnapshot(entity, view, snapshotDate, author); + } + + @Override + public Entity extractEntity(EntitySnapshot snapshot) { + return snapshotAPI.extractEntity(snapshot); + } + + @Override + public EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second) { + return snapshotAPI.getDifference(first, second); + } + + @Override + public void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping) { + snapshotAPI.migrateSnapshots(metaClass, id, classMapping); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/FileStorageAPI.java b/modules/core/src/com/haulmont/cuba/core/app/FileStorageAPI.java index c79142318f..4dd1928c1a 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/FileStorageAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/FileStorageAPI.java @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; - -import java.io.InputStream; - -/** - * Interface to store and load files defined by {@link FileDescriptor}s. - */ -public interface FileStorageAPI { - String NAME = "cuba_FileStorage"; - - /** - * Save an InputStream contents into file storage. - * @param fileDescr file descriptor - * @param inputStream input stream, must be closed in the calling code - * @return number of bytes saved - * @throws IllegalArgumentException if arguments are incorrect - * @throws FileStorageException if something goes wrong - */ - long saveStream(FileDescriptor fileDescr, InputStream inputStream) throws FileStorageException; - - /** - * Save a byte array into file storage. - * @param fileDescr file descriptor - * @param data byte array - * @throws IllegalArgumentException if arguments are incorrect - * @throws FileStorageException if something goes wrong - */ - void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException; - - /** - * Remove a file from the file storage. - * @param fileDescr file descriptor - * @throws IllegalArgumentException if arguments are incorrect - * @throws FileStorageException if something goes wrong - */ - void removeFile(FileDescriptor fileDescr) throws FileStorageException; - - /** - * Return an input stream to load a file contents. - * @param fileDescr file descriptor - * @return input stream, must be closed after use - * @throws IllegalArgumentException if arguments are incorrect - * @throws FileStorageException if something goes wrong - */ - InputStream openStream(FileDescriptor fileDescr) throws FileStorageException; - - /** - * Load a file contents into byte array. - * @param fileDescr file descriptor - * @return file contents - * @throws IllegalArgumentException if arguments are incorrect - * @throws FileStorageException if something goes wrong - */ - byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException; - - /** - * Tests whether the file denoted by this file descriptor exists. - * @param fileDescr file descriptor - * @return true if the file denoted by this file descriptor exists - * @throws IllegalArgumentException if arguments are incorrect - */ - boolean fileExists(FileDescriptor fileDescr) throws FileStorageException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; + +import java.io.InputStream; + +/** + * Interface to store and load files defined by {@link FileDescriptor}s. + */ +public interface FileStorageAPI { + String NAME = "cuba_FileStorage"; + + /** + * Save an InputStream contents into file storage. + * @param fileDescr file descriptor + * @param inputStream input stream, must be closed in the calling code + * @return number of bytes saved + * @throws IllegalArgumentException if arguments are incorrect + * @throws FileStorageException if something goes wrong + */ + long saveStream(FileDescriptor fileDescr, InputStream inputStream) throws FileStorageException; + + /** + * Save a byte array into file storage. + * @param fileDescr file descriptor + * @param data byte array + * @throws IllegalArgumentException if arguments are incorrect + * @throws FileStorageException if something goes wrong + */ + void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException; + + /** + * Remove a file from the file storage. + * @param fileDescr file descriptor + * @throws IllegalArgumentException if arguments are incorrect + * @throws FileStorageException if something goes wrong + */ + void removeFile(FileDescriptor fileDescr) throws FileStorageException; + + /** + * Return an input stream to load a file contents. + * @param fileDescr file descriptor + * @return input stream, must be closed after use + * @throws IllegalArgumentException if arguments are incorrect + * @throws FileStorageException if something goes wrong + */ + InputStream openStream(FileDescriptor fileDescr) throws FileStorageException; + + /** + * Load a file contents into byte array. + * @param fileDescr file descriptor + * @return file contents + * @throws IllegalArgumentException if arguments are incorrect + * @throws FileStorageException if something goes wrong + */ + byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException; + + /** + * Tests whether the file denoted by this file descriptor exists. + * @param fileDescr file descriptor + * @return true if the file denoted by this file descriptor exists + * @throws IllegalArgumentException if arguments are incorrect + */ + boolean fileExists(FileDescriptor fileDescr) throws FileStorageException; } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/FileStorageServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/FileStorageServiceBean.java index 538ef76c83..502ad9ff9f 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/FileStorageServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/FileStorageServiceBean.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; - -@Service(FileStorageService.NAME) -public class FileStorageServiceBean implements FileStorageService { - - @Inject - protected FileStorageAPI fileStorageAPI; - - @Override - public void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException { - fileStorageAPI.saveFile(fileDescr, data); - } - - @Override - public void removeFile(FileDescriptor fileDescr) throws FileStorageException { - fileStorageAPI.removeFile(fileDescr); - } - - @Override - public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { - return fileStorageAPI.loadFile(fileDescr); - } - - @Override - public boolean fileExists(FileDescriptor fileDescr) throws FileStorageException { - return fileStorageAPI.fileExists(fileDescr); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; + +@Service(FileStorageService.NAME) +public class FileStorageServiceBean implements FileStorageService { + + @Inject + protected FileStorageAPI fileStorageAPI; + + @Override + public void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException { + fileStorageAPI.saveFile(fileDescr, data); + } + + @Override + public void removeFile(FileDescriptor fileDescr) throws FileStorageException { + fileStorageAPI.removeFile(fileDescr); + } + + @Override + public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { + return fileStorageAPI.loadFile(fileDescr); + } + + @Override + public boolean fileExists(FileDescriptor fileDescr) throws FileStorageException { + return fileStorageAPI.fileExists(fileDescr); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/FoldersServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/FoldersServiceBean.java index 9fd717e6c2..4a390d2bd7 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/FoldersServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/FoldersServiceBean.java @@ -1,360 +1,360 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.entity.AppFolder; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Folder; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.EntityOp; -import com.haulmont.cuba.security.entity.PermissionType; -import com.haulmont.cuba.security.entity.SearchFolder; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.UserSession; -import com.thoughtworks.xstream.XStream; -import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; -import com.thoughtworks.xstream.core.DefaultConverterLookup; -import com.thoughtworks.xstream.core.util.ClassLoaderReference; -import com.thoughtworks.xstream.io.xml.XppDriver; -import groovy.lang.Binding; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.compress.archivers.ArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; -import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Iterator; -import java.util.List; -import java.util.zip.CRC32; - -@Service(FoldersService.NAME) -public class FoldersServiceBean implements FoldersService { - - private final Logger log = LoggerFactory.getLogger(FoldersServiceBean.class); - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected Metadata metadata; - - @Inject - protected Persistence persistence; - - @Inject - protected Scripting scripting; - - @Inject - protected Resources resources; - - @Inject - protected Security security; - - @Inject - protected TimeSource timeSource; - - @Override - public List loadAppFolders() { - log.debug("Loading AppFolders"); - - StopWatch stopWatch = new Log4JStopWatch("AppFolders"); - stopWatch.start(); - - List resultList; - try (Transaction tx = persistence.createTransaction()) { - String metaClassName = metadata.getExtendedEntities().getEffectiveMetaClass(AppFolder.class).getName(); - TypedQuery q = persistence.getEntityManager().createQuery( - "select f from " + metaClassName + " f order by f.sortOrder, f.name", AppFolder.class); - - resultList = q.getResultList(); - // fetch parent folder - resultList.forEach(Folder::getParent); - - tx.commit(); - } finally { - stopWatch.stop(); - } - - if (CollectionUtils.isNotEmpty(resultList)) { - Binding binding = new Binding(); - binding.setVariable("persistence", persistence); - binding.setVariable("metadata", metadata); - binding.setVariable("userSession", userSessionSource.getUserSession()); - - Iterator iterator = resultList.iterator(); - while (iterator.hasNext()) { - AppFolder folder = iterator.next(); - try (Transaction tx = persistence.createTransaction()) { - boolean evaluatedVisibilityScript = true; - try { - if (!StringUtils.isBlank(folder.getVisibilityScript())) { - binding.setVariable("folder", folder); - Boolean visible = runScript(folder.getVisibilityScript(), binding); - if (BooleanUtils.isFalse(visible)) { - iterator.remove(); - continue; - } - } - } catch (Exception e) { - log.warn("Unable to evaluate AppFolder visibility script for folder: id: {} name: {}", - folder.getId(), folder.getName(), e); - // because EclipseLink Query marks transaction as rollback-only on JPQL syntax errors - evaluatedVisibilityScript = false; - } - - boolean evaluatedQuantityScript = loadFolderQuantity(binding, folder); - - if (evaluatedVisibilityScript && evaluatedQuantityScript) { - tx.commit(); - } - } - } - } - - return resultList; - } - - protected T runScript(String script, Binding binding) { - script = StringUtils.trim(script); - if (script.endsWith(".groovy")) { - script = resources.getResourceAsString(script); - } - Object result = scripting.evaluateGroovy(script, binding); - //noinspection unchecked - return (T) result; - } - - @Override - public List reloadAppFolders(List folders) { - log.debug("Reloading AppFolders {}", folders); - - StopWatch stopWatch = new Log4JStopWatch("AppFolders"); - stopWatch.start(); - - try { - if (!folders.isEmpty()) { - Binding binding = new Binding(); - binding.setVariable("persistence", persistence); - binding.setVariable("metadata", metadata); - binding.setProperty("userSession", userSessionSource.getUserSession()); - - for (AppFolder folder : folders) { - Transaction tx = persistence.createTransaction(); - try { - if (loadFolderQuantity(binding, folder)) { - tx.commit(); - } - } finally { - tx.end(); - } - } - } - - return folders; - } finally { - stopWatch.stop(); - } - } - - protected boolean loadFolderQuantity(Binding binding, AppFolder folder) { - if (!StringUtils.isBlank(folder.getQuantityScript())) { - binding.setVariable("folder", folder); - - String styleVariable = "style"; - binding.setVariable(styleVariable, null); - - try { - Number qty = runScript(folder.getQuantityScript(), binding); - folder.setItemStyle((String) binding.getVariable(styleVariable)); - folder.setQuantity(qty == null ? null : qty.intValue()); - } catch (Exception e) { - log.warn("Unable to evaluate AppFolder quantity script for folder: id: {} , name: {}", - folder.getId(), folder.getName(), e); - return false; - } - } - - return true; - } - - @Override - public List loadSearchFolders() { - log.debug("Loading SearchFolders"); - - StopWatch stopWatch = new Log4JStopWatch("SearchFolders"); - stopWatch.start(); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(SearchFolder.class); - TypedQuery q = em.createQuery("select f from "+ effectiveMetaClass.getName() +" f " + - "left join fetch f.user u on u.id = ?1 " + - "left join fetch f.presentation " + - "where (u.id = ?1 or u is null) " + - "order by f.sortOrder, f.name", - SearchFolder.class); - q.setParameter(1, userSessionSource.currentOrSubstitutedUserId()); - List list = q.getResultList(); - // fetch parents - for (SearchFolder folder : list) { - folder.getParent(); - } - - tx.commit(); - return list; - } finally { - tx.end(); - - stopWatch.stop(); - } - } - - @Override - public byte[] exportFolder(Folder folder) throws IOException { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - - ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(byteArrayOutputStream); - zipOutputStream.setMethod(ZipArchiveOutputStream.STORED); - zipOutputStream.setEncoding(StandardCharsets.UTF_8.name()); - String xml = createXStream().toXML(folder); - byte[] xmlBytes = xml.getBytes(StandardCharsets.UTF_8); - ArchiveEntry zipEntryDesign = newStoredEntry("folder.xml", xmlBytes); - zipOutputStream.putArchiveEntry(zipEntryDesign); - zipOutputStream.write(xmlBytes); - try { - zipOutputStream.closeArchiveEntry(); - } catch (Exception ex) { - throw new RuntimeException(String.format("Exception occurred while exporting folder %s.", folder.getName())); - } - - zipOutputStream.close(); - return byteArrayOutputStream.toByteArray(); - } - - @Override - public Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException { - if (!security.isEntityOpPermitted(Folder.class, EntityOp.CREATE)) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); - } - - Folder folder = null; - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); - ZipArchiveInputStream archiveReader; - archiveReader = new ZipArchiveInputStream(byteArrayInputStream); - ZipArchiveEntry archiveEntry; - - while (((archiveEntry = archiveReader.getNextZipEntry()) != null) && (folder == null)) { - if (archiveEntry.getName().equals("folder.xml")) { - String xml = new String(IOUtils.toByteArray(archiveReader), StandardCharsets.UTF_8); - folder = (Folder) createXStream().fromXML(xml); - } - } - - byteArrayInputStream.close(); - - if (folder != null) { - checkImportPermissions(folder); - folder.setParent(parentFolder); - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - em.setSoftDeletion(false); - Folder existingFolder = em.find(Folder.class, folder.getId()); - if (existingFolder != null) { - checkImportPermissions(existingFolder); - folder.setVersion(existingFolder.getVersion()); - folder.setCreateTs(existingFolder.getCreateTs()); - folder.setCreatedBy(existingFolder.getCreatedBy()); - } else { - User user = userSessionSource.getUserSession().getUser(); - folder.setCreatedBy(user.getLoginLowerCase()); - folder.setCreateTs(timeSource.currentTimestamp()); - folder.setUpdatedBy(null); - folder.setUpdateTs(null); - folder.setVersion(0); - } - - em.merge(folder); - tx.commit(); - } finally { - tx.end(); - } - } - return folder; - } - - protected void checkImportPermissions(Folder folder) { - UserSession userSession = userSessionSource.getUserSession(); - if (folder instanceof SearchFolder) { - SearchFolder searchFolder = (SearchFolder) folder; - User currentUser = userSession.getCurrentOrSubstitutedUser(); - if (searchFolder.getUser() != null && !currentUser.equals(searchFolder.getUser())) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); - } - if (searchFolder.getUser() == null && !userSession.isSpecificPermitted("cuba.gui.searchFolder.global")) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); - } - } - if (folder instanceof AppFolder) { - if (!userSession.isSpecificPermitted("cuba.gui.appFolder.global")) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); - } - } - } - - protected XStream createXStream() { - XStream xStream = new XStream(null, new XppDriver(), - new ClassLoaderReference(Thread.currentThread().getContextClassLoader()), - null, new DefaultConverterLookup(), null); - //createTs and createdBy removed from BaseGenericIdEntity, - //and import from old versions (platform 6.2) is performed with errors - //so omit field processing - xStream.omitField(BaseGenericIdEntity.class, "createTs"); - xStream.omitField(BaseGenericIdEntity.class, "createdBy"); - xStream.getConverterRegistry().removeConverter(ExternalizableConverter.class); - return xStream; - } - - protected ArchiveEntry newStoredEntry(String name, byte[] data) { - ZipArchiveEntry zipEntry = new ZipArchiveEntry(name); - zipEntry.setSize(data.length); - zipEntry.setCompressedSize(zipEntry.getSize()); - CRC32 crc32 = new CRC32(); - crc32.update(data); - zipEntry.setCrc(crc32.getValue()); - return zipEntry; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.entity.AppFolder; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Folder; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.EntityOp; +import com.haulmont.cuba.security.entity.PermissionType; +import com.haulmont.cuba.security.entity.SearchFolder; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.UserSession; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; +import com.thoughtworks.xstream.core.DefaultConverterLookup; +import com.thoughtworks.xstream.core.util.ClassLoaderReference; +import com.thoughtworks.xstream.io.xml.XppDriver; +import groovy.lang.Binding; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.List; +import java.util.zip.CRC32; + +@Service(FoldersService.NAME) +public class FoldersServiceBean implements FoldersService { + + private final Logger log = LoggerFactory.getLogger(FoldersServiceBean.class); + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected Metadata metadata; + + @Inject + protected Persistence persistence; + + @Inject + protected Scripting scripting; + + @Inject + protected Resources resources; + + @Inject + protected Security security; + + @Inject + protected TimeSource timeSource; + + @Override + public List loadAppFolders() { + log.debug("Loading AppFolders"); + + StopWatch stopWatch = new Log4JStopWatch("AppFolders"); + stopWatch.start(); + + List resultList; + try (Transaction tx = persistence.createTransaction()) { + String metaClassName = metadata.getExtendedEntities().getEffectiveMetaClass(AppFolder.class).getName(); + TypedQuery q = persistence.getEntityManager().createQuery( + "select f from " + metaClassName + " f order by f.sortOrder, f.name", AppFolder.class); + + resultList = q.getResultList(); + // fetch parent folder + resultList.forEach(Folder::getParent); + + tx.commit(); + } finally { + stopWatch.stop(); + } + + if (CollectionUtils.isNotEmpty(resultList)) { + Binding binding = new Binding(); + binding.setVariable("persistence", persistence); + binding.setVariable("metadata", metadata); + binding.setVariable("userSession", userSessionSource.getUserSession()); + + Iterator iterator = resultList.iterator(); + while (iterator.hasNext()) { + AppFolder folder = iterator.next(); + try (Transaction tx = persistence.createTransaction()) { + boolean evaluatedVisibilityScript = true; + try { + if (!StringUtils.isBlank(folder.getVisibilityScript())) { + binding.setVariable("folder", folder); + Boolean visible = runScript(folder.getVisibilityScript(), binding); + if (BooleanUtils.isFalse(visible)) { + iterator.remove(); + continue; + } + } + } catch (Exception e) { + log.warn("Unable to evaluate AppFolder visibility script for folder: id: {} name: {}", + folder.getId(), folder.getName(), e); + // because EclipseLink Query marks transaction as rollback-only on JPQL syntax errors + evaluatedVisibilityScript = false; + } + + boolean evaluatedQuantityScript = loadFolderQuantity(binding, folder); + + if (evaluatedVisibilityScript && evaluatedQuantityScript) { + tx.commit(); + } + } + } + } + + return resultList; + } + + protected T runScript(String script, Binding binding) { + script = StringUtils.trim(script); + if (script.endsWith(".groovy")) { + script = resources.getResourceAsString(script); + } + Object result = scripting.evaluateGroovy(script, binding); + //noinspection unchecked + return (T) result; + } + + @Override + public List reloadAppFolders(List folders) { + log.debug("Reloading AppFolders {}", folders); + + StopWatch stopWatch = new Log4JStopWatch("AppFolders"); + stopWatch.start(); + + try { + if (!folders.isEmpty()) { + Binding binding = new Binding(); + binding.setVariable("persistence", persistence); + binding.setVariable("metadata", metadata); + binding.setProperty("userSession", userSessionSource.getUserSession()); + + for (AppFolder folder : folders) { + Transaction tx = persistence.createTransaction(); + try { + if (loadFolderQuantity(binding, folder)) { + tx.commit(); + } + } finally { + tx.end(); + } + } + } + + return folders; + } finally { + stopWatch.stop(); + } + } + + protected boolean loadFolderQuantity(Binding binding, AppFolder folder) { + if (!StringUtils.isBlank(folder.getQuantityScript())) { + binding.setVariable("folder", folder); + + String styleVariable = "style"; + binding.setVariable(styleVariable, null); + + try { + Number qty = runScript(folder.getQuantityScript(), binding); + folder.setItemStyle((String) binding.getVariable(styleVariable)); + folder.setQuantity(qty == null ? null : qty.intValue()); + } catch (Exception e) { + log.warn("Unable to evaluate AppFolder quantity script for folder: id: {} , name: {}", + folder.getId(), folder.getName(), e); + return false; + } + } + + return true; + } + + @Override + public List loadSearchFolders() { + log.debug("Loading SearchFolders"); + + StopWatch stopWatch = new Log4JStopWatch("SearchFolders"); + stopWatch.start(); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(SearchFolder.class); + TypedQuery q = em.createQuery("select f from "+ effectiveMetaClass.getName() +" f " + + "left join fetch f.user u on u.id = ?1 " + + "left join fetch f.presentation " + + "where (u.id = ?1 or u is null) " + + "order by f.sortOrder, f.name", + SearchFolder.class); + q.setParameter(1, userSessionSource.currentOrSubstitutedUserId()); + List list = q.getResultList(); + // fetch parents + for (SearchFolder folder : list) { + folder.getParent(); + } + + tx.commit(); + return list; + } finally { + tx.end(); + + stopWatch.stop(); + } + } + + @Override + public byte[] exportFolder(Folder folder) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(byteArrayOutputStream); + zipOutputStream.setMethod(ZipArchiveOutputStream.STORED); + zipOutputStream.setEncoding(StandardCharsets.UTF_8.name()); + String xml = createXStream().toXML(folder); + byte[] xmlBytes = xml.getBytes(StandardCharsets.UTF_8); + ArchiveEntry zipEntryDesign = newStoredEntry("folder.xml", xmlBytes); + zipOutputStream.putArchiveEntry(zipEntryDesign); + zipOutputStream.write(xmlBytes); + try { + zipOutputStream.closeArchiveEntry(); + } catch (Exception ex) { + throw new RuntimeException(String.format("Exception occurred while exporting folder %s.", folder.getName())); + } + + zipOutputStream.close(); + return byteArrayOutputStream.toByteArray(); + } + + @Override + public Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException { + if (!security.isEntityOpPermitted(Folder.class, EntityOp.CREATE)) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); + } + + Folder folder = null; + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); + ZipArchiveInputStream archiveReader; + archiveReader = new ZipArchiveInputStream(byteArrayInputStream); + ZipArchiveEntry archiveEntry; + + while (((archiveEntry = archiveReader.getNextZipEntry()) != null) && (folder == null)) { + if (archiveEntry.getName().equals("folder.xml")) { + String xml = new String(IOUtils.toByteArray(archiveReader), StandardCharsets.UTF_8); + folder = (Folder) createXStream().fromXML(xml); + } + } + + byteArrayInputStream.close(); + + if (folder != null) { + checkImportPermissions(folder); + folder.setParent(parentFolder); + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + em.setSoftDeletion(false); + Folder existingFolder = em.find(Folder.class, folder.getId()); + if (existingFolder != null) { + checkImportPermissions(existingFolder); + folder.setVersion(existingFolder.getVersion()); + folder.setCreateTs(existingFolder.getCreateTs()); + folder.setCreatedBy(existingFolder.getCreatedBy()); + } else { + User user = userSessionSource.getUserSession().getUser(); + folder.setCreatedBy(user.getLoginLowerCase()); + folder.setCreateTs(timeSource.currentTimestamp()); + folder.setUpdatedBy(null); + folder.setUpdateTs(null); + folder.setVersion(0); + } + + em.merge(folder); + tx.commit(); + } finally { + tx.end(); + } + } + return folder; + } + + protected void checkImportPermissions(Folder folder) { + UserSession userSession = userSessionSource.getUserSession(); + if (folder instanceof SearchFolder) { + SearchFolder searchFolder = (SearchFolder) folder; + User currentUser = userSession.getCurrentOrSubstitutedUser(); + if (searchFolder.getUser() != null && !currentUser.equals(searchFolder.getUser())) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); + } + if (searchFolder.getUser() == null && !userSession.isSpecificPermitted("cuba.gui.searchFolder.global")) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); + } + } + if (folder instanceof AppFolder) { + if (!userSession.isSpecificPermitted("cuba.gui.appFolder.global")) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, Folder.class.getSimpleName()); + } + } + } + + protected XStream createXStream() { + XStream xStream = new XStream(null, new XppDriver(), + new ClassLoaderReference(Thread.currentThread().getContextClassLoader()), + null, new DefaultConverterLookup(), null); + //createTs and createdBy removed from BaseGenericIdEntity, + //and import from old versions (platform 6.2) is performed with errors + //so omit field processing + xStream.omitField(BaseGenericIdEntity.class, "createTs"); + xStream.omitField(BaseGenericIdEntity.class, "createdBy"); + xStream.getConverterRegistry().removeConverter(ExternalizableConverter.class); + return xStream; + } + + protected ArchiveEntry newStoredEntry(String name, byte[] data) { + ZipArchiveEntry zipEntry = new ZipArchiveEntry(name); + zipEntry.setSize(data.length); + zipEntry.setCompressedSize(zipEntry.getSize()); + CRC32 crc32 = new CRC32(); + crc32.update(data); + zipEntry.setCrc(crc32.getValue()); + return zipEntry; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/FtsSender.java b/modules/core/src/com/haulmont/cuba/core/app/FtsSender.java index 9d94564a33..fcf308d4a0 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/FtsSender.java +++ b/modules/core/src/com/haulmont/cuba/core/app/FtsSender.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.FtsChangeType; - -/** - * Interface that is used to enqueue changed entities for indexing in Full Text Search engine. - * It is implemented outside CUBA in the FTS app component. - */ -public interface FtsSender { - - String NAME = "cuba_FtsSender"; - - void enqueue(Entity entity, FtsChangeType changeType); - - void enqueue(String entityName, Object entityId, FtsChangeType changeType); - - void enqueueFake(String entityName, Object entityId); - - void emptyQueue(String entityName); - - void emptyFakeQueue(String entityName); - - void emptyQueue(); - - void initDefault(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.FtsChangeType; + +/** + * Interface that is used to enqueue changed entities for indexing in Full Text Search engine. + * It is implemented outside CUBA in the FTS app component. + */ +public interface FtsSender { + + String NAME = "cuba_FtsSender"; + + void enqueue(Entity entity, FtsChangeType changeType); + + void enqueue(String entityName, Object entityId, FtsChangeType changeType); + + void enqueueFake(String entityName, Object entityId); + + void emptyQueue(String entityName); + + void emptyFakeQueue(String entityName); + + void emptyQueue(); + + void initDefault(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/LockManager.java b/modules/core/src/com/haulmont/cuba/core/app/LockManager.java index 67d2b0d124..c9605c72da 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/LockManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/LockManager.java @@ -1,272 +1,272 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.LockDescriptor; -import com.haulmont.cuba.core.global.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.*; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -@Component(LockManagerAPI.NAME) -public class LockManager implements LockManagerAPI, ClusterListener { - - private static class LockKey { - - private final String name; - private final String id; - - private LockKey(String name, String id) { - this.name = name; - this.id = id; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - LockKey key = (LockKey) o; - - if (id != null ? !id.equals(key.id) : key.id != null) return false; - if (!name.equals(key.name)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = name.hashCode(); - result = 31 * result + (id != null ? id.hashCode() : 0); - return result; - } - } - - private Logger log = LoggerFactory.getLogger(LockManager.class); - - private volatile Map config; - - private Map locks = new ConcurrentHashMap<>(); - - @Inject - private Persistence persistence; - - @Inject - private Metadata metadata; - - @Inject - private UserSessionSource userSessionSource; - - private ClusterManagerAPI clusterManager; - - @Inject - public void setClusterManager(ClusterManagerAPI clusterManager) { - this.clusterManager = clusterManager; - this.clusterManager.addListener(LockInfo.class, this); - } - - private Map getConfig() { - if (this.config == null) { - synchronized (this) { - if (this.config == null) { - Map config = new ConcurrentHashMap<>(); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - TypedQuery q = em.createQuery( - "select d from sys$LockDescriptor d", LockDescriptor.class); - List list = q.getResultList(); - for (LockDescriptor ld : list) { - config.put(ld.getName(), ld); - } - tx.commit(); - } finally { - tx.end(); - } - this.config = config; - } - } - } - return config; - } - - @Override - public LockInfo lock(String name, String id) { - LockKey key = new LockKey(name, id); - - LockInfo lockInfo = locks.get(key); - if (lockInfo != null) { - log.debug("Already locked: " + lockInfo); - return lockInfo; - } - - LockDescriptor ld = getConfig().get(name); - if (ld == null) { - return new LockNotSupported(); - } - - lockInfo = new LockInfo(userSessionSource.getUserSession().getCurrentOrSubstitutedUser(), name, id); - locks.put(key, lockInfo); - log.debug("Locked " + name + "/" + id); - - clusterManager.send(lockInfo); - - return null; - } - - @Nullable - @Override - public LockInfo lock(Entity entity) { - Preconditions.checkNotNullArgument(entity, "entity is null"); - - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass); - - return lock(originalMetaClass.getName(), entity.getId().toString()); - } - - @Override - public void unlock(String name, String id) { - LockInfo lockInfo = locks.remove(new LockKey(name, id)); - if (lockInfo != null) { - log.debug("Unlocked " + name + "/" + id); - - clusterManager.send(new LockInfo(null, name, id)); - } - } - - @Override - public void unlock(Entity entity) { - Preconditions.checkNotNullArgument(entity, "entity is null"); - - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass); - - unlock(originalMetaClass.getName(), entity.getId().toString()); - } - - @Override - public LockInfo getLockInfo(String name, String id) { - LockDescriptor ld = getConfig().get(name); - if (ld == null) { - return new LockNotSupported(); - } - - return locks.get(new LockKey(name, id)); - } - - @Override - public List getCurrentLocks() { - return new ArrayList<>(locks.values()); - } - - @Override - public void expireLocks() { - log.debug("Expiring locks"); - ArrayList list = new ArrayList<>(locks.keySet()); - for (LockKey key : list) { - LockInfo lockInfo = locks.get(key); - if (lockInfo != null) { - LockDescriptor ld = getConfig().get(key.name); - if (ld == null) { - log.debug("Lock " + key.name + "/" + key.id + " configuration not found, remove it"); - locks.remove(key); - } else { - Integer timeoutSec = ld.getTimeoutSec(); - if (timeoutSec != null && timeoutSec > 0) { - Date since = lockInfo.getSince(); - if (since.getTime() + timeoutSec * 1000 < AppBeans.get(TimeSource.class).currentTimestamp().getTime()) { - log.debug("Lock " + key.name + "/" + key.id + " expired"); - locks.remove(key); - } - } - } - } - } - } - - @Override - public void reloadConfiguration() { - config = null; - } - - @Override - public void receive(LockInfo message) { - LockKey key = new LockKey(message.getEntityName(), message.getEntityId()); - if (message.getUser() != null) { - LockInfo lockInfo = locks.get(key); - if (lockInfo == null || lockInfo.getSince().before(message.getSince())) { - locks.put(key, message); - } - } else { - locks.remove(key); - } - } - - @Override - public byte[] getState() { - List list = new ArrayList<>(locks.values()); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(list); - } catch (IOException e) { - log.error("Error serializing LockInfo list", e); - return new byte[0]; - } - return bos.toByteArray(); - } - - @Override - public void setState(byte[] state) { - if (state == null || state.length == 0) - return; - - List list; - ByteArrayInputStream bis = new ByteArrayInputStream(state); - try { - ObjectInputStream ois = new ObjectInputStream(bis); - list = (List) ois.readObject(); - } catch (Exception e) { - log.error("Error deserializing LockInfo list", e); - return; - } - - for (LockInfo lockInfo : list) { - receive(lockInfo); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.LockDescriptor; +import com.haulmont.cuba.core.global.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component(LockManagerAPI.NAME) +public class LockManager implements LockManagerAPI, ClusterListener { + + private static class LockKey { + + private final String name; + private final String id; + + private LockKey(String name, String id) { + this.name = name; + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LockKey key = (LockKey) o; + + if (id != null ? !id.equals(key.id) : key.id != null) return false; + if (!name.equals(key.name)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + (id != null ? id.hashCode() : 0); + return result; + } + } + + private Logger log = LoggerFactory.getLogger(LockManager.class); + + private volatile Map config; + + private Map locks = new ConcurrentHashMap<>(); + + @Inject + private Persistence persistence; + + @Inject + private Metadata metadata; + + @Inject + private UserSessionSource userSessionSource; + + private ClusterManagerAPI clusterManager; + + @Inject + public void setClusterManager(ClusterManagerAPI clusterManager) { + this.clusterManager = clusterManager; + this.clusterManager.addListener(LockInfo.class, this); + } + + private Map getConfig() { + if (this.config == null) { + synchronized (this) { + if (this.config == null) { + Map config = new ConcurrentHashMap<>(); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + TypedQuery q = em.createQuery( + "select d from sys$LockDescriptor d", LockDescriptor.class); + List list = q.getResultList(); + for (LockDescriptor ld : list) { + config.put(ld.getName(), ld); + } + tx.commit(); + } finally { + tx.end(); + } + this.config = config; + } + } + } + return config; + } + + @Override + public LockInfo lock(String name, String id) { + LockKey key = new LockKey(name, id); + + LockInfo lockInfo = locks.get(key); + if (lockInfo != null) { + log.debug("Already locked: " + lockInfo); + return lockInfo; + } + + LockDescriptor ld = getConfig().get(name); + if (ld == null) { + return new LockNotSupported(); + } + + lockInfo = new LockInfo(userSessionSource.getUserSession().getCurrentOrSubstitutedUser(), name, id); + locks.put(key, lockInfo); + log.debug("Locked " + name + "/" + id); + + clusterManager.send(lockInfo); + + return null; + } + + @Nullable + @Override + public LockInfo lock(Entity entity) { + Preconditions.checkNotNullArgument(entity, "entity is null"); + + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass); + + return lock(originalMetaClass.getName(), entity.getId().toString()); + } + + @Override + public void unlock(String name, String id) { + LockInfo lockInfo = locks.remove(new LockKey(name, id)); + if (lockInfo != null) { + log.debug("Unlocked " + name + "/" + id); + + clusterManager.send(new LockInfo(null, name, id)); + } + } + + @Override + public void unlock(Entity entity) { + Preconditions.checkNotNullArgument(entity, "entity is null"); + + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass); + + unlock(originalMetaClass.getName(), entity.getId().toString()); + } + + @Override + public LockInfo getLockInfo(String name, String id) { + LockDescriptor ld = getConfig().get(name); + if (ld == null) { + return new LockNotSupported(); + } + + return locks.get(new LockKey(name, id)); + } + + @Override + public List getCurrentLocks() { + return new ArrayList<>(locks.values()); + } + + @Override + public void expireLocks() { + log.debug("Expiring locks"); + ArrayList list = new ArrayList<>(locks.keySet()); + for (LockKey key : list) { + LockInfo lockInfo = locks.get(key); + if (lockInfo != null) { + LockDescriptor ld = getConfig().get(key.name); + if (ld == null) { + log.debug("Lock " + key.name + "/" + key.id + " configuration not found, remove it"); + locks.remove(key); + } else { + Integer timeoutSec = ld.getTimeoutSec(); + if (timeoutSec != null && timeoutSec > 0) { + Date since = lockInfo.getSince(); + if (since.getTime() + timeoutSec * 1000 < AppBeans.get(TimeSource.class).currentTimestamp().getTime()) { + log.debug("Lock " + key.name + "/" + key.id + " expired"); + locks.remove(key); + } + } + } + } + } + } + + @Override + public void reloadConfiguration() { + config = null; + } + + @Override + public void receive(LockInfo message) { + LockKey key = new LockKey(message.getEntityName(), message.getEntityId()); + if (message.getUser() != null) { + LockInfo lockInfo = locks.get(key); + if (lockInfo == null || lockInfo.getSince().before(message.getSince())) { + locks.put(key, message); + } + } else { + locks.remove(key); + } + } + + @Override + public byte[] getState() { + List list = new ArrayList<>(locks.values()); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(list); + } catch (IOException e) { + log.error("Error serializing LockInfo list", e); + return new byte[0]; + } + return bos.toByteArray(); + } + + @Override + public void setState(byte[] state) { + if (state == null || state.length == 0) + return; + + List list; + ByteArrayInputStream bis = new ByteArrayInputStream(state); + try { + ObjectInputStream ois = new ObjectInputStream(bis); + list = (List) ois.readObject(); + } catch (Exception e) { + log.error("Error deserializing LockInfo list", e); + return; + } + + for (LockInfo lockInfo : list) { + receive(lockInfo); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/LockManagerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/LockManagerAPI.java index edcc336568..c81060b457 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/LockManagerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/LockManagerAPI.java @@ -1,88 +1,88 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.LockInfo; - -import javax.annotation.Nullable; -import java.util.List; - -/** - * Interface for pessimistic locking. - */ -public interface LockManagerAPI { - - String NAME = "cuba_LockManager"; - - /** - * Try to lock an arbitrary object. - * @param name locking object name - * @param id locking object ID - * @return - null in case of successful lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
- * - {@link LockInfo} instance in case of this object is already locked by someone - */ - @Nullable - LockInfo lock(String name, String id); - - /** - * Try to lock an entity. - * @param entity entity instance - * @return - null in case of successful lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this entity,
- * - {@link LockInfo} instance in case of this entity is already locked by someone - */ - @Nullable - LockInfo lock(Entity entity); - - /** - * Unlock an arbitrary object. - * @param name locking object name - * @param id locking object ID - */ - void unlock(String name, String id); - - /** - * Unlock an entity. - * @param entity entity instance - */ - void unlock(Entity entity); - - /** - * Get locking status for particular object - * @param name locking object name - * @param id locking object ID - * @return - null in case of no lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
- * - {@link LockInfo} instance in case of this object is locked by someone - */ - @Nullable - LockInfo getLockInfo(String name, String id); - - /** - * List of current locks - */ - List getCurrentLocks(); - - /** - * Process locks expiring. All expired locks will be removed. - */ - void expireLocks(); - - void reloadConfiguration(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.LockInfo; + +import javax.annotation.Nullable; +import java.util.List; + +/** + * Interface for pessimistic locking. + */ +public interface LockManagerAPI { + + String NAME = "cuba_LockManager"; + + /** + * Try to lock an arbitrary object. + * @param name locking object name + * @param id locking object ID + * @return - null in case of successful lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
+ * - {@link LockInfo} instance in case of this object is already locked by someone + */ + @Nullable + LockInfo lock(String name, String id); + + /** + * Try to lock an entity. + * @param entity entity instance + * @return - null in case of successful lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this entity,
+ * - {@link LockInfo} instance in case of this entity is already locked by someone + */ + @Nullable + LockInfo lock(Entity entity); + + /** + * Unlock an arbitrary object. + * @param name locking object name + * @param id locking object ID + */ + void unlock(String name, String id); + + /** + * Unlock an entity. + * @param entity entity instance + */ + void unlock(Entity entity); + + /** + * Get locking status for particular object + * @param name locking object name + * @param id locking object ID + * @return - null in case of no lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
+ * - {@link LockInfo} instance in case of this object is locked by someone + */ + @Nullable + LockInfo getLockInfo(String name, String id); + + /** + * List of current locks + */ + List getCurrentLocks(); + + /** + * Process locks expiring. All expired locks will be removed. + */ + void expireLocks(); + + void reloadConfiguration(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/LockServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/LockServiceBean.java index 1b60a38a5c..b6db7c4471 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/LockServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/LockServiceBean.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.LockInfo; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.List; - -@Service(LockService.NAME) -public class LockServiceBean implements LockService { - - @Inject - private LockManagerAPI lockManager; - - @Override - public LockInfo lock(String name, String id) { - return lockManager.lock(name, id); - } - - @Nullable - @Override - public LockInfo lock(Entity entity) { - return lockManager.lock(entity); - } - - @Override - public void unlock(String name, String id) { - lockManager.unlock(name, id); - } - - @Override - public void unlock(Entity entity) { - lockManager.unlock(entity); - } - - @Override - public LockInfo getLockInfo(String name, String id) { - return lockManager.getLockInfo(name, id); - } - - @Override - public List getCurrentLocks() { - return lockManager.getCurrentLocks(); - } - - @Override - public void reloadConfiguration(){ - lockManager.reloadConfiguration(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.LockInfo; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.List; + +@Service(LockService.NAME) +public class LockServiceBean implements LockService { + + @Inject + private LockManagerAPI lockManager; + + @Override + public LockInfo lock(String name, String id) { + return lockManager.lock(name, id); + } + + @Nullable + @Override + public LockInfo lock(Entity entity) { + return lockManager.lock(entity); + } + + @Override + public void unlock(String name, String id) { + lockManager.unlock(name, id); + } + + @Override + public void unlock(Entity entity) { + lockManager.unlock(entity); + } + + @Override + public LockInfo getLockInfo(String name, String id) { + return lockManager.getLockInfo(name, id); + } + + @Override + public List getCurrentLocks() { + return lockManager.getCurrentLocks(); + } + + @Override + public void reloadConfiguration(){ + lockManager.reloadConfiguration(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/MiddlewareStatisticsAccumulator.java b/modules/core/src/com/haulmont/cuba/core/app/MiddlewareStatisticsAccumulator.java index 6273c2a75a..81dc66fc04 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/MiddlewareStatisticsAccumulator.java +++ b/modules/core/src/com/haulmont/cuba/core/app/MiddlewareStatisticsAccumulator.java @@ -1,152 +1,152 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.StatisticsAccumulator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import java.lang.management.ManagementFactory; -import java.util.concurrent.atomic.AtomicLong; - -@Component(MiddlewareStatisticsAccumulator.NAME) -public class MiddlewareStatisticsAccumulator extends StatisticsAccumulator { - - public static final String NAME = "cuba_MiddlewareStatisticsAccumulator"; - - protected Logger log = LoggerFactory.getLogger(MiddlewareStatisticsAccumulator.class); - - protected AtomicLong startedTransactionsCount = new AtomicLong(); - protected AtomicLong committedTransactionsCount = new AtomicLong(); - protected AtomicLong rolledBackTransactionsCount = new AtomicLong(); - protected AtomicLong middlewareRequestsCount = new AtomicLong(); - protected AtomicLong cubaScheduledTasksCount = new AtomicLong(); - - protected Parameter dbConnectionPoolNumActive = new Parameter(); - protected Parameter dbConnectionPoolNumIdle = new Parameter(); - - protected Parameter activeTransactions = new Parameter(); - protected Parameter userSessions = new Parameter(); - - @Inject - protected GlobalConfig config; - - @Override - public void gatherParameters() { - super.gatherParameters(); - try { - activeTransactions.register(getActiveTransactionsCount()); - - MBeanServerConnection connection = ManagementFactory.getPlatformMBeanServer(); - String appName = getAppName(); - - dbConnectionPoolNumActive.register((int) connection.getAttribute( - new ObjectName(appName + ".cuba:type=StatisticsCounter"), "DbConnectionPoolNumActive")); - - dbConnectionPoolNumIdle.register((int) connection.getAttribute( - new ObjectName(appName + ".cuba:type=StatisticsCounter"), "DbConnectionPoolNumIdle")); - - userSessions.register((int) connection.getAttribute( - new ObjectName(appName + ".cuba:type=UserSessions"), "Count")); - - } catch (Exception e) { - log.warn("Unable to gather system statistics: " + e); - } - } - - protected String getAppName() { - return config.getWebContextName(); - } - - public void incStartedTransactionsCount() { - startedTransactionsCount.incrementAndGet(); - } - - public void incCommittedTransactionsCount() { - committedTransactionsCount.incrementAndGet(); - } - - public void incRolledBackTransactionsCount() { - rolledBackTransactionsCount.incrementAndGet(); - } - - public void incMiddlewareRequestsCount() { - middlewareRequestsCount.incrementAndGet(); - } - - public void incCubaScheduledTasksCount() { - cubaScheduledTasksCount.incrementAndGet(); - } - - public Long getActiveTransactionsCount() { - return (startedTransactionsCount.get() - committedTransactionsCount.get() - rolledBackTransactionsCount.get()); - } - - public Long getStartedTransactionsCount() { - return startedTransactionsCount.get(); - } - - public Long getCommittedTransactionsCount() { - return committedTransactionsCount.get(); - } - - public Long getRolledBackTransactionsCount() { - return rolledBackTransactionsCount.get(); - } - - public Long getMiddlewareRequestsCount() { - return middlewareRequestsCount.get(); - } - - public Long getCubaScheduledTasksCount() { - return cubaScheduledTasksCount.get(); - } - - public double getCubaScheduledTasksPerSecond() { - return getCubaScheduledTasksCount() / ((System.currentTimeMillis() - startTime) / 1000.0); - } - - public double getAvgDbConnectionPoolNumActive() { - return dbConnectionPoolNumActive.getValue(); - } - - public double getAvgDbConnectionPoolNumIdle() { - return dbConnectionPoolNumIdle.getValue(); - } - - public double getAvgActiveTransactionsCount() { - return activeTransactions.getValue(); - } - - public double getTransactionsPerSecond() { - return getStartedTransactionsCount() / ((System.currentTimeMillis() - startTime) / 1000.0); - } - - public double getAvgUserSessions() { - return userSessions.getValue(); - } - - public double getMiddlewareRequestsPerSecond() { - return getMiddlewareRequestsCount() / ((System.currentTimeMillis() - startTime) / 1000.0); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.StatisticsAccumulator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.concurrent.atomic.AtomicLong; + +@Component(MiddlewareStatisticsAccumulator.NAME) +public class MiddlewareStatisticsAccumulator extends StatisticsAccumulator { + + public static final String NAME = "cuba_MiddlewareStatisticsAccumulator"; + + protected Logger log = LoggerFactory.getLogger(MiddlewareStatisticsAccumulator.class); + + protected AtomicLong startedTransactionsCount = new AtomicLong(); + protected AtomicLong committedTransactionsCount = new AtomicLong(); + protected AtomicLong rolledBackTransactionsCount = new AtomicLong(); + protected AtomicLong middlewareRequestsCount = new AtomicLong(); + protected AtomicLong cubaScheduledTasksCount = new AtomicLong(); + + protected Parameter dbConnectionPoolNumActive = new Parameter(); + protected Parameter dbConnectionPoolNumIdle = new Parameter(); + + protected Parameter activeTransactions = new Parameter(); + protected Parameter userSessions = new Parameter(); + + @Inject + protected GlobalConfig config; + + @Override + public void gatherParameters() { + super.gatherParameters(); + try { + activeTransactions.register(getActiveTransactionsCount()); + + MBeanServerConnection connection = ManagementFactory.getPlatformMBeanServer(); + String appName = getAppName(); + + dbConnectionPoolNumActive.register((int) connection.getAttribute( + new ObjectName(appName + ".cuba:type=StatisticsCounter"), "DbConnectionPoolNumActive")); + + dbConnectionPoolNumIdle.register((int) connection.getAttribute( + new ObjectName(appName + ".cuba:type=StatisticsCounter"), "DbConnectionPoolNumIdle")); + + userSessions.register((int) connection.getAttribute( + new ObjectName(appName + ".cuba:type=UserSessions"), "Count")); + + } catch (Exception e) { + log.warn("Unable to gather system statistics: " + e); + } + } + + protected String getAppName() { + return config.getWebContextName(); + } + + public void incStartedTransactionsCount() { + startedTransactionsCount.incrementAndGet(); + } + + public void incCommittedTransactionsCount() { + committedTransactionsCount.incrementAndGet(); + } + + public void incRolledBackTransactionsCount() { + rolledBackTransactionsCount.incrementAndGet(); + } + + public void incMiddlewareRequestsCount() { + middlewareRequestsCount.incrementAndGet(); + } + + public void incCubaScheduledTasksCount() { + cubaScheduledTasksCount.incrementAndGet(); + } + + public Long getActiveTransactionsCount() { + return (startedTransactionsCount.get() - committedTransactionsCount.get() - rolledBackTransactionsCount.get()); + } + + public Long getStartedTransactionsCount() { + return startedTransactionsCount.get(); + } + + public Long getCommittedTransactionsCount() { + return committedTransactionsCount.get(); + } + + public Long getRolledBackTransactionsCount() { + return rolledBackTransactionsCount.get(); + } + + public Long getMiddlewareRequestsCount() { + return middlewareRequestsCount.get(); + } + + public Long getCubaScheduledTasksCount() { + return cubaScheduledTasksCount.get(); + } + + public double getCubaScheduledTasksPerSecond() { + return getCubaScheduledTasksCount() / ((System.currentTimeMillis() - startTime) / 1000.0); + } + + public double getAvgDbConnectionPoolNumActive() { + return dbConnectionPoolNumActive.getValue(); + } + + public double getAvgDbConnectionPoolNumIdle() { + return dbConnectionPoolNumIdle.getValue(); + } + + public double getAvgActiveTransactionsCount() { + return activeTransactions.getValue(); + } + + public double getTransactionsPerSecond() { + return getStartedTransactionsCount() / ((System.currentTimeMillis() - startTime) / 1000.0); + } + + public double getAvgUserSessions() { + return userSessions.getValue(); + } + + public double getMiddlewareRequestsPerSecond() { + return getMiddlewareRequestsCount() / ((System.currentTimeMillis() - startTime) / 1000.0); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/PersistenceConfig.java b/modules/core/src/com/haulmont/cuba/core/app/PersistenceConfig.java index a233c356a9..9371e705f8 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/PersistenceConfig.java +++ b/modules/core/src/com/haulmont/cuba/core/app/PersistenceConfig.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.DefaultInt; - -/** - * Configuration parameters interface used by some mechanisms related to data storage. - * - */ -@Source(type = SourceType.DATABASE) -public interface PersistenceConfig extends Config { - - /** - * @return Default maximum number of entity instances of certain type in database, after which lookup screen - * will be used instead of dropdown list for lookup. - */ - @Property("cuba.defaultLookupScreenThreshold") - @DefaultInt(100) - int getDefaultLookupScreenThreshold(); - void setDefaultLookupScreenThreshold(int value); - - /** - * @return Default maximum number of entity instances of certain type in database, after which a lazy - * collection datasource will be used. This parameter is taken into account only if entity statistics has been - * gathered and if the datasource has fetchMode="LAZY". - */ - @Property("cuba.defaultLazyCollectionThreshold") - @DefaultInt(100) - int getDefaultLazyCollectionThreshold(); - void setDefaultLazyCollectionThreshold(int value); - - /** - * @return Default number of entity instances to fetch from the database. This parameter affects some visual - * components working with datasources to show entity lists. - */ - @Property("cuba.defaultFetchUI") - @DefaultInt(50) - int getDefaultFetchUI(); - void setDefaultFetchUI(int value); - - /** - * @return Default maximum number of entity instances to fetch from the database. Each SELECT statement is - * automatically amended with an appropriate LIMIT clause. - */ - @Property("cuba.defaultMaxFetchUI") - @DefaultInt(10000) - int getDefaultMaxFetchUI(); - void setDefaultMaxFetchUI(int value); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.DefaultInt; + +/** + * Configuration parameters interface used by some mechanisms related to data storage. + * + */ +@Source(type = SourceType.DATABASE) +public interface PersistenceConfig extends Config { + + /** + * @return Default maximum number of entity instances of certain type in database, after which lookup screen + * will be used instead of dropdown list for lookup. + */ + @Property("cuba.defaultLookupScreenThreshold") + @DefaultInt(100) + int getDefaultLookupScreenThreshold(); + void setDefaultLookupScreenThreshold(int value); + + /** + * @return Default maximum number of entity instances of certain type in database, after which a lazy + * collection datasource will be used. This parameter is taken into account only if entity statistics has been + * gathered and if the datasource has fetchMode="LAZY". + */ + @Property("cuba.defaultLazyCollectionThreshold") + @DefaultInt(100) + int getDefaultLazyCollectionThreshold(); + void setDefaultLazyCollectionThreshold(int value); + + /** + * @return Default number of entity instances to fetch from the database. This parameter affects some visual + * components working with datasources to show entity lists. + */ + @Property("cuba.defaultFetchUI") + @DefaultInt(50) + int getDefaultFetchUI(); + void setDefaultFetchUI(int value); + + /** + * @return Default maximum number of entity instances to fetch from the database. Each SELECT statement is + * automatically amended with an appropriate LIMIT clause. + */ + @Property("cuba.defaultMaxFetchUI") + @DefaultInt(10000) + int getDefaultMaxFetchUI(); + void setDefaultMaxFetchUI(int value); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManager.java b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManager.java index df8199b546..ed31bb7f39 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManager.java @@ -1,358 +1,358 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.entity.EntityStatistics; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.Stores; -import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; -import com.haulmont.cuba.core.sys.persistence.DbmsType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; -import javax.persistence.JoinTable; -import javax.persistence.Table; -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -@Component(PersistenceManagerAPI.NAME) -public class PersistenceManager implements PersistenceManagerAPI { - - private final Logger log = LoggerFactory.getLogger(PersistenceManager.class); - - protected volatile Set softDeleteTables; - - protected volatile Set secondaryTables; - - protected Map statisticsCache; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected PersistenceSecurity security; - - protected PersistenceConfig config; - - @Inject - public void setConfiguration(Configuration configuration) { - config = configuration.getConfig(PersistenceConfig.class); - } - - @Override - public boolean isSoftDeleteFor(String table) { - if (softDeleteTables == null) { - initSoftDeleteTables(); - } - return softDeleteTables.contains(table.toLowerCase()); - } - - @Override - public List getSoftDeleteTables() { - if (softDeleteTables == null) { - initSoftDeleteTables(); - } - ArrayList list = new ArrayList<>(softDeleteTables); - Collections.sort(list); - return list; - } - - @Override - public boolean isSecondaryTable(String table) { - if (secondaryTables == null) { - initSecondaryTables(); - } - return secondaryTables.contains(table); - } - - protected synchronized void initSoftDeleteTables() { - if (softDeleteTables == null) { // double checked locking - log.debug("Searching for soft delete tables"); - HashSet set = new HashSet<>(); - - DataSource datasource = persistence.getDataSource(); - Connection conn = null; - try { - conn = datasource.getConnection(); - DatabaseMetaData metaData = conn.getMetaData(); - - String schema = "oracle".equals(DbmsType.getType()) ? metaData.getUserName() : null; - log.trace("[initSoftDeleteTables] schema=" + schema); - - ResultSet tables = metaData.getTables(null, schema, null, new String[]{"TABLE"}); - while (tables.next()) { - String table = tables.getString("TABLE_NAME"); - log.trace("[initSoftDeleteTables] found table " + table); - - if (table != null) { - String deleteTsColumn = DbmsSpecificFactory.getDbmsFeatures().getDeleteTsColumn(); - ResultSet columns = metaData.getColumns(null, schema, table, deleteTsColumn); - if (columns.next()) { - log.trace("[initSoftDeleteTables] table " + table + " has column " + deleteTsColumn); - set.add(table.toLowerCase()); - } - columns.close(); - } - } - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - try { - if (conn != null) conn.close(); - } catch (SQLException ignored) { - } - } - - softDeleteTables = set; - } - } - - protected synchronized void initSecondaryTables() { - if (secondaryTables == null) { // double checked locking - log.debug("Searching for secondary tables"); - HashSet set = new HashSet<>(); - - Collection metaClasses = metadata.getTools().getAllPersistentMetaClasses(); - for (MetaClass metaClass : metaClasses) { - for (MetaProperty metaProperty : metaClass.getProperties()) { - JoinTable joinTable = metaProperty.getAnnotatedElement().getAnnotation(JoinTable.class); - if (joinTable != null) { - set.add(joinTable.name()); - } - } - - if (isJoinTableInheritance(metaClass)) { - Table table = (Table) metaClass.getJavaClass().getAnnotation(Table.class); - if (table != null) { - set.add(table.name()); - } - } - } - - secondaryTables = set; - } - } - - private boolean isJoinTableInheritance(MetaClass metaClass) { - for (MetaClass aClass : metaClass.getAncestors()) { - Inheritance inheritance = (Inheritance) aClass.getJavaClass().getAnnotation(Inheritance.class); - if (inheritance != null && inheritance.strategy() == InheritanceType.JOINED) { - return true; - } - } - return false; - } - - @Override - public boolean useLazyCollection(String entityName) { - EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); - if (es == null || es.getInstanceCount() == null) - return false; - else { - int threshold = es.getLazyCollectionThreshold() != null ? es.getLazyCollectionThreshold() : config.getDefaultLazyCollectionThreshold(); - return es.getInstanceCount() > threshold; - } - } - - @Override - public boolean useLookupScreen(String entityName) { - EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); - if (es == null || es.getInstanceCount() == null) - return false; - else { - int threshold = es.getLookupScreenThreshold() != null ? es.getLookupScreenThreshold() : config.getDefaultLookupScreenThreshold(); - return es.getInstanceCount() > threshold; - } - } - - @Override - public int getFetchUI(String entityName) { - EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); - if (es != null && es.getFetchUI() != null) - return es.getFetchUI(); - else - return config.getDefaultFetchUI(); - } - - @Override - public int getMaxFetchUI(String entityName) { - EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); - if (es != null && es.getMaxFetchUI() != null) - return es.getMaxFetchUI(); - else - return config.getDefaultMaxFetchUI(); - } - - protected synchronized Map getStatisticsCache() { - if (statisticsCache == null) { - statisticsCache = new ConcurrentHashMap<>(); - internalLoadStatisticsCache(); - } - return statisticsCache; - } - - protected void internalLoadStatisticsCache() { - log.info("Loading statistics cache"); - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - TypedQuery q = em.createQuery("select s from sys$EntityStatistics s", EntityStatistics.class); - List list = q.getResultList(); - for (EntityStatistics es : list) { - statisticsCache.put(es.getName(), es); - } - tx.commit(); - } finally { - tx.end(); - } - } - - @Override - public synchronized void flushStatisticsCache() { - statisticsCache = null; - } - - @Override - public synchronized EntityStatistics enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, - Integer lazyCollectionThreshold, Integer lookupScreenThreshold) { - Transaction tx = persistence.createTransaction(); - EntityStatistics es; - try { - EntityManager em = persistence.getEntityManager(); - es = getEntityStatisticsInstance(getOriginalOrThisEntityName(name), em); - - if (instanceCount != null) { - es.setInstanceCount(instanceCount); - } - if (fetchUI != null) { - es.setFetchUI(fetchUI); - } - if (maxFetchUI != null) { - es.setMaxFetchUI(maxFetchUI); - } - if (lazyCollectionThreshold != null) { - es.setLazyCollectionThreshold(lazyCollectionThreshold); - } - if (lookupScreenThreshold != null) { - es.setLookupScreenThreshold(lookupScreenThreshold); - } - - tx.commit(); - } finally { - tx.end(); - } - flushStatisticsCache(); - return es; - } - - @Override - public SortedMap getEntityStatistics() { - return new TreeMap<>(getStatisticsCache()); - } - - @Override - public void deleteStatistics(String name) { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - Query q = em.createQuery("delete from sys$EntityStatistics s where s.name = ?1"); - q.setParameter(1, getOriginalOrThisEntityName(name)); - q.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - flushStatisticsCache(); - } - - @Override - public void refreshStatisticsForEntity(String name) { - log.debug("Refreshing statistics for entity " + name); - MetaClass metaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metadata.getClassNN(name)); - String storeName = metadata.getTools().getStoreName(metaClass); - if (storeName == null) { - log.debug("Entity " + name + " is not persistent, ignoring it"); - return; - } - Transaction tx = persistence.createTransaction(storeName); - try { - EntityManager em = persistence.getEntityManager(storeName); - - Query q = em.createQuery("select count(e) from " + name + " e"); - Long count = (Long) q.getSingleResult(); - - EntityStatistics entityStatistics; - if (Stores.isMain(storeName)) { - entityStatistics = getEntityStatisticsInstance(name, em); - entityStatistics.setInstanceCount(count); - } else { - entityStatistics = persistence.callInTransaction(mainDsEm -> { - EntityStatistics es = getEntityStatisticsInstance(name, mainDsEm); - es.setInstanceCount(count); - return es; - }); - } - getStatisticsCache().put(name, entityStatistics); - - tx.commit(); - } finally { - tx.end(); - } - } - - protected EntityStatistics getEntityStatisticsInstance(String name, EntityManager em) { - TypedQuery q = - em.createQuery("select s from sys$EntityStatistics s where s.name = ?1", EntityStatistics.class); - q.setParameter(1, name); - List list = q.getResultList(); - - EntityStatistics es; - if (list.isEmpty()) { - es = metadata.create(EntityStatistics.class); - es.setName(name); - em.persist(es); - } else { - es = list.get(0); - } - return es; - } - - protected String getOriginalOrThisEntityName(String entityName) { - MetaClass metaClass = metadata.getClass(entityName); - if (metaClass == null) { - return entityName; - } - return metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass).getName(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.entity.EntityStatistics; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.Stores; +import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; +import com.haulmont.cuba.core.sys.persistence.DbmsType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinTable; +import javax.persistence.Table; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Component(PersistenceManagerAPI.NAME) +public class PersistenceManager implements PersistenceManagerAPI { + + private final Logger log = LoggerFactory.getLogger(PersistenceManager.class); + + protected volatile Set softDeleteTables; + + protected volatile Set secondaryTables; + + protected Map statisticsCache; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected PersistenceSecurity security; + + protected PersistenceConfig config; + + @Inject + public void setConfiguration(Configuration configuration) { + config = configuration.getConfig(PersistenceConfig.class); + } + + @Override + public boolean isSoftDeleteFor(String table) { + if (softDeleteTables == null) { + initSoftDeleteTables(); + } + return softDeleteTables.contains(table.toLowerCase()); + } + + @Override + public List getSoftDeleteTables() { + if (softDeleteTables == null) { + initSoftDeleteTables(); + } + ArrayList list = new ArrayList<>(softDeleteTables); + Collections.sort(list); + return list; + } + + @Override + public boolean isSecondaryTable(String table) { + if (secondaryTables == null) { + initSecondaryTables(); + } + return secondaryTables.contains(table); + } + + protected synchronized void initSoftDeleteTables() { + if (softDeleteTables == null) { // double checked locking + log.debug("Searching for soft delete tables"); + HashSet set = new HashSet<>(); + + DataSource datasource = persistence.getDataSource(); + Connection conn = null; + try { + conn = datasource.getConnection(); + DatabaseMetaData metaData = conn.getMetaData(); + + String schema = "oracle".equals(DbmsType.getType()) ? metaData.getUserName() : null; + log.trace("[initSoftDeleteTables] schema=" + schema); + + ResultSet tables = metaData.getTables(null, schema, null, new String[]{"TABLE"}); + while (tables.next()) { + String table = tables.getString("TABLE_NAME"); + log.trace("[initSoftDeleteTables] found table " + table); + + if (table != null) { + String deleteTsColumn = DbmsSpecificFactory.getDbmsFeatures().getDeleteTsColumn(); + ResultSet columns = metaData.getColumns(null, schema, table, deleteTsColumn); + if (columns.next()) { + log.trace("[initSoftDeleteTables] table " + table + " has column " + deleteTsColumn); + set.add(table.toLowerCase()); + } + columns.close(); + } + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + if (conn != null) conn.close(); + } catch (SQLException ignored) { + } + } + + softDeleteTables = set; + } + } + + protected synchronized void initSecondaryTables() { + if (secondaryTables == null) { // double checked locking + log.debug("Searching for secondary tables"); + HashSet set = new HashSet<>(); + + Collection metaClasses = metadata.getTools().getAllPersistentMetaClasses(); + for (MetaClass metaClass : metaClasses) { + for (MetaProperty metaProperty : metaClass.getProperties()) { + JoinTable joinTable = metaProperty.getAnnotatedElement().getAnnotation(JoinTable.class); + if (joinTable != null) { + set.add(joinTable.name()); + } + } + + if (isJoinTableInheritance(metaClass)) { + Table table = (Table) metaClass.getJavaClass().getAnnotation(Table.class); + if (table != null) { + set.add(table.name()); + } + } + } + + secondaryTables = set; + } + } + + private boolean isJoinTableInheritance(MetaClass metaClass) { + for (MetaClass aClass : metaClass.getAncestors()) { + Inheritance inheritance = (Inheritance) aClass.getJavaClass().getAnnotation(Inheritance.class); + if (inheritance != null && inheritance.strategy() == InheritanceType.JOINED) { + return true; + } + } + return false; + } + + @Override + public boolean useLazyCollection(String entityName) { + EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); + if (es == null || es.getInstanceCount() == null) + return false; + else { + int threshold = es.getLazyCollectionThreshold() != null ? es.getLazyCollectionThreshold() : config.getDefaultLazyCollectionThreshold(); + return es.getInstanceCount() > threshold; + } + } + + @Override + public boolean useLookupScreen(String entityName) { + EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); + if (es == null || es.getInstanceCount() == null) + return false; + else { + int threshold = es.getLookupScreenThreshold() != null ? es.getLookupScreenThreshold() : config.getDefaultLookupScreenThreshold(); + return es.getInstanceCount() > threshold; + } + } + + @Override + public int getFetchUI(String entityName) { + EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); + if (es != null && es.getFetchUI() != null) + return es.getFetchUI(); + else + return config.getDefaultFetchUI(); + } + + @Override + public int getMaxFetchUI(String entityName) { + EntityStatistics es = getStatisticsCache().get(getOriginalOrThisEntityName(entityName)); + if (es != null && es.getMaxFetchUI() != null) + return es.getMaxFetchUI(); + else + return config.getDefaultMaxFetchUI(); + } + + protected synchronized Map getStatisticsCache() { + if (statisticsCache == null) { + statisticsCache = new ConcurrentHashMap<>(); + internalLoadStatisticsCache(); + } + return statisticsCache; + } + + protected void internalLoadStatisticsCache() { + log.info("Loading statistics cache"); + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + TypedQuery q = em.createQuery("select s from sys$EntityStatistics s", EntityStatistics.class); + List list = q.getResultList(); + for (EntityStatistics es : list) { + statisticsCache.put(es.getName(), es); + } + tx.commit(); + } finally { + tx.end(); + } + } + + @Override + public synchronized void flushStatisticsCache() { + statisticsCache = null; + } + + @Override + public synchronized EntityStatistics enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, + Integer lazyCollectionThreshold, Integer lookupScreenThreshold) { + Transaction tx = persistence.createTransaction(); + EntityStatistics es; + try { + EntityManager em = persistence.getEntityManager(); + es = getEntityStatisticsInstance(getOriginalOrThisEntityName(name), em); + + if (instanceCount != null) { + es.setInstanceCount(instanceCount); + } + if (fetchUI != null) { + es.setFetchUI(fetchUI); + } + if (maxFetchUI != null) { + es.setMaxFetchUI(maxFetchUI); + } + if (lazyCollectionThreshold != null) { + es.setLazyCollectionThreshold(lazyCollectionThreshold); + } + if (lookupScreenThreshold != null) { + es.setLookupScreenThreshold(lookupScreenThreshold); + } + + tx.commit(); + } finally { + tx.end(); + } + flushStatisticsCache(); + return es; + } + + @Override + public SortedMap getEntityStatistics() { + return new TreeMap<>(getStatisticsCache()); + } + + @Override + public void deleteStatistics(String name) { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + Query q = em.createQuery("delete from sys$EntityStatistics s where s.name = ?1"); + q.setParameter(1, getOriginalOrThisEntityName(name)); + q.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + flushStatisticsCache(); + } + + @Override + public void refreshStatisticsForEntity(String name) { + log.debug("Refreshing statistics for entity " + name); + MetaClass metaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metadata.getClassNN(name)); + String storeName = metadata.getTools().getStoreName(metaClass); + if (storeName == null) { + log.debug("Entity " + name + " is not persistent, ignoring it"); + return; + } + Transaction tx = persistence.createTransaction(storeName); + try { + EntityManager em = persistence.getEntityManager(storeName); + + Query q = em.createQuery("select count(e) from " + name + " e"); + Long count = (Long) q.getSingleResult(); + + EntityStatistics entityStatistics; + if (Stores.isMain(storeName)) { + entityStatistics = getEntityStatisticsInstance(name, em); + entityStatistics.setInstanceCount(count); + } else { + entityStatistics = persistence.callInTransaction(mainDsEm -> { + EntityStatistics es = getEntityStatisticsInstance(name, mainDsEm); + es.setInstanceCount(count); + return es; + }); + } + getStatisticsCache().put(name, entityStatistics); + + tx.commit(); + } finally { + tx.end(); + } + } + + protected EntityStatistics getEntityStatisticsInstance(String name, EntityManager em) { + TypedQuery q = + em.createQuery("select s from sys$EntityStatistics s where s.name = ?1", EntityStatistics.class); + q.setParameter(1, name); + List list = q.getResultList(); + + EntityStatistics es; + if (list.isEmpty()) { + es = metadata.create(EntityStatistics.class); + es.setName(name); + em.persist(es); + } else { + es = list.get(0); + } + return es; + } + + protected String getOriginalOrThisEntityName(String entityName) { + MetaClass metaClass = metadata.getClass(entityName); + if (metaClass == null) { + return entityName; + } + return metadata.getExtendedEntities().getOriginalOrThisMetaClass(metaClass).getName(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerAPI.java index d20ffbc642..8307fd8220 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerAPI.java @@ -1,89 +1,89 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.EntityStatistics; - -import java.util.List; -import java.util.SortedMap; - -/** - * Caches database metadata information and entity statistics. - * - */ -public interface PersistenceManagerAPI { - - String NAME = "cuba_PersistenceManager"; - - /** - * Whether this database table supports soft deletion. - * @param table table name - * @return true if this database table supports soft deletion - */ - boolean isSoftDeleteFor(String table); - - /** - * @return all soft delete tables sorted in alphabetical order - */ - List getSoftDeleteTables(); - - /** - * Checks whether the table provided is a ManyToMany link table or a secondary table in JOINED inheritance strategy. - * @param table table name - * @return true/false - */ - boolean isSecondaryTable(String table); - - /** - * Whether to use a lazy collection datasource for this entity, based on current statistics. - * @param entityName entity name - * @return true if lazy collection datasource should be used for this entity - */ - boolean useLazyCollection(String entityName); - - /** - * Whether to use a lookup screen or a dropdown for this entity, based on current statistics. - * @param entityName entity name - * @return true if lookup screen should be used - */ - boolean useLookupScreen(String entityName); - - /** - * Return a limit of rows fetched for UI components in 'normal' conditions - * @param entityName entity name - * @return maximum number of rows - */ - int getFetchUI(String entityName); - - /** - * Return the absolute maximum number of rows that can be fetched for UI components - * @param entityName entity name - * @return maximum number of rows - */ - int getMaxFetchUI(String entityName); - - void flushStatisticsCache(); - - void refreshStatisticsForEntity(String name); - - void deleteStatistics(String name); - - EntityStatistics enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, - Integer lazyCollectionThreshold, Integer lookupScreenThreshold); - - SortedMap getEntityStatistics(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.EntityStatistics; + +import java.util.List; +import java.util.SortedMap; + +/** + * Caches database metadata information and entity statistics. + * + */ +public interface PersistenceManagerAPI { + + String NAME = "cuba_PersistenceManager"; + + /** + * Whether this database table supports soft deletion. + * @param table table name + * @return true if this database table supports soft deletion + */ + boolean isSoftDeleteFor(String table); + + /** + * @return all soft delete tables sorted in alphabetical order + */ + List getSoftDeleteTables(); + + /** + * Checks whether the table provided is a ManyToMany link table or a secondary table in JOINED inheritance strategy. + * @param table table name + * @return true/false + */ + boolean isSecondaryTable(String table); + + /** + * Whether to use a lazy collection datasource for this entity, based on current statistics. + * @param entityName entity name + * @return true if lazy collection datasource should be used for this entity + */ + boolean useLazyCollection(String entityName); + + /** + * Whether to use a lookup screen or a dropdown for this entity, based on current statistics. + * @param entityName entity name + * @return true if lookup screen should be used + */ + boolean useLookupScreen(String entityName); + + /** + * Return a limit of rows fetched for UI components in 'normal' conditions + * @param entityName entity name + * @return maximum number of rows + */ + int getFetchUI(String entityName); + + /** + * Return the absolute maximum number of rows that can be fetched for UI components + * @param entityName entity name + * @return maximum number of rows + */ + int getMaxFetchUI(String entityName); + + void flushStatisticsCache(); + + void refreshStatisticsForEntity(String name); + + void deleteStatistics(String name); + + EntityStatistics enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, + Integer lazyCollectionThreshold, Integer lookupScreenThreshold); + + SortedMap getEntityStatistics(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerServiceBean.java index 0219e580dc..4f2bbe850d 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/PersistenceManagerServiceBean.java @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; -import com.haulmont.cuba.core.sys.persistence.DbmsType; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; - -@Service(PersistenceManagerService.NAME) -public class PersistenceManagerServiceBean implements PersistenceManagerService { - - @Inject - private PersistenceManagerAPI pm; - - @Override - public boolean useLazyCollection(String entityName) { - return pm.useLazyCollection(entityName); - } - - @Override - public boolean useLookupScreen(String entityName) { - return pm.useLookupScreen(entityName); - } - - @Override - public int getFetchUI(String entityName) { - return pm.getFetchUI(entityName); - } - - @Override - public int getMaxFetchUI(String entityName) { - return pm.getMaxFetchUI(entityName); - } - - @Override - public String getDbmsType() { - return DbmsType.getType(); - } - - @Override - public String getDbmsVersion() { - return DbmsType.getVersion(); - } - - @Override - public String getUniqueConstraintViolationPattern() { - return DbmsSpecificFactory.getDbmsFeatures().getUniqueConstraintViolationPattern(); - } - - @Override - public boolean isNullsLastSorting() { - return DbmsSpecificFactory.getDbmsFeatures().isNullsLastSorting(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; +import com.haulmont.cuba.core.sys.persistence.DbmsType; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; + +@Service(PersistenceManagerService.NAME) +public class PersistenceManagerServiceBean implements PersistenceManagerService { + + @Inject + private PersistenceManagerAPI pm; + + @Override + public boolean useLazyCollection(String entityName) { + return pm.useLazyCollection(entityName); + } + + @Override + public boolean useLookupScreen(String entityName) { + return pm.useLookupScreen(entityName); + } + + @Override + public int getFetchUI(String entityName) { + return pm.getFetchUI(entityName); + } + + @Override + public int getMaxFetchUI(String entityName) { + return pm.getMaxFetchUI(entityName); + } + + @Override + public String getDbmsType() { + return DbmsType.getType(); + } + + @Override + public String getDbmsVersion() { + return DbmsType.getVersion(); + } + + @Override + public String getUniqueConstraintViolationPattern() { + return DbmsSpecificFactory.getDbmsFeatures().getUniqueConstraintViolationPattern(); + } + + @Override + public boolean isNullsLastSorting() { + return DbmsSpecificFactory.getDbmsFeatures().isNullsLastSorting(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/QueryResultsServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/QueryResultsServiceBean.java index a96ca0d794..b434a77bff 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/QueryResultsServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/QueryResultsServiceBean.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.app.queryresults.QueryResultsManagerAPI; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.List; -import java.util.UUID; - -@Service(QueryResultsService.NAME) -public class QueryResultsServiceBean implements QueryResultsService { - - @Inject - protected QueryResultsManagerAPI queryResultsManagerAPI; - - @Override - public void insert(int queryKey, List idList) { - queryResultsManagerAPI.insert(queryKey, idList); - } - - @Override - public void delete(int queryKey) { - queryResultsManagerAPI.delete(queryKey); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.app.queryresults.QueryResultsManagerAPI; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.List; +import java.util.UUID; + +@Service(QueryResultsService.NAME) +public class QueryResultsServiceBean implements QueryResultsService { + + @Inject + protected QueryResultsManagerAPI queryResultsManagerAPI; + + @Override + public void insert(int queryKey, List idList) { + queryResultsManagerAPI.insert(queryKey, idList); + } + + @Override + public void delete(int queryKey) { + queryResultsManagerAPI.delete(queryKey); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ScreenHistory.java b/modules/core/src/com/haulmont/cuba/core/app/ScreenHistory.java index cc836fca9c..e5d44d6c3d 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ScreenHistory.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ScreenHistory.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -/** - * Provides some functionality for history of opened screens. - * - */ -public interface ScreenHistory { - - String NAME = "cuba_ScreenHistory"; - - int MAX_RECORDS = 100; - - void cleanup(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +/** + * Provides some functionality for history of opened screens. + * + */ +public interface ScreenHistory { + + String NAME = "cuba_ScreenHistory"; + + int MAX_RECORDS = 100; + + void cleanup(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/ScreenHistoryBean.java b/modules/core/src/com/haulmont/cuba/core/app/ScreenHistoryBean.java index 0585c11aef..d7a0270f7f 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ScreenHistoryBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ScreenHistoryBean.java @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.sys.AppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.util.List; -import java.util.UUID; - -@Component(ScreenHistory.NAME) -public class ScreenHistoryBean implements ScreenHistory { - - private Logger log = LoggerFactory.getLogger(ScreenHistoryBean.class); - - private static final int DELETE_BATCH = 10; - - @Inject - protected Persistence persistence; - - @Override - public void cleanup() { - if (!AppContext.isStarted()) - return; - - log.debug("Cleanup screen history"); - Transaction tx = persistence.createTransaction(); - try { - Query q = persistence.getEntityManager().createQuery("select h.user.id, count(h.id) " + - "from sec$ScreenHistory h group by h.user.id having count(h.id) > ?1"); - q.setParameter(1, MAX_RECORDS); - List userList = q.getResultList(); - tx.commitRetaining(); - - for (Object[] row : userList) { - UUID userId = (UUID) row[0]; - - TypedQuery idQuery = persistence.getEntityManager().createQuery( - "select h.id from sec$ScreenHistory h where h.user.id = ?1 order by h.createTs desc", UUID.class); - idQuery.setParameter(1, userId); - List list = idQuery.getResultList(); - - int start = MAX_RECORDS; - int end = Math.min(start + DELETE_BATCH, list.size()); - while (start < list.size()) { - List toDelete = list.subList(start, end); - - Query deleteQuery = persistence.getEntityManager().createQuery( - "delete from sec$ScreenHistory h where h.id in ?1"); - deleteQuery.setParameter(1, toDelete); - deleteQuery.executeUpdate(); - tx.commitRetaining(); - - start = end; - end = Math.min(start + DELETE_BATCH, list.size()); - } - } - tx.commit(); - } finally { - tx.end(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.sys.AppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.util.List; +import java.util.UUID; + +@Component(ScreenHistory.NAME) +public class ScreenHistoryBean implements ScreenHistory { + + private Logger log = LoggerFactory.getLogger(ScreenHistoryBean.class); + + private static final int DELETE_BATCH = 10; + + @Inject + protected Persistence persistence; + + @Override + public void cleanup() { + if (!AppContext.isStarted()) + return; + + log.debug("Cleanup screen history"); + Transaction tx = persistence.createTransaction(); + try { + Query q = persistence.getEntityManager().createQuery("select h.user.id, count(h.id) " + + "from sec$ScreenHistory h group by h.user.id having count(h.id) > ?1"); + q.setParameter(1, MAX_RECORDS); + List userList = q.getResultList(); + tx.commitRetaining(); + + for (Object[] row : userList) { + UUID userId = (UUID) row[0]; + + TypedQuery idQuery = persistence.getEntityManager().createQuery( + "select h.id from sec$ScreenHistory h where h.user.id = ?1 order by h.createTs desc", UUID.class); + idQuery.setParameter(1, userId); + List list = idQuery.getResultList(); + + int start = MAX_RECORDS; + int end = Math.min(start + DELETE_BATCH, list.size()); + while (start < list.size()) { + List toDelete = list.subList(start, end); + + Query deleteQuery = persistence.getEntityManager().createQuery( + "delete from sec$ScreenHistory h where h.id in ?1"); + deleteQuery.setParameter(1, toDelete); + deleteQuery.executeUpdate(); + tx.commitRetaining(); + + start = end; + end = Math.min(start + DELETE_BATCH, list.size()); + } + } + tx.commit(); + } finally { + tx.end(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ServerConfig.java b/modules/core/src/com/haulmont/cuba/core/app/ServerConfig.java index 7e4ab9620c..ccda3404fa 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ServerConfig.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ServerConfig.java @@ -1,264 +1,264 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.*; - -/** - * Configuration parameters interface used by the CORE layer. - */ -@Source(type = SourceType.APP) -public interface ServerConfig extends Config { - - String SYNC_NEW_USER_SESSION_REPLICATION_PROP = "cuba.syncNewUserSessionReplication"; - - /** - * @return URL of a user session provider - usually the main middleware unit. - * This URL is used by middleware units which don't login themselves but get existing sessions from the main app. - */ - @Property("cuba.userSessionProviderUrl") - String getUserSessionProviderUrl(); - - /** - * @return Password used by LoginService.loginTrusted() method. - * Trusted client may login without providing a user password. This is used for external authentication. - * - *

Must be equal to password set for the same property on the client.

- */ - @Property("cuba.trustedClientPassword") - @DefaultString("") - String getTrustedClientPassword(); - - @Property("cuba.trustedClientPermittedIpList") - @DefaultString("127.0.0.1,0:0:0:0:0:0:0:1") - @Source(type = SourceType.DATABASE) - String getTrustedClientPermittedIpList(); - - @Property("cuba.security.resetPasswordTemplateBody") - @Default("/com/haulmont/cuba/security/app/email/reset-password-body.gsp") - String getResetPasswordEmailBodyTemplate(); - - @Property("cuba.security.resetPasswordTemplateSubject") - @Default("/com/haulmont/cuba/security/app/email/reset-password-subject.gsp") - String getResetPasswordEmailSubjectTemplate(); - - /** - * @return User session expiration timeout in seconds. - * Not the same as HTTP session timeout, but should have the same value. - */ - @Property("cuba.userSessionExpirationTimeoutSec") - @DefaultInt(1800) - int getUserSessionExpirationTimeoutSec(); - void setUserSessionExpirationTimeoutSec(int timeout); - - /** - * @return User session ping timeout in cluster. - * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, user session sends in cluster only after sendTimeout - */ - @Property("cuba.userSessionSendTimeoutSec") - @DefaultInt(10) - int getUserSessionSendTimeoutSec(); - void setUserSessionSendTimeoutSec(int timeout); - - /** - * @return DB scripts directory. - * Does not end with "/" - */ - @Property("cuba.dbDir") - String getDbDir(); - - /** - * @return Whether the server should try to init/update database on each startup. - */ - @Property("cuba.automaticDatabaseUpdate") - @DefaultBoolean(false) - boolean getAutomaticDatabaseUpdate(); - - /** - * @return {@link FileStorageAPI} storage directory. If not set, cuba.dataDir/filestorage will be used. - */ - @Property("cuba.fileStorageDir") - String getFileStorageDir(); - - /** - * An immutable file storage throws exception on attempt to write an existing file. - * - * @return whether file storage is immutable. - */ - @Property("cuba.immutableFileStorage") - @DefaultBoolean(true) - boolean getImmutableFileStorage(); - - /** - * @return Scheduled tasks execution control. - */ - @Property("cuba.schedulingActive") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getSchedulingActive(); - void setSchedulingActive(boolean value); - - /** - * @return Scheduled tasks execution control. - */ - @Property("cuba.schedulingInterval") - @Source(type = SourceType.DATABASE) - @DefaultLong(1000) - long getSchedulingInterval(); - void setSchedulingInterval(long value); - - /** - * @return Maximum size of thread pool which is used to process scheduled tasks - */ - @Property("cuba.schedulingThreadPoolSize") - @DefaultInt(10) - int getSchedulingThreadPoolSize(); - void setSchedulingThreadPoolSize(int value); - - /** - * @return Tells DataService to ensure distinct results by processing them in memory, instead of issue - * 'select distinct' to the database. - */ - @Property("cuba.inMemoryDistinct") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getInMemoryDistinct(); - void setInMemoryDistinct(boolean value); - - /** - * @return Default database query timeout in seconds. If 0, middleware doesn't apply any timeout to queries. - */ - @Property("cuba.defaultQueryTimeoutSec") - @Source(type = SourceType.DATABASE) - @DefaultInt(0) - int getDefaultQueryTimeoutSec(); - void setDefaultQueryTimeoutSec(int timeout); - - /** - * Indicates that a new user session created on login should be sent to the cluster synchronously. - */ - @Property(SYNC_NEW_USER_SESSION_REPLICATION_PROP) - @DefaultBoolean(false) - boolean getSyncNewUserSessionReplication(); - - /** - * If set to false, attribute permissions are not enforced on Middleware. This is appropriate if only server-side - * clients are used. - */ - @Property("cuba.entityAttributePermissionChecking") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getEntityAttributePermissionChecking(); - - /** - * If set to true and query loading values is affected by security constraints, an exception is thrown - */ - @Property("cuba.disableLoadValuesIfConstraints") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getDisableLoadValuesIfConstraints(); - - /** - * <= 16 symbols string, used as key for AES encryption of security token - */ - @Property("cuba.keyForSecurityTokenEncryption") - @DefaultString("CUBA.Platform") - String getKeyForSecurityTokenEncryption(); - - /** - * Indicates that {@code DataManager} should always apply security restrictions on the middleware. - */ - @Property("cuba.dataManagerChecksSecurityOnMiddleware") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getDataManagerChecksSecurityOnMiddleware(); - - /** - * Whether the brute-force protection on user login is enabled. - */ - @Property("cuba.bruteForceProtection.enabled") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getBruteForceProtectionEnabled(); - - /** - * @return a maximum number of unsuccessful login attempts - */ - @Property("cuba.bruteForceProtection.maxLoginAttemptsNumber") - @Source(type = SourceType.DATABASE) - @DefaultInt(5) - int getMaxLoginAttemptsNumber(); - - /** - * @return a time interval in seconds for which a user is blocked after a series of - * unsuccessful login attempts - */ - @Property("cuba.bruteForceProtection.blockIntervalSec") - @Source(type = SourceType.DATABASE) - @DefaultInt(60) - int getBruteForceBlockIntervalSec(); - - /** - * Login name of the anonymous user. - */ - @Property("cuba.anonymousLogin") - @Source(type = SourceType.DATABASE) - @Default("anonymous") - String getAnonymousLogin(); - - /** - * Login name which is used by default in system authentication - */ - @Property("cuba.jmxUserLogin") - @Default("admin") - String getJmxUserLogin(); - - /** - * Warning in the log when a service is invoked from inside middleware. - */ - @Property("cuba.logInternalServiceInvocation") - @DefaultBoolean(false) - boolean getLogInternalServiceInvocation(); - - /** - * @return batch size for loading related entities from different data stores - */ - @Property("cuba.crossDataStoreReferenceLoadingBatchSize") - @Source(type = SourceType.DATABASE) - @DefaultInt(50) - int getCrossDataStoreReferenceLoadingBatchSize(); - - /** - * @return use read-only transactions in {@code DataManager} load operations and do not commit them - */ - @Property("cuba.useReadOnlyTransactionForLoad") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getUseReadOnlyTransactionForLoad(); - - /** - * @return whether to store REST API OAuth tokens in the database - */ - @Property("cuba.rest.storeTokensInDb") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getRestStoreTokensInDb(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.*; + +/** + * Configuration parameters interface used by the CORE layer. + */ +@Source(type = SourceType.APP) +public interface ServerConfig extends Config { + + String SYNC_NEW_USER_SESSION_REPLICATION_PROP = "cuba.syncNewUserSessionReplication"; + + /** + * @return URL of a user session provider - usually the main middleware unit. + * This URL is used by middleware units which don't login themselves but get existing sessions from the main app. + */ + @Property("cuba.userSessionProviderUrl") + String getUserSessionProviderUrl(); + + /** + * @return Password used by LoginService.loginTrusted() method. + * Trusted client may login without providing a user password. This is used for external authentication. + * + *

Must be equal to password set for the same property on the client.

+ */ + @Property("cuba.trustedClientPassword") + @DefaultString("") + String getTrustedClientPassword(); + + @Property("cuba.trustedClientPermittedIpList") + @DefaultString("127.0.0.1,0:0:0:0:0:0:0:1") + @Source(type = SourceType.DATABASE) + String getTrustedClientPermittedIpList(); + + @Property("cuba.security.resetPasswordTemplateBody") + @Default("/com/haulmont/cuba/security/app/email/reset-password-body.gsp") + String getResetPasswordEmailBodyTemplate(); + + @Property("cuba.security.resetPasswordTemplateSubject") + @Default("/com/haulmont/cuba/security/app/email/reset-password-subject.gsp") + String getResetPasswordEmailSubjectTemplate(); + + /** + * @return User session expiration timeout in seconds. + * Not the same as HTTP session timeout, but should have the same value. + */ + @Property("cuba.userSessionExpirationTimeoutSec") + @DefaultInt(1800) + int getUserSessionExpirationTimeoutSec(); + void setUserSessionExpirationTimeoutSec(int timeout); + + /** + * @return User session ping timeout in cluster. + * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, user session sends in cluster only after sendTimeout + */ + @Property("cuba.userSessionSendTimeoutSec") + @DefaultInt(10) + int getUserSessionSendTimeoutSec(); + void setUserSessionSendTimeoutSec(int timeout); + + /** + * @return DB scripts directory. + * Does not end with "/" + */ + @Property("cuba.dbDir") + String getDbDir(); + + /** + * @return Whether the server should try to init/update database on each startup. + */ + @Property("cuba.automaticDatabaseUpdate") + @DefaultBoolean(false) + boolean getAutomaticDatabaseUpdate(); + + /** + * @return {@link FileStorageAPI} storage directory. If not set, cuba.dataDir/filestorage will be used. + */ + @Property("cuba.fileStorageDir") + String getFileStorageDir(); + + /** + * An immutable file storage throws exception on attempt to write an existing file. + * + * @return whether file storage is immutable. + */ + @Property("cuba.immutableFileStorage") + @DefaultBoolean(true) + boolean getImmutableFileStorage(); + + /** + * @return Scheduled tasks execution control. + */ + @Property("cuba.schedulingActive") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getSchedulingActive(); + void setSchedulingActive(boolean value); + + /** + * @return Scheduled tasks execution control. + */ + @Property("cuba.schedulingInterval") + @Source(type = SourceType.DATABASE) + @DefaultLong(1000) + long getSchedulingInterval(); + void setSchedulingInterval(long value); + + /** + * @return Maximum size of thread pool which is used to process scheduled tasks + */ + @Property("cuba.schedulingThreadPoolSize") + @DefaultInt(10) + int getSchedulingThreadPoolSize(); + void setSchedulingThreadPoolSize(int value); + + /** + * @return Tells DataService to ensure distinct results by processing them in memory, instead of issue + * 'select distinct' to the database. + */ + @Property("cuba.inMemoryDistinct") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getInMemoryDistinct(); + void setInMemoryDistinct(boolean value); + + /** + * @return Default database query timeout in seconds. If 0, middleware doesn't apply any timeout to queries. + */ + @Property("cuba.defaultQueryTimeoutSec") + @Source(type = SourceType.DATABASE) + @DefaultInt(0) + int getDefaultQueryTimeoutSec(); + void setDefaultQueryTimeoutSec(int timeout); + + /** + * Indicates that a new user session created on login should be sent to the cluster synchronously. + */ + @Property(SYNC_NEW_USER_SESSION_REPLICATION_PROP) + @DefaultBoolean(false) + boolean getSyncNewUserSessionReplication(); + + /** + * If set to false, attribute permissions are not enforced on Middleware. This is appropriate if only server-side + * clients are used. + */ + @Property("cuba.entityAttributePermissionChecking") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getEntityAttributePermissionChecking(); + + /** + * If set to true and query loading values is affected by security constraints, an exception is thrown + */ + @Property("cuba.disableLoadValuesIfConstraints") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getDisableLoadValuesIfConstraints(); + + /** + * <= 16 symbols string, used as key for AES encryption of security token + */ + @Property("cuba.keyForSecurityTokenEncryption") + @DefaultString("CUBA.Platform") + String getKeyForSecurityTokenEncryption(); + + /** + * Indicates that {@code DataManager} should always apply security restrictions on the middleware. + */ + @Property("cuba.dataManagerChecksSecurityOnMiddleware") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getDataManagerChecksSecurityOnMiddleware(); + + /** + * Whether the brute-force protection on user login is enabled. + */ + @Property("cuba.bruteForceProtection.enabled") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getBruteForceProtectionEnabled(); + + /** + * @return a maximum number of unsuccessful login attempts + */ + @Property("cuba.bruteForceProtection.maxLoginAttemptsNumber") + @Source(type = SourceType.DATABASE) + @DefaultInt(5) + int getMaxLoginAttemptsNumber(); + + /** + * @return a time interval in seconds for which a user is blocked after a series of + * unsuccessful login attempts + */ + @Property("cuba.bruteForceProtection.blockIntervalSec") + @Source(type = SourceType.DATABASE) + @DefaultInt(60) + int getBruteForceBlockIntervalSec(); + + /** + * Login name of the anonymous user. + */ + @Property("cuba.anonymousLogin") + @Source(type = SourceType.DATABASE) + @Default("anonymous") + String getAnonymousLogin(); + + /** + * Login name which is used by default in system authentication + */ + @Property("cuba.jmxUserLogin") + @Default("admin") + String getJmxUserLogin(); + + /** + * Warning in the log when a service is invoked from inside middleware. + */ + @Property("cuba.logInternalServiceInvocation") + @DefaultBoolean(false) + boolean getLogInternalServiceInvocation(); + + /** + * @return batch size for loading related entities from different data stores + */ + @Property("cuba.crossDataStoreReferenceLoadingBatchSize") + @Source(type = SourceType.DATABASE) + @DefaultInt(50) + int getCrossDataStoreReferenceLoadingBatchSize(); + + /** + * @return use read-only transactions in {@code DataManager} load operations and do not commit them + */ + @Property("cuba.useReadOnlyTransactionForLoad") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getUseReadOnlyTransactionForLoad(); + + /** + * @return whether to store REST API OAuth tokens in the database + */ + @Property("cuba.rest.storeTokensInDb") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getRestStoreTokensInDb(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ServerInfo.java b/modules/core/src/com/haulmont/cuba/core/app/ServerInfo.java index 5489ea7d19..aa1b56137e 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ServerInfo.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ServerInfo.java @@ -1,202 +1,202 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.global.UuidSource; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.persistence.DbTypeConverter; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.sql.Types; -import java.util.Date; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; - -@Component(ServerInfoAPI.NAME) -public class ServerInfo implements ServerInfoAPI, AppContext.Listener, Ordered { - - public static final String CUBA_RELEASE_NUMBER_PATH = "/com/haulmont/cuba/core/global/release.number"; - public static final String CUBA_RELEASE_TIMESTAMP_PATH = "/com/haulmont/cuba/core/global/release.timestamp"; - - protected Logger log = LoggerFactory.getLogger(ServerInfo.class); - - protected String releaseNumber = "?"; - protected String releaseTimestamp = "?"; - - protected Configuration configuration; - - protected volatile String serverId; - - protected GlobalConfig globalConfig; - - @Inject - protected TimeSource timeSource; - - @Inject - protected Persistence persistence; - - @Inject - protected UuidSource uuidSource; - - protected Timer infoUpdateTimer; - - public ServerInfo() { - AppContext.addListener(this); - } - - @Inject - public void setConfiguration(Configuration configuration) { - this.configuration = configuration; - - InputStream stream = getClass().getResourceAsStream(CUBA_RELEASE_NUMBER_PATH); - if (stream != null) { - try { - releaseNumber = IOUtils.toString(stream, StandardCharsets.UTF_8); - } catch (IOException e) { - log.warn("Unable to read release number", e); - } - } - - stream = getClass().getResourceAsStream(CUBA_RELEASE_TIMESTAMP_PATH); - if (stream != null) { - try { - releaseTimestamp = IOUtils.toString(stream, StandardCharsets.UTF_8); - } catch (IOException e) { - log.warn("Unable to read release timestamp", e); - } - } - - globalConfig = configuration.getConfig(GlobalConfig.class); - } - - @Override - public String getReleaseNumber() { - return releaseNumber; - } - - @Override - public String getReleaseTimestamp() { - return releaseTimestamp; - } - - @Override - public String getServerId() { - if (serverId == null) { - GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); - serverId = globalConfig.getWebHostName() + ":" + globalConfig.getWebPort() + "/" + globalConfig.getWebContextName(); - } - return serverId; - } - - @Override - public void applicationStarted() { - if (!globalConfig.getTestMode()) { - infoUpdateTimer = new Timer(true); - infoUpdateTimer.schedule( - new TimerTask() { - @Override - public void run() { - Thread.currentThread().setName("ServerInfoTimer"); - - if (AppContext.isStarted()) { - updateCurrentServer(); - } - } - }, - 30000, - 60000 - ); - } - } - - @Override - public void applicationStopped() { - try { - infoUpdateTimer.cancel(); - infoUpdateTimer.purge(); - - log.trace("Updating server information in the database"); - - DbTypeConverter types = persistence.getDbTypeConverter(); - Object tsObj = types.getSqlObject(timeSource.currentTimestamp()); - int tsType = types.getSqlType(Date.class); - Object falseObj = types.getSqlObject(Boolean.FALSE); - int boolType = types.getSqlType(Boolean.class); - - QueryRunner runner = new QueryRunner(persistence.getDataSource()); - runner.update( - "update SYS_SERVER set UPDATE_TS = ?, IS_RUNNING = ? where NAME = ?", - new Object[]{tsObj, falseObj, getServerId()}, - new int[]{tsType, boolType, Types.VARCHAR} - ); - } catch (Exception e) { - log.error("Unable to update SYS_SERVER: {}", e); - } - } - - protected void updateCurrentServer() { - try { - log.trace("Updating server information in the database"); - String serverId = getServerId(); - - DbTypeConverter types = persistence.getDbTypeConverter(); - Object tsObj = types.getSqlObject(timeSource.currentTimestamp()); - int tsType = types.getSqlType(Date.class); - Object trueObj = types.getSqlObject(Boolean.TRUE); - int boolType = types.getSqlType(Boolean.class); - - QueryRunner runner = new QueryRunner(persistence.getDataSource()); - - int updated = runner.update( - "update SYS_SERVER set UPDATE_TS = ?, IS_RUNNING = ? where NAME = ?", - new Object[]{tsObj, trueObj, serverId}, - new int[]{tsType, boolType, Types.VARCHAR} - ); - if (updated == 0) { - Object id = types.getSqlObject(uuidSource.createUuid()); - int idType = types.getSqlType(UUID.class); - runner.update( - "insert into SYS_SERVER (ID, CREATE_TS, UPDATE_TS, NAME, IS_RUNNING) " + - "values (?, ?, ?, ?, ?)", - new Object[]{id, tsObj, tsObj, serverId, trueObj}, - new int[]{idType, tsType, tsType, Types.VARCHAR, boolType} - ); - } - } catch (Exception e) { - log.error("Unable to update SYS_SERVER: {}", e.toString()); - } - } - - @Override - public int getOrder() { - return HIGHEST_PLATFORM_PRECEDENCE + 10; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.global.UuidSource; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.persistence.DbTypeConverter; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.sql.Types; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; + +@Component(ServerInfoAPI.NAME) +public class ServerInfo implements ServerInfoAPI, AppContext.Listener, Ordered { + + public static final String CUBA_RELEASE_NUMBER_PATH = "/com/haulmont/cuba/core/global/release.number"; + public static final String CUBA_RELEASE_TIMESTAMP_PATH = "/com/haulmont/cuba/core/global/release.timestamp"; + + protected Logger log = LoggerFactory.getLogger(ServerInfo.class); + + protected String releaseNumber = "?"; + protected String releaseTimestamp = "?"; + + protected Configuration configuration; + + protected volatile String serverId; + + protected GlobalConfig globalConfig; + + @Inject + protected TimeSource timeSource; + + @Inject + protected Persistence persistence; + + @Inject + protected UuidSource uuidSource; + + protected Timer infoUpdateTimer; + + public ServerInfo() { + AppContext.addListener(this); + } + + @Inject + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + + InputStream stream = getClass().getResourceAsStream(CUBA_RELEASE_NUMBER_PATH); + if (stream != null) { + try { + releaseNumber = IOUtils.toString(stream, StandardCharsets.UTF_8); + } catch (IOException e) { + log.warn("Unable to read release number", e); + } + } + + stream = getClass().getResourceAsStream(CUBA_RELEASE_TIMESTAMP_PATH); + if (stream != null) { + try { + releaseTimestamp = IOUtils.toString(stream, StandardCharsets.UTF_8); + } catch (IOException e) { + log.warn("Unable to read release timestamp", e); + } + } + + globalConfig = configuration.getConfig(GlobalConfig.class); + } + + @Override + public String getReleaseNumber() { + return releaseNumber; + } + + @Override + public String getReleaseTimestamp() { + return releaseTimestamp; + } + + @Override + public String getServerId() { + if (serverId == null) { + GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); + serverId = globalConfig.getWebHostName() + ":" + globalConfig.getWebPort() + "/" + globalConfig.getWebContextName(); + } + return serverId; + } + + @Override + public void applicationStarted() { + if (!globalConfig.getTestMode()) { + infoUpdateTimer = new Timer(true); + infoUpdateTimer.schedule( + new TimerTask() { + @Override + public void run() { + Thread.currentThread().setName("ServerInfoTimer"); + + if (AppContext.isStarted()) { + updateCurrentServer(); + } + } + }, + 30000, + 60000 + ); + } + } + + @Override + public void applicationStopped() { + try { + infoUpdateTimer.cancel(); + infoUpdateTimer.purge(); + + log.trace("Updating server information in the database"); + + DbTypeConverter types = persistence.getDbTypeConverter(); + Object tsObj = types.getSqlObject(timeSource.currentTimestamp()); + int tsType = types.getSqlType(Date.class); + Object falseObj = types.getSqlObject(Boolean.FALSE); + int boolType = types.getSqlType(Boolean.class); + + QueryRunner runner = new QueryRunner(persistence.getDataSource()); + runner.update( + "update SYS_SERVER set UPDATE_TS = ?, IS_RUNNING = ? where NAME = ?", + new Object[]{tsObj, falseObj, getServerId()}, + new int[]{tsType, boolType, Types.VARCHAR} + ); + } catch (Exception e) { + log.error("Unable to update SYS_SERVER: {}", e); + } + } + + protected void updateCurrentServer() { + try { + log.trace("Updating server information in the database"); + String serverId = getServerId(); + + DbTypeConverter types = persistence.getDbTypeConverter(); + Object tsObj = types.getSqlObject(timeSource.currentTimestamp()); + int tsType = types.getSqlType(Date.class); + Object trueObj = types.getSqlObject(Boolean.TRUE); + int boolType = types.getSqlType(Boolean.class); + + QueryRunner runner = new QueryRunner(persistence.getDataSource()); + + int updated = runner.update( + "update SYS_SERVER set UPDATE_TS = ?, IS_RUNNING = ? where NAME = ?", + new Object[]{tsObj, trueObj, serverId}, + new int[]{tsType, boolType, Types.VARCHAR} + ); + if (updated == 0) { + Object id = types.getSqlObject(uuidSource.createUuid()); + int idType = types.getSqlType(UUID.class); + runner.update( + "insert into SYS_SERVER (ID, CREATE_TS, UPDATE_TS, NAME, IS_RUNNING) " + + "values (?, ?, ?, ?, ?)", + new Object[]{id, tsObj, tsObj, serverId, trueObj}, + new int[]{idType, tsType, tsType, Types.VARCHAR, boolType} + ); + } + } catch (Exception e) { + log.error("Unable to update SYS_SERVER: {}", e.toString()); + } + } + + @Override + public int getOrder() { + return HIGHEST_PLATFORM_PRECEDENCE + 10; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/ServerInfoServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/ServerInfoServiceBean.java index 2c0314907d..dbdebe65e2 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/ServerInfoServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/ServerInfoServiceBean.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.core.global.ViewNotFoundException; -import com.haulmont.cuba.core.global.ViewRepository; -import com.haulmont.cuba.core.sys.AbstractViewRepository; -import com.haulmont.cuba.core.sys.MetadataBuildSupport; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.util.List; -import java.util.TimeZone; - -/** - * Standard implementation of {@link ServerInfoService} interface. - * - *

Annotated with @Component instead of @Service to be available before user login.

- * - */ -@Component(ServerInfoService.NAME) -public class ServerInfoServiceBean implements ServerInfoService { - - @Inject - protected ViewRepository viewRepository; - - @Inject - protected ServerInfoAPI serverInfo; - - @Inject - private MetadataBuildSupport metadataBuildSupport; - - @Inject - protected TimeSource timeSource; - - @Override - public String getReleaseNumber() { - return serverInfo.getReleaseNumber(); - } - - @Override - public String getReleaseTimestamp() { - return serverInfo.getReleaseTimestamp(); - } - - @Override - public List getViews() { - return ((AbstractViewRepository) viewRepository).getAll(); - } - - @Override - public View getView(Class entityClass, String name) { - try { - return viewRepository.getView(entityClass, name); - } catch (ViewNotFoundException e) { - return null; - } - } - - @Override - public TimeZone getTimeZone() { - return TimeZone.getDefault(); - } - - @Override - public long getTimeMillis() { - return timeSource.currentTimeMillis(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.core.global.ViewNotFoundException; +import com.haulmont.cuba.core.global.ViewRepository; +import com.haulmont.cuba.core.sys.AbstractViewRepository; +import com.haulmont.cuba.core.sys.MetadataBuildSupport; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.util.List; +import java.util.TimeZone; + +/** + * Standard implementation of {@link ServerInfoService} interface. + * + *

Annotated with @Component instead of @Service to be available before user login.

+ * + */ +@Component(ServerInfoService.NAME) +public class ServerInfoServiceBean implements ServerInfoService { + + @Inject + protected ViewRepository viewRepository; + + @Inject + protected ServerInfoAPI serverInfo; + + @Inject + private MetadataBuildSupport metadataBuildSupport; + + @Inject + protected TimeSource timeSource; + + @Override + public String getReleaseNumber() { + return serverInfo.getReleaseNumber(); + } + + @Override + public String getReleaseTimestamp() { + return serverInfo.getReleaseTimestamp(); + } + + @Override + public List getViews() { + return ((AbstractViewRepository) viewRepository).getAll(); + } + + @Override + public View getView(Class entityClass, String name) { + try { + return viewRepository.getView(entityClass, name); + } catch (ViewNotFoundException e) { + return null; + } + } + + @Override + public TimeZone getTimeZone() { + return TimeZone.getDefault(); + } + + @Override + public long getTimeMillis() { + return timeSource.currentTimeMillis(); + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbers.java b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbers.java index f4a33cb361..c7f6041546 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbers.java +++ b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbers.java @@ -1,233 +1,233 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.bali.db.DbUtils; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; -import com.haulmont.cuba.core.sys.persistence.SequenceSupport; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; - -import org.springframework.stereotype.Component; -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.regex.Pattern; - -/** - * Provides unique numbers based on database sequences. - * - */ -@Component(UniqueNumbersAPI.NAME) -public class UniqueNumbers implements UniqueNumbersAPI { - - @Inject - protected Persistence persistence; - - protected ReadWriteLock lock = new ReentrantReadWriteLock(); - - @GuardedBy("lock") - protected Set existingSequences = new HashSet<>(); - - protected SequenceSupport sequenceSupport; - - public static final Pattern SEQ_PATTERN = Pattern.compile("[a-zA-Z0-9_]+"); - - @PostConstruct - public void init() { - sequenceSupport = DbmsSpecificFactory.getSequenceSupport(); - } - - @Override - public long getNextNumber(String domain) { - String seqName = getSequenceName(domain); - String sqlScript = sequenceSupport.getNextValueSql(seqName); - - try { - lock.readLock().lock(); - return getResult(seqName, sqlScript); - } finally { - lock.readLock().unlock(); - } - } - - @Override - public long getCurrentNumber(String domain) { - String seqName = getSequenceName(domain); - String sqlScript = sequenceSupport.getCurrentValueSql(seqName); - - try { - lock.readLock().lock(); - return getResult(seqName, sqlScript); - } finally { - lock.readLock().unlock(); - } - } - - @Override - public void setCurrentNumber(String domain, long value) { - String seqName = getSequenceName(domain); - String sqlScript = sequenceSupport.modifySequenceSql(seqName, value); - - Transaction tx = persistence.getTransaction(); - try { - lock.readLock().lock(); - checkSequenceExists(seqName); - executeScript(sqlScript); - tx.commit(); - } finally { - lock.readLock().unlock(); - tx.end(); - } - } - - @Override - public void deleteSequence(String domain) { - String seqName = getSequenceName(domain); - - if (!containsSequence(seqName)) { - throw new IllegalStateException("Attempt to delete nonexistent sequence " + domain); - } - - String sqlScript = sequenceSupport.deleteSequenceSql(seqName); - - Transaction tx = persistence.getTransaction(); - try { - lock.writeLock().lock(); - if (!containsSequence(seqName)) { - tx.commit(); - return; - } - - executeScript(sqlScript); - tx.commit(); - existingSequences.remove(seqName); - } finally { - lock.writeLock().unlock(); - tx.end(); - } - } - - protected long getResult(String seqName, String sqlScript) { - Transaction tx = persistence.getTransaction(); - try { - checkSequenceExists(seqName); - - Object value = executeScript(sqlScript); - tx.commit(); - if (value instanceof Long) - return (Long) value; - else if (value instanceof BigDecimal) - return ((BigDecimal) value).longValue(); - else if (value instanceof BigInteger) - return ((BigInteger) value).longValue(); - else if (value instanceof String) - return Long.parseLong((String) value); - else if (value == null) - throw new IllegalStateException("No value returned"); - else - throw new IllegalStateException("Unsupported value type: " + value.getClass()); - } finally { - tx.end(); - } - } - - protected Object executeScript(String sqlScript) { - EntityManager em = persistence.getEntityManager(); - StrTokenizer tokenizer = new StrTokenizer(sqlScript, SequenceSupport.SQL_DELIMITER); - Object value = null; - Connection connection = em.getConnection(); - while (tokenizer.hasNext()) { - String sql = tokenizer.nextToken(); - try { - PreparedStatement statement = connection.prepareStatement(sql); - try { - if (statement.execute()) { - ResultSet rs = statement.getResultSet(); - if (rs.next()) - value = rs.getLong(1); - } - } finally { - DbUtils.closeQuietly(statement); - } - } catch (SQLException e) { - throw new IllegalStateException("Error executing SQL for getting next number", e); - } - } - return value; - } - - protected void checkSequenceExists(String seqName) { - if (containsSequence(seqName)) return; - - // Create sequence in separate transaction because it's name is cached and we want to be sure it is created - // regardless of possible errors in the invoking code - Transaction tx = persistence.createTransaction(); - try { - lock.readLock().unlock(); - lock.writeLock().lock(); - - EntityManager em = persistence.getEntityManager(); - - Query query = em.createNativeQuery(sequenceSupport.sequenceExistsSql(seqName)); - List list = query.getResultList(); - if (list.isEmpty()) { - query = em.createNativeQuery(sequenceSupport.createSequenceSql(seqName, 1, 1)); - query.executeUpdate(); - } - tx.commit(); - existingSequences.add(seqName); - } finally { - lock.readLock().lock(); - lock.writeLock().unlock(); - tx.end(); - } - } - - protected boolean containsSequence(String name) { - try { - lock.readLock().lock(); - return existingSequences.contains(name); - } finally { - lock.readLock().unlock(); - } - } - - protected String getSequenceName(String domain) { - if (StringUtils.isBlank(domain)) - throw new IllegalArgumentException("Sequence name can not be blank"); - if (!SEQ_PATTERN.matcher(domain).matches()) - throw new IllegalArgumentException("Invalid sequence name: '" + domain + "'. It can contain only alphanumeric characters and underscores"); - - return "seq_un_" + domain; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.bali.db.DbUtils; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; +import com.haulmont.cuba.core.sys.persistence.SequenceSupport; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; + +import org.springframework.stereotype.Component; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.regex.Pattern; + +/** + * Provides unique numbers based on database sequences. + * + */ +@Component(UniqueNumbersAPI.NAME) +public class UniqueNumbers implements UniqueNumbersAPI { + + @Inject + protected Persistence persistence; + + protected ReadWriteLock lock = new ReentrantReadWriteLock(); + + @GuardedBy("lock") + protected Set existingSequences = new HashSet<>(); + + protected SequenceSupport sequenceSupport; + + public static final Pattern SEQ_PATTERN = Pattern.compile("[a-zA-Z0-9_]+"); + + @PostConstruct + public void init() { + sequenceSupport = DbmsSpecificFactory.getSequenceSupport(); + } + + @Override + public long getNextNumber(String domain) { + String seqName = getSequenceName(domain); + String sqlScript = sequenceSupport.getNextValueSql(seqName); + + try { + lock.readLock().lock(); + return getResult(seqName, sqlScript); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public long getCurrentNumber(String domain) { + String seqName = getSequenceName(domain); + String sqlScript = sequenceSupport.getCurrentValueSql(seqName); + + try { + lock.readLock().lock(); + return getResult(seqName, sqlScript); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void setCurrentNumber(String domain, long value) { + String seqName = getSequenceName(domain); + String sqlScript = sequenceSupport.modifySequenceSql(seqName, value); + + Transaction tx = persistence.getTransaction(); + try { + lock.readLock().lock(); + checkSequenceExists(seqName); + executeScript(sqlScript); + tx.commit(); + } finally { + lock.readLock().unlock(); + tx.end(); + } + } + + @Override + public void deleteSequence(String domain) { + String seqName = getSequenceName(domain); + + if (!containsSequence(seqName)) { + throw new IllegalStateException("Attempt to delete nonexistent sequence " + domain); + } + + String sqlScript = sequenceSupport.deleteSequenceSql(seqName); + + Transaction tx = persistence.getTransaction(); + try { + lock.writeLock().lock(); + if (!containsSequence(seqName)) { + tx.commit(); + return; + } + + executeScript(sqlScript); + tx.commit(); + existingSequences.remove(seqName); + } finally { + lock.writeLock().unlock(); + tx.end(); + } + } + + protected long getResult(String seqName, String sqlScript) { + Transaction tx = persistence.getTransaction(); + try { + checkSequenceExists(seqName); + + Object value = executeScript(sqlScript); + tx.commit(); + if (value instanceof Long) + return (Long) value; + else if (value instanceof BigDecimal) + return ((BigDecimal) value).longValue(); + else if (value instanceof BigInteger) + return ((BigInteger) value).longValue(); + else if (value instanceof String) + return Long.parseLong((String) value); + else if (value == null) + throw new IllegalStateException("No value returned"); + else + throw new IllegalStateException("Unsupported value type: " + value.getClass()); + } finally { + tx.end(); + } + } + + protected Object executeScript(String sqlScript) { + EntityManager em = persistence.getEntityManager(); + StrTokenizer tokenizer = new StrTokenizer(sqlScript, SequenceSupport.SQL_DELIMITER); + Object value = null; + Connection connection = em.getConnection(); + while (tokenizer.hasNext()) { + String sql = tokenizer.nextToken(); + try { + PreparedStatement statement = connection.prepareStatement(sql); + try { + if (statement.execute()) { + ResultSet rs = statement.getResultSet(); + if (rs.next()) + value = rs.getLong(1); + } + } finally { + DbUtils.closeQuietly(statement); + } + } catch (SQLException e) { + throw new IllegalStateException("Error executing SQL for getting next number", e); + } + } + return value; + } + + protected void checkSequenceExists(String seqName) { + if (containsSequence(seqName)) return; + + // Create sequence in separate transaction because it's name is cached and we want to be sure it is created + // regardless of possible errors in the invoking code + Transaction tx = persistence.createTransaction(); + try { + lock.readLock().unlock(); + lock.writeLock().lock(); + + EntityManager em = persistence.getEntityManager(); + + Query query = em.createNativeQuery(sequenceSupport.sequenceExistsSql(seqName)); + List list = query.getResultList(); + if (list.isEmpty()) { + query = em.createNativeQuery(sequenceSupport.createSequenceSql(seqName, 1, 1)); + query.executeUpdate(); + } + tx.commit(); + existingSequences.add(seqName); + } finally { + lock.readLock().lock(); + lock.writeLock().unlock(); + tx.end(); + } + } + + protected boolean containsSequence(String name) { + try { + lock.readLock().lock(); + return existingSequences.contains(name); + } finally { + lock.readLock().unlock(); + } + } + + protected String getSequenceName(String domain) { + if (StringUtils.isBlank(domain)) + throw new IllegalArgumentException("Sequence name can not be blank"); + if (!SEQ_PATTERN.matcher(domain).matches()) + throw new IllegalArgumentException("Invalid sequence name: '" + domain + "'. It can contain only alphanumeric characters and underscores"); + + return "seq_un_" + domain; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersAPI.java b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersAPI.java index 36aec1a67e..a8dff680bd 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersAPI.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -/** - * Provides sequences of unique numbers based on database sequences. - * - */ -public interface UniqueNumbersAPI { - - String NAME = "cuba_UniqueNumbers"; - - /** - * Returns the next sequence value. - * - * @param domain sequence identifier - * @return next value - */ - long getNextNumber(String domain); - - /** - * Returns the current value of the sequence. For some implementations - * {@link #getNextNumber(String)} must be called at least once beforehand. - * - * @param domain sequence identifier - * @return current value - */ - long getCurrentNumber(String domain); - - /** - * Set current value for the sequence. - * Next {@link #getCurrentNumber(String)} invocation will return {@code value} - * Next {@link #getNextNumber(String)} invocation will return {@code value + increment} - * - * @param domain sequence identifier - * @param value value - */ - void setCurrentNumber(String domain, long value); - - /** - * Removes sequence with specified identifier - * @param domain sequence identifier - * @throws java.lang.IllegalStateException if sequence does not exist - */ - void deleteSequence(String domain); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +/** + * Provides sequences of unique numbers based on database sequences. + * + */ +public interface UniqueNumbersAPI { + + String NAME = "cuba_UniqueNumbers"; + + /** + * Returns the next sequence value. + * + * @param domain sequence identifier + * @return next value + */ + long getNextNumber(String domain); + + /** + * Returns the current value of the sequence. For some implementations + * {@link #getNextNumber(String)} must be called at least once beforehand. + * + * @param domain sequence identifier + * @return current value + */ + long getCurrentNumber(String domain); + + /** + * Set current value for the sequence. + * Next {@link #getCurrentNumber(String)} invocation will return {@code value} + * Next {@link #getNextNumber(String)} invocation will return {@code value + increment} + * + * @param domain sequence identifier + * @param value value + */ + void setCurrentNumber(String domain, long value); + + /** + * Removes sequence with specified identifier + * @param domain sequence identifier + * @throws java.lang.IllegalStateException if sequence does not exist + */ + void deleteSequence(String domain); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersServiceBean.java index a44727f2a4..6ba0dd3c53 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/UniqueNumbersServiceBean.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.inject.Inject; - -@Service(UniqueNumbersService.NAME) -public class UniqueNumbersServiceBean implements UniqueNumbersService { - - @Inject - protected UniqueNumbersAPI uniqueNumbers; - - @Override - @Transactional - public long getNextNumber(String domain) { - return uniqueNumbers.getNextNumber(domain); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.inject.Inject; + +@Service(UniqueNumbersService.NAME) +public class UniqueNumbersServiceBean implements UniqueNumbersService { + + @Inject + protected UniqueNumbersAPI uniqueNumbers; + + @Override + @Transactional + public long getNextNumber(String domain) { + return uniqueNumbers.getNextNumber(domain); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/CacheLoader.java b/modules/core/src/com/haulmont/cuba/core/app/cache/CacheLoader.java index f15c2d29f5..66906fa668 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/CacheLoader.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/CacheLoader.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import java.util.Map; - -/** - * Data loader interface for ObjectsCache - * - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -public interface CacheLoader { - CacheSet loadData(ObjectsCache cache) throws CacheException; - - void updateData(CacheSet cacheSet, Map params) throws CacheException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import java.util.Map; + +/** + * Data loader interface for ObjectsCache + * + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +public interface CacheLoader { + CacheSet loadData(ObjectsCache cache) throws CacheException; + + void updateData(CacheSet cacheSet, Map params) throws CacheException; } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCache.java b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCache.java index c33c522b5e..ffb6708bc8 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCache.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCache.java @@ -1,342 +1,342 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.google.common.collect.Lists; -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.cuba.core.app.ClusterManagerAPI; -import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.sys.AppContext; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.Predicate; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Inject; -import java.util.*; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Cache for application objects. - * - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -public class ObjectsCache implements ObjectsCacheInstance, ObjectsCacheController { - - private final Logger log = LoggerFactory.getLogger(ObjectsCache.class); - - protected String name; - protected CacheSet cacheSet; - protected CacheLoader loader; - protected boolean logUpdateEvent = false; - - protected ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); - protected ReentrantLock updateDataLock = new ReentrantLock(); - - protected Date lastUpdateTime; - protected long lastUpdateDuration; - - protected final static int UPDATE_COUNT_FOR_AVERAGE_DURATION = 10; - protected List updateDurations = new ArrayList<>(UPDATE_COUNT_FOR_AVERAGE_DURATION); - protected int updateDurationsIndex = 0; - - @Inject - protected ObjectsCacheManagerAPI managerAPI; - @Inject - protected ClusterManagerAPI clusterManagerAPI; - - public ObjectsCache() { - cacheSet = new CacheSet(Collections.emptyList()); - } - - protected CacheSet createCacheSet(Collection items) { - return new CacheSet(items); - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - managerAPI.registerCache(this); - managerAPI.registerController(this); - } - - public CacheLoader getLoader() { - return loader; - } - - public void setLoader(CacheLoader loader) { - this.loader = loader; - } - - public boolean isLogUpdateEvent() { - return logUpdateEvent; - } - - public void setLogUpdateEvent(boolean logUpdateEvent) { - this.logUpdateEvent = logUpdateEvent; - } - - protected boolean isValidState() { - if (StringUtils.isEmpty(name)) { - log.error("Not set name for ObjectsCache instance"); - return false; - } - - if (!AppContext.isStarted()) - return false; - - if (loader == null) { - log.error("Not set cache loader for ObjectsCache:" + name); - return false; - } - - return true; - } - - public void refresh() { - TimeSource timeSource = AppBeans.get(TimeSource.class); - if (isValidState()) { - Date updateStart = timeSource.currentTimestamp(); - - // Load data - CacheSet data; - try { - data = loader.loadData(this); - } catch (CacheException e) { - log.error(String.format("Load data for cache %s failed", name), e); - this.cacheSet = new CacheSet(Collections.emptyList()); - return; - } - - Date updateEnd = timeSource.currentTimestamp(); - - this.lastUpdateDuration = updateEnd.getTime() - updateStart.getTime(); - - if (updateDurations.size() > updateDurationsIndex) - updateDurations.set(updateDurationsIndex, lastUpdateDuration); - else - updateDurations.add(lastUpdateDuration); - - updateDurationsIndex = (updateDurationsIndex + 1) % UPDATE_COUNT_FOR_AVERAGE_DURATION; - - cacheLock.writeLock().lock(); - - // Modify cache set - this.cacheSet = data; - - cacheLock.writeLock().unlock(); - - this.lastUpdateTime = timeSource.currentTimestamp(); - - if (logUpdateEvent) - log.debug("Updated cache set in " + name + " " + - String.valueOf(lastUpdateDuration) + " millis"); - } - } - - @Override - public CacheStatistics getStatistics() { - - cacheLock.readLock().lock(); - - CacheStatistics stats = new CacheStatistics(this); - stats.setObjectsCount(cacheSet.getSize()); - stats.setLastUpdateTime(lastUpdateTime); - stats.setLastUpdateDuration(lastUpdateDuration); - - double durationSumm = 0; - int durationsCount = 0; - long averageDurationTime = 0; - for (Long updateDuration : updateDurations) { - if (updateDuration != null) { - durationSumm += updateDuration; - durationsCount++; - } - } - if (durationsCount > 0) - averageDurationTime = Math.round(durationSumm / durationsCount); - stats.setAverageUpdateDuration(averageDurationTime); - - cacheLock.readLock().unlock(); - - return stats; - } - - @Override - public Collection execute(CacheSelector cacheSelector) { - Collection result; - - cacheLock.readLock().lock(); - - if (cacheSelector != null) { - // Select from cache copy - CacheSet temporaryCacheSet; - try { - temporaryCacheSet = (CacheSet) cacheSet.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - result = cacheSelector.select(temporaryCacheSet); - } else - result = Collections.emptyList(); - - cacheLock.readLock().unlock(); - - return result; - } - - @Override - public int count(Predicate... selectors) { - cacheLock.readLock().lock(); - - int count; - try { - count = cacheSet.countConjunction(selectors); - } finally { - cacheLock.readLock().unlock(); - } - - return count; - } - - @Override - public Pair count(Collection selectors, Predicate amplifyingSelector) { - cacheLock.readLock().lock(); - try { - return cacheSet.countConjunction(selectors, amplifyingSelector); - } finally { - cacheLock.readLock().unlock(); - } - } - - @Override - public ObjectsCacheInstance getCache() { - return this; - } - - @Override - public void reloadCache() { - refresh(); - } - - @Override - public void updateCache(Map params) { - if (isValidState()) { - // do not allow parallel update, but do not block reading - updateDataLock.lock(); - - try { - // Modify cache copy - CacheSet temporaryCacheSet; - try { - cacheLock.readLock().lock(); - - temporaryCacheSet = createCacheSet(new ArrayList<>(cacheSet.getItems())); - temporaryCacheSet.setForUpdate(true); - } finally { - cacheLock.readLock().unlock(); - } - - try { - loader.updateData(temporaryCacheSet, params); - } catch (CacheException e) { - log.error(String.format("Update data for cache %s failed", name), e); - this.cacheSet = new CacheSet(Collections.emptyList()); - return; - } - - cacheLock.writeLock().lock(); - - try { - temporaryCacheSet.setForUpdate(false); - // Modify cache set - this.cacheSet = temporaryCacheSet; - sendCacheUpdateMessage(cacheSet.getRemovedItems(), - cacheSet.getAddedItems()); - } finally { - cacheLock.writeLock().unlock(); - } - } finally { - updateDataLock.unlock(); - } - } - } - - @SuppressWarnings("unchecked") - protected void sendCacheUpdateMessage(Set removedItems, Set addedItems) { - if (clusterManagerAPI.isStarted()) - clusterManagerAPI.send(new CacheUpdateMessage(name, copyItemsCollection(removedItems), addedItems)); - } - - @SuppressWarnings("unchecked") - protected List copyItemsCollection(Collection items) { - List result = Lists.newArrayList(); - for (T item : items) { - if (item instanceof BaseGenericIdEntity - && BooleanUtils.isFalse(BaseEntityInternalAccess.isDetached((BaseGenericIdEntity) item))) - item = (T) copy((BaseGenericIdEntity) item); - result.add(item); - } - - return result; - } - - // Items passed to update method can be managed we send only their copies - protected Entity copy(BaseGenericIdEntity entity) { - BaseGenericIdEntity result = (BaseGenericIdEntity) AppBeans.get(Metadata.class).create(entity.getMetaClass()); - result.setId(entity.getId()); - return result; - } - - public void updateCache(CacheUpdateMessage msg) { - if (isValidState()) { - updateDataLock.lock(); - try { - cacheLock.writeLock().lock(); - try { - Collection itemsToRemove = msg.getItemsToRemove(); - Collection itemsToAdd = msg.getItemsToAdd(); - - if (CollectionUtils.isNotEmpty(itemsToRemove)) - cacheSet.getItems().removeAll(itemsToRemove); - - if (CollectionUtils.isNotEmpty(itemsToAdd)) - cacheSet.getItems().addAll(itemsToAdd); - - } finally { - cacheLock.writeLock().unlock(); - } - } finally { - updateDataLock.unlock(); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.google.common.collect.Lists; +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.cuba.core.app.ClusterManagerAPI; +import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.sys.AppContext; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import java.util.*; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Cache for application objects. + * + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +public class ObjectsCache implements ObjectsCacheInstance, ObjectsCacheController { + + private final Logger log = LoggerFactory.getLogger(ObjectsCache.class); + + protected String name; + protected CacheSet cacheSet; + protected CacheLoader loader; + protected boolean logUpdateEvent = false; + + protected ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); + protected ReentrantLock updateDataLock = new ReentrantLock(); + + protected Date lastUpdateTime; + protected long lastUpdateDuration; + + protected final static int UPDATE_COUNT_FOR_AVERAGE_DURATION = 10; + protected List updateDurations = new ArrayList<>(UPDATE_COUNT_FOR_AVERAGE_DURATION); + protected int updateDurationsIndex = 0; + + @Inject + protected ObjectsCacheManagerAPI managerAPI; + @Inject + protected ClusterManagerAPI clusterManagerAPI; + + public ObjectsCache() { + cacheSet = new CacheSet(Collections.emptyList()); + } + + protected CacheSet createCacheSet(Collection items) { + return new CacheSet(items); + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + managerAPI.registerCache(this); + managerAPI.registerController(this); + } + + public CacheLoader getLoader() { + return loader; + } + + public void setLoader(CacheLoader loader) { + this.loader = loader; + } + + public boolean isLogUpdateEvent() { + return logUpdateEvent; + } + + public void setLogUpdateEvent(boolean logUpdateEvent) { + this.logUpdateEvent = logUpdateEvent; + } + + protected boolean isValidState() { + if (StringUtils.isEmpty(name)) { + log.error("Not set name for ObjectsCache instance"); + return false; + } + + if (!AppContext.isStarted()) + return false; + + if (loader == null) { + log.error("Not set cache loader for ObjectsCache:" + name); + return false; + } + + return true; + } + + public void refresh() { + TimeSource timeSource = AppBeans.get(TimeSource.class); + if (isValidState()) { + Date updateStart = timeSource.currentTimestamp(); + + // Load data + CacheSet data; + try { + data = loader.loadData(this); + } catch (CacheException e) { + log.error(String.format("Load data for cache %s failed", name), e); + this.cacheSet = new CacheSet(Collections.emptyList()); + return; + } + + Date updateEnd = timeSource.currentTimestamp(); + + this.lastUpdateDuration = updateEnd.getTime() - updateStart.getTime(); + + if (updateDurations.size() > updateDurationsIndex) + updateDurations.set(updateDurationsIndex, lastUpdateDuration); + else + updateDurations.add(lastUpdateDuration); + + updateDurationsIndex = (updateDurationsIndex + 1) % UPDATE_COUNT_FOR_AVERAGE_DURATION; + + cacheLock.writeLock().lock(); + + // Modify cache set + this.cacheSet = data; + + cacheLock.writeLock().unlock(); + + this.lastUpdateTime = timeSource.currentTimestamp(); + + if (logUpdateEvent) + log.debug("Updated cache set in " + name + " " + + String.valueOf(lastUpdateDuration) + " millis"); + } + } + + @Override + public CacheStatistics getStatistics() { + + cacheLock.readLock().lock(); + + CacheStatistics stats = new CacheStatistics(this); + stats.setObjectsCount(cacheSet.getSize()); + stats.setLastUpdateTime(lastUpdateTime); + stats.setLastUpdateDuration(lastUpdateDuration); + + double durationSumm = 0; + int durationsCount = 0; + long averageDurationTime = 0; + for (Long updateDuration : updateDurations) { + if (updateDuration != null) { + durationSumm += updateDuration; + durationsCount++; + } + } + if (durationsCount > 0) + averageDurationTime = Math.round(durationSumm / durationsCount); + stats.setAverageUpdateDuration(averageDurationTime); + + cacheLock.readLock().unlock(); + + return stats; + } + + @Override + public Collection execute(CacheSelector cacheSelector) { + Collection result; + + cacheLock.readLock().lock(); + + if (cacheSelector != null) { + // Select from cache copy + CacheSet temporaryCacheSet; + try { + temporaryCacheSet = (CacheSet) cacheSet.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + result = cacheSelector.select(temporaryCacheSet); + } else + result = Collections.emptyList(); + + cacheLock.readLock().unlock(); + + return result; + } + + @Override + public int count(Predicate... selectors) { + cacheLock.readLock().lock(); + + int count; + try { + count = cacheSet.countConjunction(selectors); + } finally { + cacheLock.readLock().unlock(); + } + + return count; + } + + @Override + public Pair count(Collection selectors, Predicate amplifyingSelector) { + cacheLock.readLock().lock(); + try { + return cacheSet.countConjunction(selectors, amplifyingSelector); + } finally { + cacheLock.readLock().unlock(); + } + } + + @Override + public ObjectsCacheInstance getCache() { + return this; + } + + @Override + public void reloadCache() { + refresh(); + } + + @Override + public void updateCache(Map params) { + if (isValidState()) { + // do not allow parallel update, but do not block reading + updateDataLock.lock(); + + try { + // Modify cache copy + CacheSet temporaryCacheSet; + try { + cacheLock.readLock().lock(); + + temporaryCacheSet = createCacheSet(new ArrayList<>(cacheSet.getItems())); + temporaryCacheSet.setForUpdate(true); + } finally { + cacheLock.readLock().unlock(); + } + + try { + loader.updateData(temporaryCacheSet, params); + } catch (CacheException e) { + log.error(String.format("Update data for cache %s failed", name), e); + this.cacheSet = new CacheSet(Collections.emptyList()); + return; + } + + cacheLock.writeLock().lock(); + + try { + temporaryCacheSet.setForUpdate(false); + // Modify cache set + this.cacheSet = temporaryCacheSet; + sendCacheUpdateMessage(cacheSet.getRemovedItems(), + cacheSet.getAddedItems()); + } finally { + cacheLock.writeLock().unlock(); + } + } finally { + updateDataLock.unlock(); + } + } + } + + @SuppressWarnings("unchecked") + protected void sendCacheUpdateMessage(Set removedItems, Set addedItems) { + if (clusterManagerAPI.isStarted()) + clusterManagerAPI.send(new CacheUpdateMessage(name, copyItemsCollection(removedItems), addedItems)); + } + + @SuppressWarnings("unchecked") + protected List copyItemsCollection(Collection items) { + List result = Lists.newArrayList(); + for (T item : items) { + if (item instanceof BaseGenericIdEntity + && BooleanUtils.isFalse(BaseEntityInternalAccess.isDetached((BaseGenericIdEntity) item))) + item = (T) copy((BaseGenericIdEntity) item); + result.add(item); + } + + return result; + } + + // Items passed to update method can be managed we send only their copies + protected Entity copy(BaseGenericIdEntity entity) { + BaseGenericIdEntity result = (BaseGenericIdEntity) AppBeans.get(Metadata.class).create(entity.getMetaClass()); + result.setId(entity.getId()); + return result; + } + + public void updateCache(CacheUpdateMessage msg) { + if (isValidState()) { + updateDataLock.lock(); + try { + cacheLock.writeLock().lock(); + try { + Collection itemsToRemove = msg.getItemsToRemove(); + Collection itemsToAdd = msg.getItemsToAdd(); + + if (CollectionUtils.isNotEmpty(itemsToRemove)) + cacheSet.getItems().removeAll(itemsToRemove); + + if (CollectionUtils.isNotEmpty(itemsToAdd)) + cacheSet.getItems().addAll(itemsToAdd); + + } finally { + cacheLock.writeLock().unlock(); + } + } finally { + updateDataLock.unlock(); + } + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManager.java b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManager.java index f09620959a..41da01cce1 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManager.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.haulmont.cuba.core.app.ClusterListenerAdapter; -import com.haulmont.cuba.core.app.ClusterManagerAPI; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -@Component(ObjectsCacheManagerAPI.NAME) -public class ObjectsCacheManager implements ObjectsCacheManagerAPI { - - private final Logger log = LoggerFactory.getLogger(ObjectsCacheManager.class); - - protected ConcurrentMap instances = new ConcurrentHashMap<>(); - - protected ConcurrentMap controllers = new ConcurrentHashMap<>(); - - protected ClusterManagerAPI clusterManagerAPI; - - @Inject - public void setClusterManagerAPI(ClusterManagerAPI clusterManagerAPI) { - this.clusterManagerAPI = clusterManagerAPI; - clusterManagerAPI.addListener(CacheUpdateMessage.class, new ClusterListenerAdapter() { - @Override - public void receive(CacheUpdateMessage message) { - ObjectsCacheController controller = getController(message.cacheName); - if (controller instanceof ObjectsCache) - ((ObjectsCache) controller).updateCache(message); - } - }); - } - - @Override - public void registerCache(ObjectsCacheInstance objectsCache) { - checkNotNull(objectsCache); - - if (StringUtils.isNotEmpty(objectsCache.getName())) { - if (!instances.containsKey(objectsCache.getName())) { - instances.put(objectsCache.getName(), objectsCache); - } else - log.error( - String.format("Cache instance with name \"%s\" is already registered", objectsCache.getName())); - } - } - - @Override - public void registerController(ObjectsCacheController cacheController) { - checkNotNull(cacheController); - checkNotNull(cacheController.getCache()); - - ObjectsCacheInstance objectsCache = cacheController.getCache(); - - if (StringUtils.isNotEmpty(objectsCache.getName())) { - if (!controllers.containsKey(objectsCache.getName())) { - controllers.put(objectsCache.getName(), cacheController); - } else - log.error( - String.format("Cache instance with name \"%s\" is already registered", objectsCache.getName())); - } - } - - @Override - public Collection getActiveInstances() { - return instances.values(); - } - - @Override - public ObjectsCacheInstance getCache(String cacheName) { - return instances.get(cacheName); - } - - @Override - public ObjectsCacheInstance getCacheNN(String cacheName) { - ObjectsCacheInstance objectsCacheInstance = instances.get(cacheName); - if (objectsCacheInstance == null) { - throw new IllegalArgumentException("ObjectsCacheInstance with name '" + cacheName + "' not found"); - } - return objectsCacheInstance; - } - - @Override - public ObjectsCacheController getController(String cacheName) { - return controllers.get(cacheName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.haulmont.cuba.core.app.ClusterListenerAdapter; +import com.haulmont.cuba.core.app.ClusterManagerAPI; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +@Component(ObjectsCacheManagerAPI.NAME) +public class ObjectsCacheManager implements ObjectsCacheManagerAPI { + + private final Logger log = LoggerFactory.getLogger(ObjectsCacheManager.class); + + protected ConcurrentMap instances = new ConcurrentHashMap<>(); + + protected ConcurrentMap controllers = new ConcurrentHashMap<>(); + + protected ClusterManagerAPI clusterManagerAPI; + + @Inject + public void setClusterManagerAPI(ClusterManagerAPI clusterManagerAPI) { + this.clusterManagerAPI = clusterManagerAPI; + clusterManagerAPI.addListener(CacheUpdateMessage.class, new ClusterListenerAdapter() { + @Override + public void receive(CacheUpdateMessage message) { + ObjectsCacheController controller = getController(message.cacheName); + if (controller instanceof ObjectsCache) + ((ObjectsCache) controller).updateCache(message); + } + }); + } + + @Override + public void registerCache(ObjectsCacheInstance objectsCache) { + checkNotNull(objectsCache); + + if (StringUtils.isNotEmpty(objectsCache.getName())) { + if (!instances.containsKey(objectsCache.getName())) { + instances.put(objectsCache.getName(), objectsCache); + } else + log.error( + String.format("Cache instance with name \"%s\" is already registered", objectsCache.getName())); + } + } + + @Override + public void registerController(ObjectsCacheController cacheController) { + checkNotNull(cacheController); + checkNotNull(cacheController.getCache()); + + ObjectsCacheInstance objectsCache = cacheController.getCache(); + + if (StringUtils.isNotEmpty(objectsCache.getName())) { + if (!controllers.containsKey(objectsCache.getName())) { + controllers.put(objectsCache.getName(), cacheController); + } else + log.error( + String.format("Cache instance with name \"%s\" is already registered", objectsCache.getName())); + } + } + + @Override + public Collection getActiveInstances() { + return instances.values(); + } + + @Override + public ObjectsCacheInstance getCache(String cacheName) { + return instances.get(cacheName); + } + + @Override + public ObjectsCacheInstance getCacheNN(String cacheName) { + ObjectsCacheInstance objectsCacheInstance = instances.get(cacheName); + if (objectsCacheInstance == null) { + throw new IllegalArgumentException("ObjectsCacheInstance with name '" + cacheName + "' not found"); + } + return objectsCacheInstance; + } + + @Override + public ObjectsCacheController getController(String cacheName) { + return controllers.get(cacheName); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerAPI.java index 40d7eeb91e..7f29f6adf2 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerAPI.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import javax.annotation.Nullable; -import java.util.Collection; - -/** - * Interface to provide "Data in memory" caches and controllers. - * - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -public interface ObjectsCacheManagerAPI { - - String NAME = "cuba_ObjectsCacheManager"; - - /** - * Register cache instance in - * - * @param objectsCache Cache instance - */ - void registerCache(ObjectsCacheInstance objectsCache); - - /** - * Register cache controller in - * - * @param cacheController Cache controller - */ - void registerController(ObjectsCacheController cacheController); - - /** - * Get collection of registered instances - * - * @return Active cache instances - */ - Collection getActiveInstances(); - - /** - * Get cache instance by name - * - * @param cacheName Unique cache name - * @return Cache instance - */ - @Nullable - ObjectsCacheInstance getCache(String cacheName); - - /** - * Get cache instance by name - * - * @param cacheName Unique cache name - * @return Cache instance - * @throws java.lang.IllegalArgumentException if cache with given name not found - */ - ObjectsCacheInstance getCacheNN(String cacheName); - - /** - * Get cache controller instance by cache name - * - * @param cacheName Unique cache name - * @return Cache controller - */ - @Nullable - ObjectsCacheController getController(String cacheName); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import javax.annotation.Nullable; +import java.util.Collection; + +/** + * Interface to provide "Data in memory" caches and controllers. + * + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +public interface ObjectsCacheManagerAPI { + + String NAME = "cuba_ObjectsCacheManager"; + + /** + * Register cache instance in + * + * @param objectsCache Cache instance + */ + void registerCache(ObjectsCacheInstance objectsCache); + + /** + * Register cache controller in + * + * @param cacheController Cache controller + */ + void registerController(ObjectsCacheController cacheController); + + /** + * Get collection of registered instances + * + * @return Active cache instances + */ + Collection getActiveInstances(); + + /** + * Get cache instance by name + * + * @param cacheName Unique cache name + * @return Cache instance + */ + @Nullable + ObjectsCacheInstance getCache(String cacheName); + + /** + * Get cache instance by name + * + * @param cacheName Unique cache name + * @return Cache instance + * @throws java.lang.IllegalArgumentException if cache with given name not found + */ + ObjectsCacheInstance getCacheNN(String cacheName); + + /** + * Get cache controller instance by cache name + * + * @param cacheName Unique cache name + * @return Cache controller + */ + @Nullable + ObjectsCacheController getController(String cacheName); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerServiceBean.java index 7447d716e3..514ab7d16a 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerServiceBean.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.Map; - -/** - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -@Service(ObjectsCacheManagerService.NAME) -public class ObjectsCacheManagerServiceBean implements ObjectsCacheManagerService { - - @Inject - private ObjectsCacheManagerAPI managerAPI; - - @Override - public void updateCache(String cacheName, Map params) { - ObjectsCacheController controller = managerAPI.getController(cacheName); - controller.updateCache(params); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.Map; + +/** + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +@Service(ObjectsCacheManagerService.NAME) +public class ObjectsCacheManagerServiceBean implements ObjectsCacheManagerService { + + @Inject + private ObjectsCacheManagerAPI managerAPI; + + @Override + public void updateCache(String cacheName, Map params) { + ObjectsCacheController controller = managerAPI.getController(cacheName); + controller.updateCache(params); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/cache/StandardCacheLoader.java b/modules/core/src/com/haulmont/cuba/core/app/cache/StandardCacheLoader.java index d1a45b0e7a..941ad21c98 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/cache/StandardCacheLoader.java +++ b/modules/core/src/com/haulmont/cuba/core/app/cache/StandardCacheLoader.java @@ -1,168 +1,168 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.app.PersistenceConfig; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Inject; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * JPQL cache loader
- * Loads objects tree with jpql query and view. - * - * @deprecated Will be removed in release 7.0 - */ -@Deprecated -public class StandardCacheLoader implements CacheLoader { - - @Inject - private Persistence persistence; - - @Inject - private Metadata metadata; - - @Inject - private Resources resources; - - @Inject - private Configuration configuration; - - private static Logger log = LoggerFactory.getLogger(ObjectsCache.class); - - private String viewName; - private String queryPath; - private String metaClassName; - - private String dbQuery; - - public String getViewName() { - return viewName; - } - - public void setViewName(String viewName) { - this.viewName = viewName; - } - - public String getQueryPath() { - return queryPath; - } - - public void setQueryPath(String queryPath) { - this.queryPath = queryPath; - } - - public String getMetaClassName() { - return metaClassName; - } - - public void setMetaClassName(String metaClassName) { - this.metaClassName = metaClassName; - } - - @Override - @SuppressWarnings("unchecked") - public CacheSet loadData(ObjectsCache cache) throws CacheException { - CacheSet cacheSet; - - if (StringUtils.isEmpty(dbQuery)) { - try { - dbQuery = resources.getResourceAsString(queryPath); - } catch (Exception e) { - log.error("Broken or missing query file for cache: " + cache.getName()); - throw new CacheException(e); - } - } - - MetaClass metaClass = metadata.getSession().getClass(metaClassName); - View view = metadata.getViewRepository().getView(metaClass, viewName); - - Transaction tx = persistence.createTransaction(); - - try { - EntityManager em = persistence.getEntityManager(); - Query query = em.createQuery(dbQuery); - query.setView(view); - query.setMaxResults(getMaxQueryResults()); - List resultList = query.getResultList(); - cacheSet = new CacheSet(resultList); - tx.commit(); - } catch (Exception e) { - throw new CacheException(e); - } finally { - tx.end(); - } - - return cacheSet; - } - - @Override - public void updateData(CacheSet cacheSet, Map params) throws CacheException { - if (configuration.getConfig(GlobalConfig.class).getTestMode()) - return; - - Collection items = cacheSet.getItems(); - - List updateItems = (List) params.get("items"); - - if ((updateItems != null) && (updateItems.size() > 0)) { - MetaClass metaClass = metadata.getSession().getClass(metaClassName); - View view = metadata.getViewRepository().getView(metaClass, viewName); - - Transaction tx = persistence.createTransaction(); - - try { - EntityManager em = persistence.getEntityManager(); - - for (Object item : updateItems) { - Entity entity = (Entity) item; - entity = em.find(entity.getClass(), entity.getId(), view); - - items.remove(item); - if(entity != null) - items.add(entity); - } - - tx.commit(); - } catch (Exception e) { - throw new CacheException(e); - } finally { - tx.end(); - } - } else { - log.debug("Nothing to update"); - } - } - - protected int getMaxQueryResults() { - return configuration.getConfig(GlobalConfig.class).getTestMode() ? - 500 : configuration.getConfig(PersistenceConfig.class).getDefaultMaxFetchUI(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.app.PersistenceConfig; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * JPQL cache loader
+ * Loads objects tree with jpql query and view. + * + * @deprecated Will be removed in release 7.0 + */ +@Deprecated +public class StandardCacheLoader implements CacheLoader { + + @Inject + private Persistence persistence; + + @Inject + private Metadata metadata; + + @Inject + private Resources resources; + + @Inject + private Configuration configuration; + + private static Logger log = LoggerFactory.getLogger(ObjectsCache.class); + + private String viewName; + private String queryPath; + private String metaClassName; + + private String dbQuery; + + public String getViewName() { + return viewName; + } + + public void setViewName(String viewName) { + this.viewName = viewName; + } + + public String getQueryPath() { + return queryPath; + } + + public void setQueryPath(String queryPath) { + this.queryPath = queryPath; + } + + public String getMetaClassName() { + return metaClassName; + } + + public void setMetaClassName(String metaClassName) { + this.metaClassName = metaClassName; + } + + @Override + @SuppressWarnings("unchecked") + public CacheSet loadData(ObjectsCache cache) throws CacheException { + CacheSet cacheSet; + + if (StringUtils.isEmpty(dbQuery)) { + try { + dbQuery = resources.getResourceAsString(queryPath); + } catch (Exception e) { + log.error("Broken or missing query file for cache: " + cache.getName()); + throw new CacheException(e); + } + } + + MetaClass metaClass = metadata.getSession().getClass(metaClassName); + View view = metadata.getViewRepository().getView(metaClass, viewName); + + Transaction tx = persistence.createTransaction(); + + try { + EntityManager em = persistence.getEntityManager(); + Query query = em.createQuery(dbQuery); + query.setView(view); + query.setMaxResults(getMaxQueryResults()); + List resultList = query.getResultList(); + cacheSet = new CacheSet(resultList); + tx.commit(); + } catch (Exception e) { + throw new CacheException(e); + } finally { + tx.end(); + } + + return cacheSet; + } + + @Override + public void updateData(CacheSet cacheSet, Map params) throws CacheException { + if (configuration.getConfig(GlobalConfig.class).getTestMode()) + return; + + Collection items = cacheSet.getItems(); + + List updateItems = (List) params.get("items"); + + if ((updateItems != null) && (updateItems.size() > 0)) { + MetaClass metaClass = metadata.getSession().getClass(metaClassName); + View view = metadata.getViewRepository().getView(metaClass, viewName); + + Transaction tx = persistence.createTransaction(); + + try { + EntityManager em = persistence.getEntityManager(); + + for (Object item : updateItems) { + Entity entity = (Entity) item; + entity = em.find(entity.getClass(), entity.getId(), view); + + items.remove(item); + if(entity != null) + items.add(entity); + } + + tx.commit(); + } catch (Exception e) { + throw new CacheException(e); + } finally { + tx.end(); + } + } else { + log.debug("Nothing to update"); + } + } + + protected int getMaxQueryResults() { + return configuration.getConfig(GlobalConfig.class).getTestMode() ? + 500 : configuration.getConfig(PersistenceConfig.class).getDefaultMaxFetchUI(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/domain/DomainDescription.ftl b/modules/core/src/com/haulmont/cuba/core/app/domain/DomainDescription.ftl index fce771050d..5aa6c32008 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/domain/DomainDescription.ftl +++ b/modules/core/src/com/haulmont/cuba/core/app/domain/DomainDescription.ftl @@ -1,150 +1,150 @@ - - - - - - Data model description - - - - - -<#macro printView view> -
    - <#list view.properties as property> -
  • ${property.name} ${property.lazy}
  • - <#if property.view ??> - <@printView view = property.view/> - - -
- - - - -

Domain model description

- -

Available basic types:

-
    - <#list availableTypes as type> -
  • ${type}
  • - -
- -

Known entities:

- - - -<#list knownEntities as entity> - -

${entity.name}

-

Table: ${entity.tableName}

- <#if entity.parent ??> - ${entity.parent} - -

${entity.description}

-

Fields

- - - - - - - - - - - - - - - - <#list entity.properties as property> - - - - - - - - - -
PropertyColumnTypeDescriptionCardinalityAnnotations
${property.name}<#if property.persistent>${property.columnName}${property.enum!property.javaType}${property.description}${property.cardinality} - <#list property.annotations as ann> - ${ann}<#if ann_has_next>;  - -
- - <#if entity.views ??> -

Views

-
    - <#list entity.views as aview> -
  • ${aview.name}
  • - <@printView view=aview/> - -
- -

 

- - -

Enumerations:

- - - <#list enums as enum> - -

${enum.name}

-

Values

- - - - - - - - <#list enum.values as value> - - <#if value.idObj.id?? && value.idObj.id?is_boolean> - - <#else> - - - - - -
IdValue
${value.idObj.id?c}${value.idObj.id!}${value.name}
- - - - + + + + + + Data model description + + + + + +<#macro printView view> +
    + <#list view.properties as property> +
  • ${property.name} ${property.lazy}
  • + <#if property.view ??> + <@printView view = property.view/> + + +
+ + + + +

Domain model description

+ +

Available basic types:

+
    + <#list availableTypes as type> +
  • ${type}
  • + +
+ +

Known entities:

+ + + +<#list knownEntities as entity> + +

${entity.name}

+

Table: ${entity.tableName}

+ <#if entity.parent ??> + ${entity.parent} + +

${entity.description}

+

Fields

+ + + + + + + + + + + + + + + + <#list entity.properties as property> + + + + + + + + + +
PropertyColumnTypeDescriptionCardinalityAnnotations
${property.name}<#if property.persistent>${property.columnName}${property.enum!property.javaType}${property.description}${property.cardinality} + <#list property.annotations as ann> + ${ann}<#if ann_has_next>;  + +
+ + <#if entity.views ??> +

Views

+
    + <#list entity.views as aview> +
  • ${aview.name}
  • + <@printView view=aview/> + +
+ +

 

+ + +

Enumerations:

+ + + <#list enums as enum> + +

${enum.name}

+

Values

+ + + + + + + + <#list enum.values as value> + + <#if value.idObj.id?? && value.idObj.id?is_boolean> + + <#else> + + + + + +
IdValue
${value.idObj.id?c}${value.idObj.id!}${value.name}
+ + + + diff --git a/modules/core/src/com/haulmont/cuba/core/app/domain/MetaClassRepresentation.java b/modules/core/src/com/haulmont/cuba/core/app/domain/MetaClassRepresentation.java index 890d2091fb..4acf119d53 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/domain/MetaClassRepresentation.java +++ b/modules/core/src/com/haulmont/cuba/core/app/domain/MetaClassRepresentation.java @@ -1,318 +1,318 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.domain; - -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.EntityAttrAccess; -import com.haulmont.cuba.security.entity.EntityOp; -import freemarker.template.*; - -import javax.persistence.Column; -import javax.persistence.Embeddable; -import javax.persistence.JoinColumn; -import javax.persistence.MappedSuperclass; -import java.util.*; - -public class MetaClassRepresentation { - private MetaClass meta; - private List views; - - public MetaClassRepresentation(MetaClass meta, List views) { - this.meta = meta; - this.views = views; - getTableName(); - } - - public String getTableName() { - boolean isEmbeddable = meta.getJavaClass().isAnnotationPresent(Embeddable.class); - if (isEmbeddable) - return "not defined for embeddable entities"; - - MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - - String databaseTable = metadataTools.getDatabaseTable(meta); - return databaseTable != null ? databaseTable : "not defined"; - } - - public String getName() { - return meta.getName(); - } - - public String getParent() { - MetaClass ancestor = meta.getAncestor(); - - if (ancestor == null || !ancestor.getName().contains("$") || - ancestor.getJavaClass().isAnnotationPresent(MappedSuperclass.class)) - return ""; - - if (!readPermitted(ancestor)) { - return null; - } - - return "Parent is " + asHref(ancestor.getName()); - } - - public String getDescription() { - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - String result = messageTools.getEntityCaption(meta); - return result == null ? "" : result; - } - - public Collection getProperties() { - List result = new ArrayList<>(); - for (MetaProperty property : meta.getProperties()) { - MetaProperty.Type propertyType = property.getType(); - //don't show property if user don't have permissions to view it - if (!attrViewPermitted(meta, property.getName())) { - continue; - } - - //don't show property if it's reference and user - //don't have permissions to view it's entity class - if (propertyType == MetaProperty.Type.COMPOSITION - || propertyType == MetaProperty.Type.ASSOCIATION) { - MetaClass propertyMetaClass = propertyMetaClass(property); - if (!readPermitted(propertyMetaClass)) - continue; - } - MetaClassRepProperty prop = new MetaClassRepProperty(property, meta); - result.add(prop); - } - return result; - } - - public static class MetaClassRepProperty { - private MetaProperty property; - private MetaClass metaClass; - - public MetaClassRepProperty(MetaProperty property, MetaClass metaClass) { - this.property = property; - this.metaClass = metaClass; - } - - public String getColumnName() { - Column column = property.getAnnotatedElement().getAnnotation(Column.class); - if (column != null) - return column.name(); - - JoinColumn joinColumn = property.getAnnotatedElement().getAnnotation(JoinColumn.class); - return joinColumn != null ? joinColumn.name() : ""; - } - - public String getName() { - return property.getName(); - } - - public String getDescription() { - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - String result = messageTools.getPropertyCaption(metaClass, property.getName()); - return result == null ? "" : result; - } - - public String getEnum() { - return property.getRange().isEnum() ? asHref(property.getRange().asEnumeration().toString()) : null; - } - - /** - * @return map representing Enumeration with localized Enumeration item values - */ - public TemplateHashModel getEnumValues() { - if (property.getRange().isEnum()) { - - Enumeration enumeration = property.getRange().asEnumeration(); - SimpleHash wrappedEnum = new SimpleHash(); - wrappedEnum.put("name", enumeration.toString()); - SimpleSequence values = new SimpleSequence(); - - for (Enum enumItem : enumeration.getValues()) { - SimpleHash wrappedEnumElement = new SimpleHash(); - try { - wrappedEnumElement.put("idObj", ObjectWrapper.BEANS_WRAPPER.wrap(enumItem)); //Some enums don't implement EnumClass interface so we'll get id field here via reflection. - Messages messages = AppBeans.get(Messages.NAME); - wrappedEnumElement.put("name", messages.getMessage(enumItem)); - values.add(wrappedEnumElement); - } catch (TemplateModelException e) { - throw new RuntimeException(e); - } - } - wrappedEnum.put("values", values); - - return wrappedEnum; - } - return null; - } - - public String getJavaType() { - String type = property.getJavaType().getName(); - String simpleName = property.getJavaType().getSimpleName(); - return type.startsWith("java.lang.") && ("java.lang.".length() + simpleName.length() == type.length()) || type.startsWith("[")? - simpleName : - property.getRange().isClass() ? - asHref(property.getRange().asClass().getName()) : - type; - } - - public String getCardinality() { - switch (property.getRange().getCardinality()) { - case NONE: - return ""; - case ONE_TO_ONE: - return property.getRange().isClass() ? "1:1" : ""; - case ONE_TO_MANY: - return "1:N"; - case MANY_TO_ONE: - return "N:1"; - case MANY_TO_MANY: - return "N:N"; - default: - return property.getRange().getCardinality().toString(); - } - } - - public Collection getAnnotations() { - List result = new ArrayList<>(); - Map map = property.getAnnotations(); - for (Map.Entry entry : map.entrySet()) { - String annotationName = entry.getKey(); - if (("length".equals(annotationName) && !String.class.equals(property.getJavaType()))) - continue; - - if (Boolean.TRUE.equals(entry.getValue())) - result.add(annotationName); - else - result.add(annotationName + ": " + entry.getValue()); - } - Collections.sort(result); - return result; - } - - public boolean isPersistent() { - MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - return metadataTools.isPersistent(property); - } - } - - public Collection getViews() { - if (views == null) - return null; - - Collection result = new ArrayList<>(); - for (View view : views) { - if (!viewAccessPermitted(view)) - continue; - result.add(new MetaClassRepView(view)); - } - return result; - } - - private static boolean viewAccessPermitted(View view) { - Class clazz = view.getEntityClass(); - MetaClass meta = getMetaClass(clazz); - return MetaClassRepresentation.readPermitted(meta); - } - - private static MetaClass getMetaClass(Class clazz) { - Metadata metadata = AppBeans.get(Metadata.NAME); - return metadata.getExtendedEntities().getEffectiveMetaClass(metadata.getClassNN(clazz)); - } - - private static boolean viewPropertyReadPermitted(MetaClass meta, ViewProperty viewProperty) { - if (!attrViewPermitted(meta, viewProperty.getName())) - return false; - - MetaProperty metaProperty = meta.getPropertyNN(viewProperty.getName()); - if (metaProperty.getType() == MetaProperty.Type.DATATYPE - || metaProperty.getType() == MetaProperty.Type.ENUM) - return true; - - MetaClass propertyMeta = metaProperty.getRange().asClass(); - return readPermitted(propertyMeta); - } - - public static class MetaClassRepView { - private View view; - - public MetaClassRepView(View view) { - this.view = view; - } - - public String getName() { - return view.getName(); - } - - public Collection getProperties() { - Collection result = new ArrayList<>(); - MetaClass meta = getMetaClass(view.getEntityClass()); - for (ViewProperty property : view.getProperties()) { - if (!MetaClassRepresentation.viewPropertyReadPermitted(meta, property)) - continue; - result.add(new MetaClassRepViewProperty(property)); - } - return result; - } - } - - public static class MetaClassRepViewProperty { - private ViewProperty property; - - public MetaClassRepViewProperty(ViewProperty property) { - this.property = property; - } - - public String getName() { - return property.getName(); - } - - public String getLazy() { - return property.isLazy() ? "LAZY" : ""; - } - - public MetaClassRepView getView() { - return property.getView() == null ? null : new MetaClassRepView(property.getView()); - } - } - - private MetaClass propertyMetaClass(MetaProperty property) { - return property.getRange().asClass(); - } - - private static boolean attrViewPermitted(MetaClass metaClass, String property) { - return attrPermitted(metaClass, property, EntityAttrAccess.VIEW); - } - - private static boolean attrPermitted(MetaClass metaClass, String property, EntityAttrAccess entityAttrAccess) { - Security security = AppBeans.get(Security.NAME); - return security.isEntityAttrPermitted(metaClass, property, entityAttrAccess); - } - - private static boolean readPermitted(MetaClass metaClass) { - return entityOpPermitted(metaClass, EntityOp.READ); - } - - private static boolean entityOpPermitted(MetaClass metaClass, EntityOp entityOp) { - Security security = AppBeans.get(Security.NAME); - return security.isEntityOpPermitted(metaClass, entityOp); - } - - private static String asHref(String element) { - return "" + element + ""; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.domain; + +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.EntityAttrAccess; +import com.haulmont.cuba.security.entity.EntityOp; +import freemarker.template.*; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.JoinColumn; +import javax.persistence.MappedSuperclass; +import java.util.*; + +public class MetaClassRepresentation { + private MetaClass meta; + private List views; + + public MetaClassRepresentation(MetaClass meta, List views) { + this.meta = meta; + this.views = views; + getTableName(); + } + + public String getTableName() { + boolean isEmbeddable = meta.getJavaClass().isAnnotationPresent(Embeddable.class); + if (isEmbeddable) + return "not defined for embeddable entities"; + + MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + + String databaseTable = metadataTools.getDatabaseTable(meta); + return databaseTable != null ? databaseTable : "not defined"; + } + + public String getName() { + return meta.getName(); + } + + public String getParent() { + MetaClass ancestor = meta.getAncestor(); + + if (ancestor == null || !ancestor.getName().contains("$") || + ancestor.getJavaClass().isAnnotationPresent(MappedSuperclass.class)) + return ""; + + if (!readPermitted(ancestor)) { + return null; + } + + return "Parent is " + asHref(ancestor.getName()); + } + + public String getDescription() { + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + String result = messageTools.getEntityCaption(meta); + return result == null ? "" : result; + } + + public Collection getProperties() { + List result = new ArrayList<>(); + for (MetaProperty property : meta.getProperties()) { + MetaProperty.Type propertyType = property.getType(); + //don't show property if user don't have permissions to view it + if (!attrViewPermitted(meta, property.getName())) { + continue; + } + + //don't show property if it's reference and user + //don't have permissions to view it's entity class + if (propertyType == MetaProperty.Type.COMPOSITION + || propertyType == MetaProperty.Type.ASSOCIATION) { + MetaClass propertyMetaClass = propertyMetaClass(property); + if (!readPermitted(propertyMetaClass)) + continue; + } + MetaClassRepProperty prop = new MetaClassRepProperty(property, meta); + result.add(prop); + } + return result; + } + + public static class MetaClassRepProperty { + private MetaProperty property; + private MetaClass metaClass; + + public MetaClassRepProperty(MetaProperty property, MetaClass metaClass) { + this.property = property; + this.metaClass = metaClass; + } + + public String getColumnName() { + Column column = property.getAnnotatedElement().getAnnotation(Column.class); + if (column != null) + return column.name(); + + JoinColumn joinColumn = property.getAnnotatedElement().getAnnotation(JoinColumn.class); + return joinColumn != null ? joinColumn.name() : ""; + } + + public String getName() { + return property.getName(); + } + + public String getDescription() { + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + String result = messageTools.getPropertyCaption(metaClass, property.getName()); + return result == null ? "" : result; + } + + public String getEnum() { + return property.getRange().isEnum() ? asHref(property.getRange().asEnumeration().toString()) : null; + } + + /** + * @return map representing Enumeration with localized Enumeration item values + */ + public TemplateHashModel getEnumValues() { + if (property.getRange().isEnum()) { + + Enumeration enumeration = property.getRange().asEnumeration(); + SimpleHash wrappedEnum = new SimpleHash(); + wrappedEnum.put("name", enumeration.toString()); + SimpleSequence values = new SimpleSequence(); + + for (Enum enumItem : enumeration.getValues()) { + SimpleHash wrappedEnumElement = new SimpleHash(); + try { + wrappedEnumElement.put("idObj", ObjectWrapper.BEANS_WRAPPER.wrap(enumItem)); //Some enums don't implement EnumClass interface so we'll get id field here via reflection. + Messages messages = AppBeans.get(Messages.NAME); + wrappedEnumElement.put("name", messages.getMessage(enumItem)); + values.add(wrappedEnumElement); + } catch (TemplateModelException e) { + throw new RuntimeException(e); + } + } + wrappedEnum.put("values", values); + + return wrappedEnum; + } + return null; + } + + public String getJavaType() { + String type = property.getJavaType().getName(); + String simpleName = property.getJavaType().getSimpleName(); + return type.startsWith("java.lang.") && ("java.lang.".length() + simpleName.length() == type.length()) || type.startsWith("[")? + simpleName : + property.getRange().isClass() ? + asHref(property.getRange().asClass().getName()) : + type; + } + + public String getCardinality() { + switch (property.getRange().getCardinality()) { + case NONE: + return ""; + case ONE_TO_ONE: + return property.getRange().isClass() ? "1:1" : ""; + case ONE_TO_MANY: + return "1:N"; + case MANY_TO_ONE: + return "N:1"; + case MANY_TO_MANY: + return "N:N"; + default: + return property.getRange().getCardinality().toString(); + } + } + + public Collection getAnnotations() { + List result = new ArrayList<>(); + Map map = property.getAnnotations(); + for (Map.Entry entry : map.entrySet()) { + String annotationName = entry.getKey(); + if (("length".equals(annotationName) && !String.class.equals(property.getJavaType()))) + continue; + + if (Boolean.TRUE.equals(entry.getValue())) + result.add(annotationName); + else + result.add(annotationName + ": " + entry.getValue()); + } + Collections.sort(result); + return result; + } + + public boolean isPersistent() { + MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + return metadataTools.isPersistent(property); + } + } + + public Collection getViews() { + if (views == null) + return null; + + Collection result = new ArrayList<>(); + for (View view : views) { + if (!viewAccessPermitted(view)) + continue; + result.add(new MetaClassRepView(view)); + } + return result; + } + + private static boolean viewAccessPermitted(View view) { + Class clazz = view.getEntityClass(); + MetaClass meta = getMetaClass(clazz); + return MetaClassRepresentation.readPermitted(meta); + } + + private static MetaClass getMetaClass(Class clazz) { + Metadata metadata = AppBeans.get(Metadata.NAME); + return metadata.getExtendedEntities().getEffectiveMetaClass(metadata.getClassNN(clazz)); + } + + private static boolean viewPropertyReadPermitted(MetaClass meta, ViewProperty viewProperty) { + if (!attrViewPermitted(meta, viewProperty.getName())) + return false; + + MetaProperty metaProperty = meta.getPropertyNN(viewProperty.getName()); + if (metaProperty.getType() == MetaProperty.Type.DATATYPE + || metaProperty.getType() == MetaProperty.Type.ENUM) + return true; + + MetaClass propertyMeta = metaProperty.getRange().asClass(); + return readPermitted(propertyMeta); + } + + public static class MetaClassRepView { + private View view; + + public MetaClassRepView(View view) { + this.view = view; + } + + public String getName() { + return view.getName(); + } + + public Collection getProperties() { + Collection result = new ArrayList<>(); + MetaClass meta = getMetaClass(view.getEntityClass()); + for (ViewProperty property : view.getProperties()) { + if (!MetaClassRepresentation.viewPropertyReadPermitted(meta, property)) + continue; + result.add(new MetaClassRepViewProperty(property)); + } + return result; + } + } + + public static class MetaClassRepViewProperty { + private ViewProperty property; + + public MetaClassRepViewProperty(ViewProperty property) { + this.property = property; + } + + public String getName() { + return property.getName(); + } + + public String getLazy() { + return property.isLazy() ? "LAZY" : ""; + } + + public MetaClassRepView getView() { + return property.getView() == null ? null : new MetaClassRepView(property.getView()); + } + } + + private MetaClass propertyMetaClass(MetaProperty property) { + return property.getRange().asClass(); + } + + private static boolean attrViewPermitted(MetaClass metaClass, String property) { + return attrPermitted(metaClass, property, EntityAttrAccess.VIEW); + } + + private static boolean attrPermitted(MetaClass metaClass, String property, EntityAttrAccess entityAttrAccess) { + Security security = AppBeans.get(Security.NAME); + return security.isEntityAttrPermitted(metaClass, property, entityAttrAccess); + } + + private static boolean readPermitted(MetaClass metaClass) { + return entityOpPermitted(metaClass, EntityOp.READ); + } + + private static boolean entityOpPermitted(MetaClass metaClass, EntityOp entityOp) { + Security security = AppBeans.get(Security.NAME); + return security.isEntityOpPermitted(metaClass, entityOp); + } + + private static String asHref(String element) { + return "" + element + ""; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/CategoryAttributeListener.java b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/CategoryAttributeListener.java index d2d089707d..50e9eda121 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/CategoryAttributeListener.java +++ b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/CategoryAttributeListener.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; -import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; - -import org.springframework.stereotype.Component; - -@Component("report_CategoryAttributeListener") -public class CategoryAttributeListener implements BeforeInsertEntityListener, - BeforeUpdateEntityListener { - @Override - public void onBeforeInsert(CategoryAttribute entity, EntityManager entityManager) { - setCategoryEntityType(entity); - } - - @Override - public void onBeforeUpdate(CategoryAttribute entity, EntityManager entityManager) { - setCategoryEntityType(entity); - } - - protected void setCategoryEntityType(CategoryAttribute entity) { - if (entity.getCategory() != null) { - entity.setCategoryEntityType(entity.getCategory().getEntityType()); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; +import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; + +import org.springframework.stereotype.Component; + +@Component("report_CategoryAttributeListener") +public class CategoryAttributeListener implements BeforeInsertEntityListener, + BeforeUpdateEntityListener { + @Override + public void onBeforeInsert(CategoryAttribute entity, EntityManager entityManager) { + setCategoryEntityType(entity); + } + + @Override + public void onBeforeUpdate(CategoryAttribute entity, EntityManager entityManager) { + setCategoryEntityType(entity); + } + + protected void setCategoryEntityType(CategoryAttribute entity) { + if (entity.getCategory() != null) { + entity.setCategoryEntityType(entity.getCategory().getEntityType()); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheServiceBean.java index 46871e7c2e..33c3cfa27f 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheServiceBean.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.Date; - -@Service(DynamicAttributesCacheService.NAME) -public class DynamicAttributesCacheServiceBean implements DynamicAttributesCacheService { - @Inject - protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; - - @Override - public void loadCache(){ - dynamicAttributesManagerAPI.loadCache(); - } - - @Override - public DynamicAttributesCache getCacheIfNewer(Date clientCacheDate) { - return dynamicAttributesManagerAPI.getCacheIfNewer(clientCacheDate); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.Date; + +@Service(DynamicAttributesCacheService.NAME) +public class DynamicAttributesCacheServiceBean implements DynamicAttributesCacheService { + @Inject + protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; + + @Override + public void loadCache(){ + dynamicAttributesManagerAPI.loadCache(); + } + + @Override + public DynamicAttributesCache getCacheIfNewer(Date clientCacheDate) { + return dynamicAttributesManagerAPI.getCacheIfNewer(clientCacheDate); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesImpl.java b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesImpl.java index 24a3800670..b7a83f2b20 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesImpl.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; - -import org.springframework.stereotype.Component; -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.Collection; - -@Component(DynamicAttributes.NAME) -public class DynamicAttributesImpl implements DynamicAttributes { - @Inject - protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; - - @Override - public Collection getCategoriesForMetaClass(MetaClass metaClass) { - return dynamicAttributesManagerAPI.getCategoriesForMetaClass(metaClass); - } - - @Override - public Collection getAttributesForMetaClass(MetaClass metaClass){ - return dynamicAttributesManagerAPI.getAttributesForMetaClass(metaClass); - } - - @Nullable - @Override - public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { - return dynamicAttributesManagerAPI.getAttributeForMetaClass(metaClass, code); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; + +import org.springframework.stereotype.Component; +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.Collection; + +@Component(DynamicAttributes.NAME) +public class DynamicAttributesImpl implements DynamicAttributes { + @Inject + protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; + + @Override + public Collection getCategoriesForMetaClass(MetaClass metaClass) { + return dynamicAttributesManagerAPI.getCategoriesForMetaClass(metaClass); + } + + @Override + public Collection getAttributesForMetaClass(MetaClass metaClass){ + return dynamicAttributesManagerAPI.getAttributesForMetaClass(metaClass); + } + + @Nullable + @Override + public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { + return dynamicAttributesManagerAPI.getAttributeForMetaClass(metaClass, code); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManager.java b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManager.java index eeb0970432..2c5936cc95 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManager.java +++ b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManager.java @@ -1,497 +1,497 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.app.ClusterListenerAdapter; -import com.haulmont.cuba.core.app.ClusterManagerAPI; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.*; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.BooleanUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; - -import static java.lang.String.format; - -@Component(DynamicAttributesManagerAPI.NAME) -public class DynamicAttributesManager implements DynamicAttributesManagerAPI { - public static final int MAX_ENTITIES_FOR_ATTRIBUTE_VALUES_BATCH = 100; - - protected Logger log = LoggerFactory.getLogger(DynamicAttributesManager.class); - - @Inject - protected Metadata metadata; - - @Inject - protected TimeSource timeSource; - - @Inject - protected ViewRepository viewRepository; - - @Inject - protected Persistence persistence; - - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - - protected ClusterManagerAPI clusterManager; - - protected ReentrantLock loadCacheLock = new ReentrantLock(); - - protected volatile DynamicAttributesCache dynamicAttributesCache; - - @Inject - public void setClusterManager(ClusterManagerAPI clusterManager) { - this.clusterManager = clusterManager; - clusterManager.addListener(ReloadCacheMsg.class, new ClusterListenerAdapter() { - @Override - public void receive(ReloadCacheMsg message) { - doLoadCache(false, false); - } - }); - } - - @Override - public void loadCache() { - doLoadCache(true, false); - } - - protected void doLoadCache(boolean sendClusterMessage, boolean stopIfNotNull) { - loadCacheLock.lock(); - Transaction tx = persistence.createTransaction(); - try { - if (stopIfNotNull && dynamicAttributesCache != null) { - return; - } - - EntityManager entityManager = persistence.getEntityManager(); - TypedQuery query = entityManager.createQuery("select c from sys$Category c", Category.class); - query.setViewName("for.cache"); - List resultList = query.getResultList(); - - Multimap categoriesCache = HashMultimap.create(); - Map> attributesCache = new LinkedHashMap<>(); - - for (Category category : resultList) { - MetaClass metaClass = resolveTargetMetaClass(metadata.getSession().getClass(category.getEntityType())); - if (metaClass != null) { - categoriesCache.put(metaClass.getName(), category); - Map attributes = attributesCache.get(metaClass.getName()); - if (attributes == null) { - attributes = new LinkedHashMap<>(); - attributesCache.put(metaClass.getName(), attributes); - } - - for (CategoryAttribute categoryAttribute : category.getCategoryAttrs()) { - attributes.put(categoryAttribute.getCode(), categoryAttribute); - } - } else { - log.warn(format("Could not resolve meta class name [%s] for the category [%s].", - category.getEntityType(), category.getName())); - } - } - tx.commit(); - - dynamicAttributesCache = new DynamicAttributesCache(categoriesCache, attributesCache, timeSource.currentTimestamp()); - if (sendClusterMessage) { - clusterManager.send(new ReloadCacheMsg()); - } - } finally { - loadCacheLock.unlock(); - tx.end(); - } - } - - @Override - public Collection getCategoriesForMetaClass(MetaClass metaClass) { - return cache().getCategoriesForMetaClass(metaClass); - } - - @Override - public Collection getAttributesForMetaClass(MetaClass metaClass) { - return cache().getAttributesForMetaClass(metaClass); - } - - @Nullable - @Override - public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { - return cache().getAttributeForMetaClass(metaClass, code); - } - - @Override - public DynamicAttributesCache getCacheIfNewer(Date clientCacheDate) { - if (clientCacheDate == null - || this.dynamicAttributesCache == null - || this.dynamicAttributesCache.getCreationDate() == null - || clientCacheDate.before(this.dynamicAttributesCache.getCreationDate())) { - return cache(); - } else { - return null; - } - } - - protected DynamicAttributesCache cache() { - if (this.dynamicAttributesCache == null) { - doLoadCache(true, true); - } - return this.dynamicAttributesCache; - } - - @Nullable - protected MetaClass resolveTargetMetaClass(MetaClass metaClass) { - if (metaClass == null) { - return null; - } - - MetaClass targetMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); - if (targetMetaClass == null) { - targetMetaClass = metaClass; - } - return targetMetaClass; - } - - @Override - public void storeDynamicAttributes(BaseGenericIdEntity entity) { - try (Transaction tx = persistence.getTransaction()) { - doStoreDynamicAttributes(entity); - tx.commit(); - } - } - - @Override - public void fetchDynamicAttributes(List entities, @Nonnull Set dependentClasses) { - Set toProcess = new HashSet<>(); - entities.forEach(entity -> { - toProcess.add(entity); - if (!dependentClasses.isEmpty()) { - metadata.getTools().traverseAttributes(entity, new EntityAttributeVisitor() { - @Override - public void visit(Entity dependentEntity, MetaProperty property) { - if (dependentEntity instanceof BaseGenericIdEntity) { - toProcess.add((BaseGenericIdEntity) dependentEntity); - } - } - - @Override - public boolean skip(MetaProperty property) { - return metadata.getTools().isPersistent(property) - && property.getRange().isClass() - && dependentClasses.contains(property.getJavaType()); - } - }); - } - }); - if (toProcess.isEmpty()) - return; - - try (Transaction tx = persistence.getTransaction()) { - Multimap entitiesByType = HashMultimap.create(); - toProcess.forEach(e -> entitiesByType.put(e.getMetaClass().getName(), e)); - entitiesByType.keySet().forEach(entityType -> { - MetaClass metaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metadata.getClass(entityType)); - doFetchDynamicAttributes(metaClass, entitiesByType.get(entityType)); - }); - tx.commit(); - } - } - - @SuppressWarnings("unchecked") - protected void doStoreDynamicAttributes(BaseGenericIdEntity entity) { - final EntityManager em = persistence.getEntityManager(); - Map dynamicAttributes = entity.getDynamicAttributes(); - if (dynamicAttributes != null) { - Map mergedDynamicAttributes = new HashMap<>(); - for (Map.Entry entry : dynamicAttributes.entrySet()) { - CategoryAttributeValue categoryAttributeValue = entry.getValue(); - if (categoryAttributeValue.getCategoryAttribute() == null - && categoryAttributeValue.getCode() != null) { - CategoryAttribute attribute = - getAttributeForMetaClass(entity.getMetaClass(), categoryAttributeValue.getCode()); - categoryAttributeValue.setCategoryAttribute(attribute); - } - - //remove deleted and empty attributes - if (categoryAttributeValue.getDeleteTs() == null && categoryAttributeValue.getValue() != null) { - if (entity instanceof BaseDbGeneratedIdEntity && categoryAttributeValue.getObjectEntityId() == null) { - categoryAttributeValue.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); - } - CategoryAttributeValue mergedCategoryAttributeValue = em.merge(categoryAttributeValue); - mergedCategoryAttributeValue.setCategoryAttribute(categoryAttributeValue.getCategoryAttribute()); - - //copy transient fields (for nested CAVs as well) - mergedCategoryAttributeValue.setTransientEntityValue(categoryAttributeValue.getTransientEntityValue()); - mergedCategoryAttributeValue.setTransientCollectionValue(categoryAttributeValue.getTransientCollectionValue()); - if (BooleanUtils.isTrue(categoryAttributeValue.getCategoryAttribute().getIsCollection()) && categoryAttributeValue.getChildValues() != null) { - for (CategoryAttributeValue childCAV : categoryAttributeValue.getChildValues()) { - for (CategoryAttributeValue mergedChildCAV : mergedCategoryAttributeValue.getChildValues()) { - if (mergedChildCAV.getId().equals(childCAV.getId())) { - mergedChildCAV.setTransientEntityValue(childCAV.getTransientEntityValue()); - break; - } - } - - } - } - - if (BooleanUtils.isTrue(mergedCategoryAttributeValue.getCategoryAttribute().getIsCollection())) { - storeCategoryAttributeValueWithCollectionType(mergedCategoryAttributeValue); - } - - mergedDynamicAttributes.put(entry.getKey(), mergedCategoryAttributeValue); - } else { - em.remove(categoryAttributeValue); - } - } - - entity.setDynamicAttributes(mergedDynamicAttributes); - } - } - - /** - * Removes nested {@code CategoryAttributeValue} entities for items that were removed from the collection value - * and creates new child {@code CategoryAttributeValue} instances for just added collection value items. - * - * @param categoryAttributeValue - */ - protected void storeCategoryAttributeValueWithCollectionType(CategoryAttributeValue categoryAttributeValue) { - EntityManager em = persistence.getEntityManager(); - - List collectionValue = categoryAttributeValue.getTransientCollectionValue(); - List newCollectionValue = new ArrayList<>(collectionValue); - - //remove existing child CategoryAttributeValues that are not in the CategoryAttributeValue.collectionValue property - if (categoryAttributeValue.getChildValues() != null) { - for (CategoryAttributeValue existingChildCategoryAttributeValue : categoryAttributeValue.getChildValues()) { - Object value = existingChildCategoryAttributeValue.getValue(); - if (!collectionValue.contains(value)) { - em.remove(existingChildCategoryAttributeValue); - } - newCollectionValue.remove(value); - } - } - - //newCollectionValue now contains only the values that were added but not persisted yet - newCollectionValue.forEach(value -> { - CategoryAttributeValue childCAV = metadata.create(CategoryAttributeValue.class); - childCAV.setParent(categoryAttributeValue); - childCAV.setValue(value); - if (categoryAttributeValue.getObjectEntityId() != null) { - childCAV.setObjectEntityId(categoryAttributeValue.getObjectEntityId()); - } - childCAV.setCode(categoryAttributeValue.getCode()); - childCAV.setCategoryAttribute(categoryAttributeValue.getCategoryAttribute()); - em.persist(childCAV); - }); - } - - protected void doFetchDynamicAttributes(MetaClass metaClass, Collection entities) { - List ids = entities.stream() - .map(e -> referenceToEntitySupport.getReferenceId(e)) - .collect(Collectors.toList()); - - Multimap allAttributeValues = HashMultimap.create(); - - List currentIds = new ArrayList<>(); - for (Object id : ids) { - currentIds.add(id); - if (currentIds.size() >= MAX_ENTITIES_FOR_ATTRIBUTE_VALUES_BATCH) { - handleAttributeValuesForIds(metaClass, currentIds, allAttributeValues); - currentIds = new ArrayList<>(); - } - } - handleAttributeValuesForIds(metaClass, currentIds, allAttributeValues); - - for (BaseGenericIdEntity entity : entities) { - Collection entityAttributeValues = allAttributeValues.get(referenceToEntitySupport.getReferenceId(entity)); - Map map = new HashMap<>(); - entity.setDynamicAttributes(map); - if (CollectionUtils.isNotEmpty(entityAttributeValues)) { - for (CategoryAttributeValue categoryAttributeValue : entityAttributeValues) { - CategoryAttribute attribute = categoryAttributeValue.getCategoryAttribute(); - if (attribute != null) { - map.put(attribute.getCode(), categoryAttributeValue); - } - } - } - } - } - - protected void handleAttributeValuesForIds(MetaClass metaClass, List currentIds, Multimap attributeValuesForEntity) { - if (CollectionUtils.isNotEmpty(currentIds)) { - for (CategoryAttributeValue attributeValue : loadAttributeValues(metaClass, currentIds)) { - attributeValuesForEntity.put(attributeValue.getObjectEntityId(), attributeValue); - } - } - } - - protected List loadAttributeValues(MetaClass metaClass, List entityIds) { - List attributeValues = new ArrayList<>(); - try (Transaction tx = persistence.getTransaction()) { - EntityManager em = persistence.getEntityManager(); - - View view = new View(viewRepository.getView(CategoryAttributeValue.class, View.LOCAL), null, false) - .addProperty("categoryAttribute", new View(viewRepository.getView(CategoryAttribute.class, View.LOCAL), null, false) - .addProperty("category") - .addProperty("defaultEntity", viewRepository.getView(ReferenceToEntity.class, View.LOCAL))); - - TypedQuery query; - if (HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { - query = em.createQuery(format("select cav from sys$CategoryAttributeValue cav where cav.entity.%s in :ids and cav.parent is null", - referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), - CategoryAttributeValue.class); - } else { - query = em.createQuery(format("select cav from sys$CategoryAttributeValue cav where cav.entity.%s in :ids " + - "and cav.categoryAttribute.categoryEntityType = :entityType and cav.parent is null", - referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), - CategoryAttributeValue.class); - query.setParameter("entityType", metaClass.getName()); - } - query.setParameter("ids", entityIds); - query.setView(view); - List resultList = query.getResultList(); - - List cavsOfEntityType = resultList.stream() - .filter(cav -> cav.getObjectEntityValueId() != null) - .collect(Collectors.toList()); - - List cavsOfCollectionType = resultList.stream() - .filter(cav -> cav.getCategoryAttribute().getIsCollection()) - .collect(Collectors.toList()); - - if (cavsOfCollectionType.isEmpty()) { - loadEntityValues(cavsOfEntityType); - attributeValues.addAll(resultList); - } else { - List cavsOfCollectionTypeWithChildren = reloadCategoryAttributeValuesWithChildren(cavsOfCollectionType); - - //add nested collection values to the cavsOfEntityType collection, because this collection will later be - //used for loading entity values - cavsOfCollectionTypeWithChildren.stream() - .filter(cav -> cav.getCategoryAttribute().getDataType() == PropertyType.ENTITY && cav.getChildValues() != null) - .forEach(cav -> cavsOfEntityType.addAll(cav.getChildValues())); - - loadEntityValues(cavsOfEntityType); - - cavsOfCollectionTypeWithChildren.stream() - .filter(cav -> cav.getChildValues() != null) - .forEach(cav -> { - List value = cav.getChildValues().stream() - .map(CategoryAttributeValue::getValue) - .collect(Collectors.toList()); - cav.setTransientCollectionValue(value); - }); - - attributeValues.addAll(resultList.stream() - .filter(cav -> !cavsOfCollectionTypeWithChildren.contains(cav)) - .collect(Collectors.toList())); - - attributeValues.addAll(cavsOfCollectionTypeWithChildren); - } - - tx.commit(); - } - return attributeValues; - } - - /** - * Method loads entity values for CategoryAttributeValues of entity type and sets entity values to the corresponding - * property of the {@code CategoryAttributeValue} entity. - */ - @SuppressWarnings("unchecked") - protected void loadEntityValues(List cavsOfEntityType) { - HashMultimap entitiesIdsToBeLoaded = HashMultimap.create(); - HashMultimap cavByType = HashMultimap.create(); - - cavsOfEntityType.forEach(cav -> { - String className = cav.getCategoryAttribute().getEntityClass(); - try { - Class aClass = Class.forName(className); - MetaClass metaClass = metadata.getClass(aClass); - entitiesIdsToBeLoaded.put(metaClass, cav.getObjectEntityValueId()); - cavByType.put(metaClass, cav); - } catch (ClassNotFoundException e) { - log.error("Class {} not found", className); - } - }); - - EntityManager em = persistence.getEntityManager(); - - for (Map.Entry> entry : entitiesIdsToBeLoaded.asMap().entrySet()) { - Map idToEntityMap = new HashMap<>(); - MetaClass metaClass = entry.getKey(); - Collection ids = entry.getValue(); - - if (!ids.isEmpty()) { - String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); - List entitiesValues = em.createQuery(format("select e from %s e where e.%s in :ids", metaClass.getName(), pkName)) - .setParameter("ids", ids) - .setView(metaClass.getJavaClass(), View.MINIMAL) - .getResultList(); - - for (BaseGenericIdEntity entity : entitiesValues) { - idToEntityMap.put(entity.getId(), entity); - } - } - - for (CategoryAttributeValue cav : cavByType.get(metaClass)) { - cav.setTransientEntityValue(idToEntityMap.get(cav.getObjectEntityValueId())); - } - } - } - - protected List reloadCategoryAttributeValuesWithChildren(List categoryAttributeValues) { - EntityManager em = persistence.getEntityManager(); - - View categoryAttributeValueLocalView = viewRepository.getView(CategoryAttributeValue.class, View.LOCAL); - View categoryAttributeLocalView = viewRepository.getView(CategoryAttribute.class, View.LOCAL); - - View view = new View(categoryAttributeValueLocalView, null, false) - .addProperty("categoryAttribute", new View(categoryAttributeLocalView, null, false).addProperty("category")) - .addProperty("childValues", categoryAttributeValueLocalView); - - List ids = categoryAttributeValues.stream() - .map(BaseUuidEntity::getId) - .collect(Collectors.toList()); - - return em.createQuery("select cav from sys$CategoryAttributeValue cav where cav.id in :ids", CategoryAttributeValue.class) - .setParameter("ids", ids) - .setView(view) - .getResultList(); - } - - private static class ReloadCacheMsg implements Serializable { - private static final long serialVersionUID = -3116358584797500962L; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.app.ClusterListenerAdapter; +import com.haulmont.cuba.core.app.ClusterManagerAPI; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.*; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; + +import static java.lang.String.format; + +@Component(DynamicAttributesManagerAPI.NAME) +public class DynamicAttributesManager implements DynamicAttributesManagerAPI { + public static final int MAX_ENTITIES_FOR_ATTRIBUTE_VALUES_BATCH = 100; + + protected Logger log = LoggerFactory.getLogger(DynamicAttributesManager.class); + + @Inject + protected Metadata metadata; + + @Inject + protected TimeSource timeSource; + + @Inject + protected ViewRepository viewRepository; + + @Inject + protected Persistence persistence; + + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + + protected ClusterManagerAPI clusterManager; + + protected ReentrantLock loadCacheLock = new ReentrantLock(); + + protected volatile DynamicAttributesCache dynamicAttributesCache; + + @Inject + public void setClusterManager(ClusterManagerAPI clusterManager) { + this.clusterManager = clusterManager; + clusterManager.addListener(ReloadCacheMsg.class, new ClusterListenerAdapter() { + @Override + public void receive(ReloadCacheMsg message) { + doLoadCache(false, false); + } + }); + } + + @Override + public void loadCache() { + doLoadCache(true, false); + } + + protected void doLoadCache(boolean sendClusterMessage, boolean stopIfNotNull) { + loadCacheLock.lock(); + Transaction tx = persistence.createTransaction(); + try { + if (stopIfNotNull && dynamicAttributesCache != null) { + return; + } + + EntityManager entityManager = persistence.getEntityManager(); + TypedQuery query = entityManager.createQuery("select c from sys$Category c", Category.class); + query.setViewName("for.cache"); + List resultList = query.getResultList(); + + Multimap categoriesCache = HashMultimap.create(); + Map> attributesCache = new LinkedHashMap<>(); + + for (Category category : resultList) { + MetaClass metaClass = resolveTargetMetaClass(metadata.getSession().getClass(category.getEntityType())); + if (metaClass != null) { + categoriesCache.put(metaClass.getName(), category); + Map attributes = attributesCache.get(metaClass.getName()); + if (attributes == null) { + attributes = new LinkedHashMap<>(); + attributesCache.put(metaClass.getName(), attributes); + } + + for (CategoryAttribute categoryAttribute : category.getCategoryAttrs()) { + attributes.put(categoryAttribute.getCode(), categoryAttribute); + } + } else { + log.warn(format("Could not resolve meta class name [%s] for the category [%s].", + category.getEntityType(), category.getName())); + } + } + tx.commit(); + + dynamicAttributesCache = new DynamicAttributesCache(categoriesCache, attributesCache, timeSource.currentTimestamp()); + if (sendClusterMessage) { + clusterManager.send(new ReloadCacheMsg()); + } + } finally { + loadCacheLock.unlock(); + tx.end(); + } + } + + @Override + public Collection getCategoriesForMetaClass(MetaClass metaClass) { + return cache().getCategoriesForMetaClass(metaClass); + } + + @Override + public Collection getAttributesForMetaClass(MetaClass metaClass) { + return cache().getAttributesForMetaClass(metaClass); + } + + @Nullable + @Override + public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { + return cache().getAttributeForMetaClass(metaClass, code); + } + + @Override + public DynamicAttributesCache getCacheIfNewer(Date clientCacheDate) { + if (clientCacheDate == null + || this.dynamicAttributesCache == null + || this.dynamicAttributesCache.getCreationDate() == null + || clientCacheDate.before(this.dynamicAttributesCache.getCreationDate())) { + return cache(); + } else { + return null; + } + } + + protected DynamicAttributesCache cache() { + if (this.dynamicAttributesCache == null) { + doLoadCache(true, true); + } + return this.dynamicAttributesCache; + } + + @Nullable + protected MetaClass resolveTargetMetaClass(MetaClass metaClass) { + if (metaClass == null) { + return null; + } + + MetaClass targetMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); + if (targetMetaClass == null) { + targetMetaClass = metaClass; + } + return targetMetaClass; + } + + @Override + public void storeDynamicAttributes(BaseGenericIdEntity entity) { + try (Transaction tx = persistence.getTransaction()) { + doStoreDynamicAttributes(entity); + tx.commit(); + } + } + + @Override + public void fetchDynamicAttributes(List entities, @Nonnull Set dependentClasses) { + Set toProcess = new HashSet<>(); + entities.forEach(entity -> { + toProcess.add(entity); + if (!dependentClasses.isEmpty()) { + metadata.getTools().traverseAttributes(entity, new EntityAttributeVisitor() { + @Override + public void visit(Entity dependentEntity, MetaProperty property) { + if (dependentEntity instanceof BaseGenericIdEntity) { + toProcess.add((BaseGenericIdEntity) dependentEntity); + } + } + + @Override + public boolean skip(MetaProperty property) { + return metadata.getTools().isPersistent(property) + && property.getRange().isClass() + && dependentClasses.contains(property.getJavaType()); + } + }); + } + }); + if (toProcess.isEmpty()) + return; + + try (Transaction tx = persistence.getTransaction()) { + Multimap entitiesByType = HashMultimap.create(); + toProcess.forEach(e -> entitiesByType.put(e.getMetaClass().getName(), e)); + entitiesByType.keySet().forEach(entityType -> { + MetaClass metaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(metadata.getClass(entityType)); + doFetchDynamicAttributes(metaClass, entitiesByType.get(entityType)); + }); + tx.commit(); + } + } + + @SuppressWarnings("unchecked") + protected void doStoreDynamicAttributes(BaseGenericIdEntity entity) { + final EntityManager em = persistence.getEntityManager(); + Map dynamicAttributes = entity.getDynamicAttributes(); + if (dynamicAttributes != null) { + Map mergedDynamicAttributes = new HashMap<>(); + for (Map.Entry entry : dynamicAttributes.entrySet()) { + CategoryAttributeValue categoryAttributeValue = entry.getValue(); + if (categoryAttributeValue.getCategoryAttribute() == null + && categoryAttributeValue.getCode() != null) { + CategoryAttribute attribute = + getAttributeForMetaClass(entity.getMetaClass(), categoryAttributeValue.getCode()); + categoryAttributeValue.setCategoryAttribute(attribute); + } + + //remove deleted and empty attributes + if (categoryAttributeValue.getDeleteTs() == null && categoryAttributeValue.getValue() != null) { + if (entity instanceof BaseDbGeneratedIdEntity && categoryAttributeValue.getObjectEntityId() == null) { + categoryAttributeValue.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); + } + CategoryAttributeValue mergedCategoryAttributeValue = em.merge(categoryAttributeValue); + mergedCategoryAttributeValue.setCategoryAttribute(categoryAttributeValue.getCategoryAttribute()); + + //copy transient fields (for nested CAVs as well) + mergedCategoryAttributeValue.setTransientEntityValue(categoryAttributeValue.getTransientEntityValue()); + mergedCategoryAttributeValue.setTransientCollectionValue(categoryAttributeValue.getTransientCollectionValue()); + if (BooleanUtils.isTrue(categoryAttributeValue.getCategoryAttribute().getIsCollection()) && categoryAttributeValue.getChildValues() != null) { + for (CategoryAttributeValue childCAV : categoryAttributeValue.getChildValues()) { + for (CategoryAttributeValue mergedChildCAV : mergedCategoryAttributeValue.getChildValues()) { + if (mergedChildCAV.getId().equals(childCAV.getId())) { + mergedChildCAV.setTransientEntityValue(childCAV.getTransientEntityValue()); + break; + } + } + + } + } + + if (BooleanUtils.isTrue(mergedCategoryAttributeValue.getCategoryAttribute().getIsCollection())) { + storeCategoryAttributeValueWithCollectionType(mergedCategoryAttributeValue); + } + + mergedDynamicAttributes.put(entry.getKey(), mergedCategoryAttributeValue); + } else { + em.remove(categoryAttributeValue); + } + } + + entity.setDynamicAttributes(mergedDynamicAttributes); + } + } + + /** + * Removes nested {@code CategoryAttributeValue} entities for items that were removed from the collection value + * and creates new child {@code CategoryAttributeValue} instances for just added collection value items. + * + * @param categoryAttributeValue + */ + protected void storeCategoryAttributeValueWithCollectionType(CategoryAttributeValue categoryAttributeValue) { + EntityManager em = persistence.getEntityManager(); + + List collectionValue = categoryAttributeValue.getTransientCollectionValue(); + List newCollectionValue = new ArrayList<>(collectionValue); + + //remove existing child CategoryAttributeValues that are not in the CategoryAttributeValue.collectionValue property + if (categoryAttributeValue.getChildValues() != null) { + for (CategoryAttributeValue existingChildCategoryAttributeValue : categoryAttributeValue.getChildValues()) { + Object value = existingChildCategoryAttributeValue.getValue(); + if (!collectionValue.contains(value)) { + em.remove(existingChildCategoryAttributeValue); + } + newCollectionValue.remove(value); + } + } + + //newCollectionValue now contains only the values that were added but not persisted yet + newCollectionValue.forEach(value -> { + CategoryAttributeValue childCAV = metadata.create(CategoryAttributeValue.class); + childCAV.setParent(categoryAttributeValue); + childCAV.setValue(value); + if (categoryAttributeValue.getObjectEntityId() != null) { + childCAV.setObjectEntityId(categoryAttributeValue.getObjectEntityId()); + } + childCAV.setCode(categoryAttributeValue.getCode()); + childCAV.setCategoryAttribute(categoryAttributeValue.getCategoryAttribute()); + em.persist(childCAV); + }); + } + + protected void doFetchDynamicAttributes(MetaClass metaClass, Collection entities) { + List ids = entities.stream() + .map(e -> referenceToEntitySupport.getReferenceId(e)) + .collect(Collectors.toList()); + + Multimap allAttributeValues = HashMultimap.create(); + + List currentIds = new ArrayList<>(); + for (Object id : ids) { + currentIds.add(id); + if (currentIds.size() >= MAX_ENTITIES_FOR_ATTRIBUTE_VALUES_BATCH) { + handleAttributeValuesForIds(metaClass, currentIds, allAttributeValues); + currentIds = new ArrayList<>(); + } + } + handleAttributeValuesForIds(metaClass, currentIds, allAttributeValues); + + for (BaseGenericIdEntity entity : entities) { + Collection entityAttributeValues = allAttributeValues.get(referenceToEntitySupport.getReferenceId(entity)); + Map map = new HashMap<>(); + entity.setDynamicAttributes(map); + if (CollectionUtils.isNotEmpty(entityAttributeValues)) { + for (CategoryAttributeValue categoryAttributeValue : entityAttributeValues) { + CategoryAttribute attribute = categoryAttributeValue.getCategoryAttribute(); + if (attribute != null) { + map.put(attribute.getCode(), categoryAttributeValue); + } + } + } + } + } + + protected void handleAttributeValuesForIds(MetaClass metaClass, List currentIds, Multimap attributeValuesForEntity) { + if (CollectionUtils.isNotEmpty(currentIds)) { + for (CategoryAttributeValue attributeValue : loadAttributeValues(metaClass, currentIds)) { + attributeValuesForEntity.put(attributeValue.getObjectEntityId(), attributeValue); + } + } + } + + protected List loadAttributeValues(MetaClass metaClass, List entityIds) { + List attributeValues = new ArrayList<>(); + try (Transaction tx = persistence.getTransaction()) { + EntityManager em = persistence.getEntityManager(); + + View view = new View(viewRepository.getView(CategoryAttributeValue.class, View.LOCAL), null, false) + .addProperty("categoryAttribute", new View(viewRepository.getView(CategoryAttribute.class, View.LOCAL), null, false) + .addProperty("category") + .addProperty("defaultEntity", viewRepository.getView(ReferenceToEntity.class, View.LOCAL))); + + TypedQuery query; + if (HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { + query = em.createQuery(format("select cav from sys$CategoryAttributeValue cav where cav.entity.%s in :ids and cav.parent is null", + referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), + CategoryAttributeValue.class); + } else { + query = em.createQuery(format("select cav from sys$CategoryAttributeValue cav where cav.entity.%s in :ids " + + "and cav.categoryAttribute.categoryEntityType = :entityType and cav.parent is null", + referenceToEntitySupport.getReferenceIdPropertyName(metaClass)), + CategoryAttributeValue.class); + query.setParameter("entityType", metaClass.getName()); + } + query.setParameter("ids", entityIds); + query.setView(view); + List resultList = query.getResultList(); + + List cavsOfEntityType = resultList.stream() + .filter(cav -> cav.getObjectEntityValueId() != null) + .collect(Collectors.toList()); + + List cavsOfCollectionType = resultList.stream() + .filter(cav -> cav.getCategoryAttribute().getIsCollection()) + .collect(Collectors.toList()); + + if (cavsOfCollectionType.isEmpty()) { + loadEntityValues(cavsOfEntityType); + attributeValues.addAll(resultList); + } else { + List cavsOfCollectionTypeWithChildren = reloadCategoryAttributeValuesWithChildren(cavsOfCollectionType); + + //add nested collection values to the cavsOfEntityType collection, because this collection will later be + //used for loading entity values + cavsOfCollectionTypeWithChildren.stream() + .filter(cav -> cav.getCategoryAttribute().getDataType() == PropertyType.ENTITY && cav.getChildValues() != null) + .forEach(cav -> cavsOfEntityType.addAll(cav.getChildValues())); + + loadEntityValues(cavsOfEntityType); + + cavsOfCollectionTypeWithChildren.stream() + .filter(cav -> cav.getChildValues() != null) + .forEach(cav -> { + List value = cav.getChildValues().stream() + .map(CategoryAttributeValue::getValue) + .collect(Collectors.toList()); + cav.setTransientCollectionValue(value); + }); + + attributeValues.addAll(resultList.stream() + .filter(cav -> !cavsOfCollectionTypeWithChildren.contains(cav)) + .collect(Collectors.toList())); + + attributeValues.addAll(cavsOfCollectionTypeWithChildren); + } + + tx.commit(); + } + return attributeValues; + } + + /** + * Method loads entity values for CategoryAttributeValues of entity type and sets entity values to the corresponding + * property of the {@code CategoryAttributeValue} entity. + */ + @SuppressWarnings("unchecked") + protected void loadEntityValues(List cavsOfEntityType) { + HashMultimap entitiesIdsToBeLoaded = HashMultimap.create(); + HashMultimap cavByType = HashMultimap.create(); + + cavsOfEntityType.forEach(cav -> { + String className = cav.getCategoryAttribute().getEntityClass(); + try { + Class aClass = Class.forName(className); + MetaClass metaClass = metadata.getClass(aClass); + entitiesIdsToBeLoaded.put(metaClass, cav.getObjectEntityValueId()); + cavByType.put(metaClass, cav); + } catch (ClassNotFoundException e) { + log.error("Class {} not found", className); + } + }); + + EntityManager em = persistence.getEntityManager(); + + for (Map.Entry> entry : entitiesIdsToBeLoaded.asMap().entrySet()) { + Map idToEntityMap = new HashMap<>(); + MetaClass metaClass = entry.getKey(); + Collection ids = entry.getValue(); + + if (!ids.isEmpty()) { + String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); + List entitiesValues = em.createQuery(format("select e from %s e where e.%s in :ids", metaClass.getName(), pkName)) + .setParameter("ids", ids) + .setView(metaClass.getJavaClass(), View.MINIMAL) + .getResultList(); + + for (BaseGenericIdEntity entity : entitiesValues) { + idToEntityMap.put(entity.getId(), entity); + } + } + + for (CategoryAttributeValue cav : cavByType.get(metaClass)) { + cav.setTransientEntityValue(idToEntityMap.get(cav.getObjectEntityValueId())); + } + } + } + + protected List reloadCategoryAttributeValuesWithChildren(List categoryAttributeValues) { + EntityManager em = persistence.getEntityManager(); + + View categoryAttributeValueLocalView = viewRepository.getView(CategoryAttributeValue.class, View.LOCAL); + View categoryAttributeLocalView = viewRepository.getView(CategoryAttribute.class, View.LOCAL); + + View view = new View(categoryAttributeValueLocalView, null, false) + .addProperty("categoryAttribute", new View(categoryAttributeLocalView, null, false).addProperty("category")) + .addProperty("childValues", categoryAttributeValueLocalView); + + List ids = categoryAttributeValues.stream() + .map(BaseUuidEntity::getId) + .collect(Collectors.toList()); + + return em.createQuery("select cav from sys$CategoryAttributeValue cav where cav.id in :ids", CategoryAttributeValue.class) + .setParameter("ids", ids) + .setView(view) + .getResultList(); + } + + private static class ReloadCacheMsg implements Serializable { + private static final long serialVersionUID = -3116358584797500962L; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManagerAPI.java b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManagerAPI.java index 0a404550d9..268518e834 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManagerAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesManagerAPI.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Set; - -public interface DynamicAttributesManagerAPI { - String NAME = "cuba_DynamicAttributesManager"; - - /** - * Reload dynamic attributes cache from database - */ - void loadCache(); - - /** - * Get all categories linked with metaClass from cache - */ - Collection getCategoriesForMetaClass(MetaClass metaClass); - - /** - * Get all categories attributes for metaClass from cache - */ - Collection getAttributesForMetaClass(MetaClass metaClass); - - /** - * Get certain category attribute for metaClass by attribute code - */ - @Nullable - CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code); - - @Nullable - DynamicAttributesCache getCacheIfNewer(Date clientCacheDate); - - /** - * Fetch dynamic attributes from database for each entity - */ - void fetchDynamicAttributes(List entities, @Nonnull Set dependentClasses); - - /** - * Store dynamic attributes from the entity to database - */ - void storeDynamicAttributes(BaseGenericIdEntity entity); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; + +public interface DynamicAttributesManagerAPI { + String NAME = "cuba_DynamicAttributesManager"; + + /** + * Reload dynamic attributes cache from database + */ + void loadCache(); + + /** + * Get all categories linked with metaClass from cache + */ + Collection getCategoriesForMetaClass(MetaClass metaClass); + + /** + * Get all categories attributes for metaClass from cache + */ + Collection getAttributesForMetaClass(MetaClass metaClass); + + /** + * Get certain category attribute for metaClass by attribute code + */ + @Nullable + CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code); + + @Nullable + DynamicAttributesCache getCacheIfNewer(Date clientCacheDate); + + /** + * Fetch dynamic attributes from database for each entity + */ + void fetchDynamicAttributes(List entities, @Nonnull Set dependentClasses); + + /** + * Store dynamic attributes from the entity to database + */ + void storeDynamicAttributes(BaseGenericIdEntity entity); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/filestorage/FileStorage.java b/modules/core/src/com/haulmont/cuba/core/app/filestorage/FileStorage.java index 32e4ef857c..e9dd60f15e 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/filestorage/FileStorage.java +++ b/modules/core/src/com/haulmont/cuba/core/app/filestorage/FileStorage.java @@ -1,336 +1,336 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app.filestorage; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.haulmont.cuba.core.app.FileStorageAPI; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.inject.Inject; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -@Component(FileStorageAPI.NAME) -public class FileStorage implements FileStorageAPI { - - private final Logger log = LoggerFactory.getLogger(FileStorage.class); - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected TimeSource timeSource; - - @Inject - protected Configuration configuration; - - protected boolean isImmutableFileStorage; - - protected ExecutorService writeExecutor = Executors.newFixedThreadPool(5, - new ThreadFactoryBuilder().setNameFormat("FileStorageWriter-%d").build()); - - protected volatile File[] storageRoots; - - @PostConstruct - public void init() { - this.isImmutableFileStorage = configuration.getConfig(ServerConfig.class).getImmutableFileStorage(); - } - - /** - * INTERNAL. Don't use in application code. - */ - public File[] getStorageRoots() { - if (storageRoots == null) { - String conf = configuration.getConfig(ServerConfig.class).getFileStorageDir(); - if (StringUtils.isBlank(conf)) { - String dataDir = configuration.getConfig(GlobalConfig.class).getDataDir(); - File dir = new File(dataDir, "filestorage"); - dir.mkdirs(); - storageRoots = new File[]{dir}; - } else { - List list = new ArrayList<>(); - for (String str : conf.split(",")) { - str = str.trim(); - if (!StringUtils.isEmpty(str)) { - File file = new File(str); - if (!list.contains(file)) - list.add(file); - } - } - storageRoots = list.toArray(new File[list.size()]); - } - } - return storageRoots; - } - - @Override - public long saveStream(final FileDescriptor fileDescr, final InputStream inputStream) throws FileStorageException { - checkFileDescriptor(fileDescr); - - File[] roots = getStorageRoots(); - - // Store to primary storage - - checkStorageDefined(roots, fileDescr); - checkPrimaryStorageAccessible(roots, fileDescr); - - File dir = getStorageDir(roots[0], fileDescr); - dir.mkdirs(); - checkDirectoryExists(dir); - - final File file = new File(dir, getFileName(fileDescr)); - checkFileExists(file); - - long size = 0; - OutputStream os = null; - try { - os = FileUtils.openOutputStream(file); - size = IOUtils.copyLarge(inputStream, os); - os.flush(); - writeLog(file, false); - } catch (IOException e) { - IOUtils.closeQuietly(os); - FileUtils.deleteQuietly(file); - - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, file.getAbsolutePath(), e); - } finally { - IOUtils.closeQuietly(os); - } - - // Copy file to secondary storages asynchronously - - final SecurityContext securityContext = AppContext.getSecurityContext(); - for (int i = 1; i < roots.length; i++) { - if (!roots[i].exists()) { - log.error("Error saving {} into {} : directory doesn't exist", fileDescr, roots[i]); - continue; - } - - File copyDir = getStorageDir(roots[i], fileDescr); - final File fileCopy = new File(copyDir, getFileName(fileDescr)); - - writeExecutor.submit(new Runnable() { - @Override - public void run() { - try { - AppContext.setSecurityContext(securityContext); - FileUtils.copyFile(file, fileCopy, true); - writeLog(fileCopy, false); - } catch (Exception e) { - log.error("Error saving {} into {} : {}", fileDescr, fileCopy.getAbsolutePath(), e.getMessage()); - } finally { - AppContext.setSecurityContext(null); - } - } - }); - } - - return size; - } - - protected void checkFileExists(File file) throws FileStorageException { - if (file.exists() && isImmutableFileStorage) - throw new FileStorageException(FileStorageException.Type.FILE_ALREADY_EXISTS, file.getAbsolutePath()); - } - - protected void checkDirectoryExists(File dir) throws FileStorageException { - if (!dir.exists()) - throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, dir.getAbsolutePath()); - } - - protected void checkPrimaryStorageAccessible(File[] roots, FileDescriptor fileDescr) throws FileStorageException { - if (!roots[0].exists()) { - log.error("Inaccessible primary storage at {}", roots[0]); - throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString()); - } - } - - protected void checkStorageDefined(File[] roots, FileDescriptor fileDescr) throws FileStorageException { - if (roots.length == 0) { - log.error("No storage directories defined"); - throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString()); - } - } - - @Override - public void saveFile(final FileDescriptor fileDescr, final byte[] data) throws FileStorageException { - checkNotNullArgument(data, "File content is null"); - saveStream(fileDescr, new ByteArrayInputStream(data)); - } - - protected synchronized void writeLog(File file, boolean remove) { - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - - StringBuilder sb = new StringBuilder(); - sb.append(df.format(timeSource.currentTimestamp())).append(" "); - sb.append("[").append(userSessionSource.getUserSession().getUser()).append("] "); - sb.append(remove ? "REMOVE" : "CREATE").append(" "); - sb.append("\"").append(file.getAbsolutePath()).append("\"\n"); - - File rootDir; - try { - rootDir = file.getParentFile().getParentFile().getParentFile().getParentFile(); - } catch (NullPointerException e) { - log.error("Unable to write log: invalid file storage structure", e); - return; - } - File logFile = new File(rootDir, "storage.log"); - try { - try (FileOutputStream fos = new FileOutputStream(logFile, true)) { - IOUtils.write(sb.toString(), fos, StandardCharsets.UTF_8.name()); - } - } catch (IOException e) { - log.error("Unable to write log", e); - } - } - - @Override - public void removeFile(FileDescriptor fileDescr) throws FileStorageException { - checkFileDescriptor(fileDescr); - - File[] roots = getStorageRoots(); - if (roots.length == 0) { - log.error("No storage directories defined"); - return; - } - - for (File root : roots) { - File dir = getStorageDir(root, fileDescr); - File file = new File(dir, getFileName(fileDescr)); - if (file.exists()) { - if (!file.delete()) { - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, "Unable to delete file " + file.getAbsolutePath()); - } else { - writeLog(file, true); - } - } - } - } - - protected void checkFileDescriptor(FileDescriptor fd) { - if (fd == null || fd.getCreateDate() == null) { - throw new IllegalArgumentException("A FileDescriptor instance with populated 'createDate' attribute must be provided"); - } - } - - @Override - public InputStream openStream(FileDescriptor fileDescr) throws FileStorageException { - checkFileDescriptor(fileDescr); - - File[] roots = getStorageRoots(); - if (roots.length == 0) { - log.error("No storage directories available"); - throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString()); - } - - InputStream inputStream = null; - for (File root : roots) { - File dir = getStorageDir(root, fileDescr); - - File file = new File(dir, getFileName(fileDescr)); - if (!file.exists()) { - log.error("File " + file + " not found"); - continue; - } - - try { - inputStream = FileUtils.openInputStream(file); - break; - } catch (IOException e) { - log.error("Error opening input stream for " + file, e); - } - } - if (inputStream != null) - return inputStream; - else - throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString()); - } - - @Override - public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { - InputStream inputStream = openStream(fileDescr); - try { - return IOUtils.toByteArray(inputStream); - } catch (IOException e) { - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e); - } finally { - IOUtils.closeQuietly(inputStream); - } - } - - @Override - public boolean fileExists(FileDescriptor fileDescr) { - checkFileDescriptor(fileDescr); - - File[] roots = getStorageRoots(); - for (File root : roots) { - File dir = getStorageDir(root, fileDescr); - File file = new File(dir, getFileName(fileDescr)); - if (file.exists()) { - return true; - } - } - return false; - } - - /** - * INTERNAL. Don't use in application code. - */ - public File getStorageDir(File rootDir, FileDescriptor fileDescriptor) { - checkNotNullArgument(rootDir); - checkNotNullArgument(fileDescriptor); - - Calendar cal = Calendar.getInstance(); - cal.setTime(fileDescriptor.getCreateDate()); - int year = cal.get(Calendar.YEAR); - int month = cal.get(Calendar.MONTH) + 1; - int day = cal.get(Calendar.DAY_OF_MONTH); - - return new File(rootDir, year + "/" - + StringUtils.leftPad(String.valueOf(month), 2, '0') + "/" - + StringUtils.leftPad(String.valueOf(day), 2, '0')); - } - - public static String getFileName(FileDescriptor fileDescriptor) { - return fileDescriptor.getId().toString() + "." + fileDescriptor.getExtension(); - } - - @PreDestroy - protected void stopWriteExecutor() { - writeExecutor.shutdown(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app.filestorage; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.haulmont.cuba.core.app.FileStorageAPI; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +@Component(FileStorageAPI.NAME) +public class FileStorage implements FileStorageAPI { + + private final Logger log = LoggerFactory.getLogger(FileStorage.class); + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected TimeSource timeSource; + + @Inject + protected Configuration configuration; + + protected boolean isImmutableFileStorage; + + protected ExecutorService writeExecutor = Executors.newFixedThreadPool(5, + new ThreadFactoryBuilder().setNameFormat("FileStorageWriter-%d").build()); + + protected volatile File[] storageRoots; + + @PostConstruct + public void init() { + this.isImmutableFileStorage = configuration.getConfig(ServerConfig.class).getImmutableFileStorage(); + } + + /** + * INTERNAL. Don't use in application code. + */ + public File[] getStorageRoots() { + if (storageRoots == null) { + String conf = configuration.getConfig(ServerConfig.class).getFileStorageDir(); + if (StringUtils.isBlank(conf)) { + String dataDir = configuration.getConfig(GlobalConfig.class).getDataDir(); + File dir = new File(dataDir, "filestorage"); + dir.mkdirs(); + storageRoots = new File[]{dir}; + } else { + List list = new ArrayList<>(); + for (String str : conf.split(",")) { + str = str.trim(); + if (!StringUtils.isEmpty(str)) { + File file = new File(str); + if (!list.contains(file)) + list.add(file); + } + } + storageRoots = list.toArray(new File[list.size()]); + } + } + return storageRoots; + } + + @Override + public long saveStream(final FileDescriptor fileDescr, final InputStream inputStream) throws FileStorageException { + checkFileDescriptor(fileDescr); + + File[] roots = getStorageRoots(); + + // Store to primary storage + + checkStorageDefined(roots, fileDescr); + checkPrimaryStorageAccessible(roots, fileDescr); + + File dir = getStorageDir(roots[0], fileDescr); + dir.mkdirs(); + checkDirectoryExists(dir); + + final File file = new File(dir, getFileName(fileDescr)); + checkFileExists(file); + + long size = 0; + OutputStream os = null; + try { + os = FileUtils.openOutputStream(file); + size = IOUtils.copyLarge(inputStream, os); + os.flush(); + writeLog(file, false); + } catch (IOException e) { + IOUtils.closeQuietly(os); + FileUtils.deleteQuietly(file); + + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, file.getAbsolutePath(), e); + } finally { + IOUtils.closeQuietly(os); + } + + // Copy file to secondary storages asynchronously + + final SecurityContext securityContext = AppContext.getSecurityContext(); + for (int i = 1; i < roots.length; i++) { + if (!roots[i].exists()) { + log.error("Error saving {} into {} : directory doesn't exist", fileDescr, roots[i]); + continue; + } + + File copyDir = getStorageDir(roots[i], fileDescr); + final File fileCopy = new File(copyDir, getFileName(fileDescr)); + + writeExecutor.submit(new Runnable() { + @Override + public void run() { + try { + AppContext.setSecurityContext(securityContext); + FileUtils.copyFile(file, fileCopy, true); + writeLog(fileCopy, false); + } catch (Exception e) { + log.error("Error saving {} into {} : {}", fileDescr, fileCopy.getAbsolutePath(), e.getMessage()); + } finally { + AppContext.setSecurityContext(null); + } + } + }); + } + + return size; + } + + protected void checkFileExists(File file) throws FileStorageException { + if (file.exists() && isImmutableFileStorage) + throw new FileStorageException(FileStorageException.Type.FILE_ALREADY_EXISTS, file.getAbsolutePath()); + } + + protected void checkDirectoryExists(File dir) throws FileStorageException { + if (!dir.exists()) + throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, dir.getAbsolutePath()); + } + + protected void checkPrimaryStorageAccessible(File[] roots, FileDescriptor fileDescr) throws FileStorageException { + if (!roots[0].exists()) { + log.error("Inaccessible primary storage at {}", roots[0]); + throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString()); + } + } + + protected void checkStorageDefined(File[] roots, FileDescriptor fileDescr) throws FileStorageException { + if (roots.length == 0) { + log.error("No storage directories defined"); + throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString()); + } + } + + @Override + public void saveFile(final FileDescriptor fileDescr, final byte[] data) throws FileStorageException { + checkNotNullArgument(data, "File content is null"); + saveStream(fileDescr, new ByteArrayInputStream(data)); + } + + protected synchronized void writeLog(File file, boolean remove) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + StringBuilder sb = new StringBuilder(); + sb.append(df.format(timeSource.currentTimestamp())).append(" "); + sb.append("[").append(userSessionSource.getUserSession().getUser()).append("] "); + sb.append(remove ? "REMOVE" : "CREATE").append(" "); + sb.append("\"").append(file.getAbsolutePath()).append("\"\n"); + + File rootDir; + try { + rootDir = file.getParentFile().getParentFile().getParentFile().getParentFile(); + } catch (NullPointerException e) { + log.error("Unable to write log: invalid file storage structure", e); + return; + } + File logFile = new File(rootDir, "storage.log"); + try { + try (FileOutputStream fos = new FileOutputStream(logFile, true)) { + IOUtils.write(sb.toString(), fos, StandardCharsets.UTF_8.name()); + } + } catch (IOException e) { + log.error("Unable to write log", e); + } + } + + @Override + public void removeFile(FileDescriptor fileDescr) throws FileStorageException { + checkFileDescriptor(fileDescr); + + File[] roots = getStorageRoots(); + if (roots.length == 0) { + log.error("No storage directories defined"); + return; + } + + for (File root : roots) { + File dir = getStorageDir(root, fileDescr); + File file = new File(dir, getFileName(fileDescr)); + if (file.exists()) { + if (!file.delete()) { + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, "Unable to delete file " + file.getAbsolutePath()); + } else { + writeLog(file, true); + } + } + } + } + + protected void checkFileDescriptor(FileDescriptor fd) { + if (fd == null || fd.getCreateDate() == null) { + throw new IllegalArgumentException("A FileDescriptor instance with populated 'createDate' attribute must be provided"); + } + } + + @Override + public InputStream openStream(FileDescriptor fileDescr) throws FileStorageException { + checkFileDescriptor(fileDescr); + + File[] roots = getStorageRoots(); + if (roots.length == 0) { + log.error("No storage directories available"); + throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString()); + } + + InputStream inputStream = null; + for (File root : roots) { + File dir = getStorageDir(root, fileDescr); + + File file = new File(dir, getFileName(fileDescr)); + if (!file.exists()) { + log.error("File " + file + " not found"); + continue; + } + + try { + inputStream = FileUtils.openInputStream(file); + break; + } catch (IOException e) { + log.error("Error opening input stream for " + file, e); + } + } + if (inputStream != null) + return inputStream; + else + throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString()); + } + + @Override + public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { + InputStream inputStream = openStream(fileDescr); + try { + return IOUtils.toByteArray(inputStream); + } catch (IOException e) { + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e); + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + @Override + public boolean fileExists(FileDescriptor fileDescr) { + checkFileDescriptor(fileDescr); + + File[] roots = getStorageRoots(); + for (File root : roots) { + File dir = getStorageDir(root, fileDescr); + File file = new File(dir, getFileName(fileDescr)); + if (file.exists()) { + return true; + } + } + return false; + } + + /** + * INTERNAL. Don't use in application code. + */ + public File getStorageDir(File rootDir, FileDescriptor fileDescriptor) { + checkNotNullArgument(rootDir); + checkNotNullArgument(fileDescriptor); + + Calendar cal = Calendar.getInstance(); + cal.setTime(fileDescriptor.getCreateDate()); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH) + 1; + int day = cal.get(Calendar.DAY_OF_MONTH); + + return new File(rootDir, year + "/" + + StringUtils.leftPad(String.valueOf(month), 2, '0') + "/" + + StringUtils.leftPad(String.valueOf(day), 2, '0')); + } + + public static String getFileName(FileDescriptor fileDescriptor) { + return fileDescriptor.getId().toString() + "." + fileDescriptor.getExtension(); + } + + @PreDestroy + protected void stopWriteExecutor() { + writeExecutor.shutdown(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorage.java b/modules/core/src/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorage.java index 80aafc6643..7c7683861c 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorage.java +++ b/modules/core/src/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorage.java @@ -1,268 +1,268 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.filestorage.amazon; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.app.FileStorageAPI; -import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerBase; -import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerForAuthorizationHeader; -import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerForChunkedUpload; -import com.haulmont.cuba.core.app.filestorage.amazon.util.HttpUtils; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; - -import javax.inject.Inject; -import java.io.ByteArrayInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -public class AmazonS3FileStorage implements FileStorageAPI { - - @Inject - protected AmazonS3Config amazonS3Config; - - @Override - public long saveStream(FileDescriptor fileDescr, InputStream inputStream) throws FileStorageException { - Preconditions.checkNotNullArgument(fileDescr.getSize()); - - int chunkSize = amazonS3Config.getChunkSize(); - long fileSize = fileDescr.getSize(); - URL amazonUrl = getAmazonUrl(fileDescr); - // set the markers indicating we're going to send the upload as a series - // of chunks: - // -- 'x-amz-content-sha256' is the fixed marker indicating chunked - // upload - // -- 'content-length' becomes the total size in bytes of the upload - // (including chunk headers), - // -- 'x-amz-decoded-content-length' is used to transmit the actual - // length of the data payload, less chunk headers - Map headers = new HashMap<>(); - headers.put("x-amz-storage-class", "REDUCED_REDUNDANCY"); - headers.put("x-amz-content-sha256", AWS4SignerForChunkedUpload.STREAMING_BODY_SHA256); - headers.put("content-encoding", "aws-chunked"); - headers.put("x-amz-decoded-content-length", "" + fileSize); - - AWS4SignerForChunkedUpload signer = new AWS4SignerForChunkedUpload( - amazonUrl, "PUT", "s3", amazonS3Config.getRegionName()); - - // how big is the overall request stream going to be once we add the signature - // 'headers' to each chunk? - long totalLength = AWS4SignerForChunkedUpload.calculateChunkedContentLength( - fileSize, chunkSize); - headers.put("content-length", "" + totalLength); - - String authorization = signer.computeSignature(headers, - null, // no query parameters - AWS4SignerForChunkedUpload.STREAMING_BODY_SHA256, - amazonS3Config.getAccessKey(), - amazonS3Config.getSecretAccessKey()); - - // place the computed signature into a formatted 'Authorization' header - // and call S3 - headers.put("Authorization", authorization); - - // start consuming the data payload in blocks which we subsequently chunk; this prefixes - // the data with a 'chunk header' containing signature data from the prior chunk (or header - // signing, if the first chunk) plus length and other data. Each completed chunk is - // written to the request stream and to complete the upload, we send a final chunk with - // a zero-length data payload. - - try { - // first set up the connection - HttpURLConnection connection = HttpUtils.createHttpConnection(amazonUrl, "PUT", headers); - - // get the request stream and start writing the user data as chunks, as outlined - // above; - int bytesRead; - byte[] buffer = new byte[chunkSize]; - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - //guarantees that it will read as many bytes as possible, this may not always be the case for - //subclasses of InputStream - while ((bytesRead = IOUtils.read(inputStream, buffer, 0, chunkSize)) > 0) { - // process into a chunk - byte[] chunk = signer.constructSignedChunk(bytesRead, buffer); - - // send the chunk - outputStream.write(chunk); - outputStream.flush(); - } - - // last step is to send a signed zero-length chunk to complete the upload - byte[] finalChunk = signer.constructSignedChunk(0, buffer); - outputStream.write(finalChunk); - outputStream.flush(); - outputStream.close(); - - // make the call to Amazon S3 - HttpUtils.HttpResponse httpResponse = HttpUtils.executeHttpRequest(connection); - if (!httpResponse.isStatusOk()) { - String message = String.format("Could not save file %s. %s", - getFileName(fileDescr), getInputStreamContent(httpResponse)); - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); - } - } catch (IOException e) { - throw new RuntimeException("Error when sending chunked upload request", e); - } - - return fileDescr.getSize(); - } - - @Override - public void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException { - checkNotNullArgument(data, "File content is null"); - saveStream(fileDescr, new ByteArrayInputStream(data)); - } - - @Override - public void removeFile(FileDescriptor fileDescr) throws FileStorageException { - URL amazonUrl = getAmazonUrl(fileDescr); - - // for a simple DELETE, we have no body so supply the precomputed 'empty' hash - Map headers = new HashMap<>(); - headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); - - String authorization = createAuthorizationHeader(amazonUrl, "DELETE", headers); - - headers.put("Authorization", authorization); - HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "DELETE", headers, null); - if (!httpResponse.isStatusOk()) { - String message = String.format("Could not remove file %s. %s", - getFileName(fileDescr), getInputStreamContent(httpResponse)); - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); - } - } - - @Override - public InputStream openStream(FileDescriptor fileDescr) throws FileStorageException { - URL amazonUrl = getAmazonUrl(fileDescr); - - // for a simple GET, we have no body so supply the precomputed 'empty' hash - Map headers = new HashMap<>(); - headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); - - String authorization = createAuthorizationHeader(amazonUrl, "GET", headers); - - headers.put("Authorization", authorization); - HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "GET", headers, null); - - if (httpResponse.isStatusOk()) { - return httpResponse.getInputStream(); - } else if (httpResponse.isStatusNotFound()) { - throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, - "File not found" + getFileName(fileDescr)); - } else { - String message = String.format("Could not get file %s. %s", - getFileName(fileDescr), getInputStreamContent(httpResponse)); - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); - } - } - - @Override - public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { - InputStream inputStream = openStream(fileDescr); - try { - return IOUtils.toByteArray(inputStream); - } catch (IOException e) { - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e); - } finally { - IOUtils.closeQuietly(inputStream); - } - } - - @Override - public boolean fileExists(FileDescriptor fileDescr) { - URL amazonUrl = getAmazonUrl(fileDescr); - - // for a simple HEAD, we have no body so supply the precomputed 'empty' hash - Map headers = new HashMap<>(); - headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); - - String authorization = createAuthorizationHeader(amazonUrl, "HEAD", headers); - - headers.put("Authorization", authorization); - HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "HEAD", headers, null); - return httpResponse.isStatusOk(); - } - - protected String resolveFileName(FileDescriptor fileDescr) { - return getStorageDir(fileDescr.getCreateDate()) + "/" + getFileName(fileDescr); - } - - /** - * INTERNAL. Don't use in application code. - */ - protected String getStorageDir(Date createDate) { - Calendar cal = Calendar.getInstance(); - cal.setTime(createDate); - int year = cal.get(Calendar.YEAR); - int month = cal.get(Calendar.MONTH) + 1; - int day = cal.get(Calendar.DAY_OF_MONTH); - - return String.format("%d/%s/%s", - year, StringUtils.leftPad(String.valueOf(month), 2, '0'), StringUtils.leftPad(String.valueOf(day), 2, '0')); - } - - protected URL getAmazonUrl(FileDescriptor fileDescr) { - // the region-specific endpoint to the target object expressed in path style - try { - return new URL(String.format("https://%s.s3.amazonaws.com/%s", - amazonS3Config.getBucket(), resolveFileName(fileDescr))); - } catch (MalformedURLException e) { - throw new RuntimeException("Unable to parse service endpoint: " + e.getMessage()); - } - } - - protected String getFileName(FileDescriptor fileDescriptor) { - if (StringUtils.isNotBlank(fileDescriptor.getExtension())) { - return fileDescriptor.getId().toString() + "." + fileDescriptor.getExtension(); - } else { - return fileDescriptor.getId().toString(); - } - } - - protected String createAuthorizationHeader(URL endpointUrl, String method, Map headers) { - AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader( - endpointUrl, method, "s3", amazonS3Config.getRegionName()); - return signer.computeSignature(headers, - null, // no query parameters - AWS4SignerBase.EMPTY_BODY_SHA256, - amazonS3Config.getAccessKey(), - amazonS3Config.getSecretAccessKey()); - } - - protected String getInputStreamContent(HttpUtils.HttpResponse httpResponse) { - try { - return IOUtils.toString(httpResponse.getInputStream(), StandardCharsets.UTF_8); - } catch (IOException e) { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.filestorage.amazon; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.app.FileStorageAPI; +import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerBase; +import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerForAuthorizationHeader; +import com.haulmont.cuba.core.app.filestorage.amazon.auth.AWS4SignerForChunkedUpload; +import com.haulmont.cuba.core.app.filestorage.amazon.util.HttpUtils; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; + +import javax.inject.Inject; +import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +public class AmazonS3FileStorage implements FileStorageAPI { + + @Inject + protected AmazonS3Config amazonS3Config; + + @Override + public long saveStream(FileDescriptor fileDescr, InputStream inputStream) throws FileStorageException { + Preconditions.checkNotNullArgument(fileDescr.getSize()); + + int chunkSize = amazonS3Config.getChunkSize(); + long fileSize = fileDescr.getSize(); + URL amazonUrl = getAmazonUrl(fileDescr); + // set the markers indicating we're going to send the upload as a series + // of chunks: + // -- 'x-amz-content-sha256' is the fixed marker indicating chunked + // upload + // -- 'content-length' becomes the total size in bytes of the upload + // (including chunk headers), + // -- 'x-amz-decoded-content-length' is used to transmit the actual + // length of the data payload, less chunk headers + Map headers = new HashMap<>(); + headers.put("x-amz-storage-class", "REDUCED_REDUNDANCY"); + headers.put("x-amz-content-sha256", AWS4SignerForChunkedUpload.STREAMING_BODY_SHA256); + headers.put("content-encoding", "aws-chunked"); + headers.put("x-amz-decoded-content-length", "" + fileSize); + + AWS4SignerForChunkedUpload signer = new AWS4SignerForChunkedUpload( + amazonUrl, "PUT", "s3", amazonS3Config.getRegionName()); + + // how big is the overall request stream going to be once we add the signature + // 'headers' to each chunk? + long totalLength = AWS4SignerForChunkedUpload.calculateChunkedContentLength( + fileSize, chunkSize); + headers.put("content-length", "" + totalLength); + + String authorization = signer.computeSignature(headers, + null, // no query parameters + AWS4SignerForChunkedUpload.STREAMING_BODY_SHA256, + amazonS3Config.getAccessKey(), + amazonS3Config.getSecretAccessKey()); + + // place the computed signature into a formatted 'Authorization' header + // and call S3 + headers.put("Authorization", authorization); + + // start consuming the data payload in blocks which we subsequently chunk; this prefixes + // the data with a 'chunk header' containing signature data from the prior chunk (or header + // signing, if the first chunk) plus length and other data. Each completed chunk is + // written to the request stream and to complete the upload, we send a final chunk with + // a zero-length data payload. + + try { + // first set up the connection + HttpURLConnection connection = HttpUtils.createHttpConnection(amazonUrl, "PUT", headers); + + // get the request stream and start writing the user data as chunks, as outlined + // above; + int bytesRead; + byte[] buffer = new byte[chunkSize]; + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + //guarantees that it will read as many bytes as possible, this may not always be the case for + //subclasses of InputStream + while ((bytesRead = IOUtils.read(inputStream, buffer, 0, chunkSize)) > 0) { + // process into a chunk + byte[] chunk = signer.constructSignedChunk(bytesRead, buffer); + + // send the chunk + outputStream.write(chunk); + outputStream.flush(); + } + + // last step is to send a signed zero-length chunk to complete the upload + byte[] finalChunk = signer.constructSignedChunk(0, buffer); + outputStream.write(finalChunk); + outputStream.flush(); + outputStream.close(); + + // make the call to Amazon S3 + HttpUtils.HttpResponse httpResponse = HttpUtils.executeHttpRequest(connection); + if (!httpResponse.isStatusOk()) { + String message = String.format("Could not save file %s. %s", + getFileName(fileDescr), getInputStreamContent(httpResponse)); + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); + } + } catch (IOException e) { + throw new RuntimeException("Error when sending chunked upload request", e); + } + + return fileDescr.getSize(); + } + + @Override + public void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException { + checkNotNullArgument(data, "File content is null"); + saveStream(fileDescr, new ByteArrayInputStream(data)); + } + + @Override + public void removeFile(FileDescriptor fileDescr) throws FileStorageException { + URL amazonUrl = getAmazonUrl(fileDescr); + + // for a simple DELETE, we have no body so supply the precomputed 'empty' hash + Map headers = new HashMap<>(); + headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); + + String authorization = createAuthorizationHeader(amazonUrl, "DELETE", headers); + + headers.put("Authorization", authorization); + HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "DELETE", headers, null); + if (!httpResponse.isStatusOk()) { + String message = String.format("Could not remove file %s. %s", + getFileName(fileDescr), getInputStreamContent(httpResponse)); + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); + } + } + + @Override + public InputStream openStream(FileDescriptor fileDescr) throws FileStorageException { + URL amazonUrl = getAmazonUrl(fileDescr); + + // for a simple GET, we have no body so supply the precomputed 'empty' hash + Map headers = new HashMap<>(); + headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); + + String authorization = createAuthorizationHeader(amazonUrl, "GET", headers); + + headers.put("Authorization", authorization); + HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "GET", headers, null); + + if (httpResponse.isStatusOk()) { + return httpResponse.getInputStream(); + } else if (httpResponse.isStatusNotFound()) { + throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, + "File not found" + getFileName(fileDescr)); + } else { + String message = String.format("Could not get file %s. %s", + getFileName(fileDescr), getInputStreamContent(httpResponse)); + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, message); + } + } + + @Override + public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException { + InputStream inputStream = openStream(fileDescr); + try { + return IOUtils.toByteArray(inputStream); + } catch (IOException e) { + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e); + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + @Override + public boolean fileExists(FileDescriptor fileDescr) { + URL amazonUrl = getAmazonUrl(fileDescr); + + // for a simple HEAD, we have no body so supply the precomputed 'empty' hash + Map headers = new HashMap<>(); + headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256); + + String authorization = createAuthorizationHeader(amazonUrl, "HEAD", headers); + + headers.put("Authorization", authorization); + HttpUtils.HttpResponse httpResponse = HttpUtils.invokeHttpRequest(amazonUrl, "HEAD", headers, null); + return httpResponse.isStatusOk(); + } + + protected String resolveFileName(FileDescriptor fileDescr) { + return getStorageDir(fileDescr.getCreateDate()) + "/" + getFileName(fileDescr); + } + + /** + * INTERNAL. Don't use in application code. + */ + protected String getStorageDir(Date createDate) { + Calendar cal = Calendar.getInstance(); + cal.setTime(createDate); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH) + 1; + int day = cal.get(Calendar.DAY_OF_MONTH); + + return String.format("%d/%s/%s", + year, StringUtils.leftPad(String.valueOf(month), 2, '0'), StringUtils.leftPad(String.valueOf(day), 2, '0')); + } + + protected URL getAmazonUrl(FileDescriptor fileDescr) { + // the region-specific endpoint to the target object expressed in path style + try { + return new URL(String.format("https://%s.s3.amazonaws.com/%s", + amazonS3Config.getBucket(), resolveFileName(fileDescr))); + } catch (MalformedURLException e) { + throw new RuntimeException("Unable to parse service endpoint: " + e.getMessage()); + } + } + + protected String getFileName(FileDescriptor fileDescriptor) { + if (StringUtils.isNotBlank(fileDescriptor.getExtension())) { + return fileDescriptor.getId().toString() + "." + fileDescriptor.getExtension(); + } else { + return fileDescriptor.getId().toString(); + } + } + + protected String createAuthorizationHeader(URL endpointUrl, String method, Map headers) { + AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader( + endpointUrl, method, "s3", amazonS3Config.getRegionName()); + return signer.computeSignature(headers, + null, // no query parameters + AWS4SignerBase.EMPTY_BODY_SHA256, + amazonS3Config.getAccessKey(), + amazonS3Config.getSecretAccessKey()); + } + + protected String getInputStreamContent(HttpUtils.HttpResponse httpResponse) { + try { + return IOUtils.toString(httpResponse.getInputStream(), StandardCharsets.UTF_8); + } catch (IOException e) { + return null; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExport.java b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExport.java index b31c702486..d2cc9d7688 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExport.java +++ b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExport.java @@ -1,699 +1,699 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.Range; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.PersistenceSecurity; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.app.DataStore; -import com.haulmont.cuba.core.app.RdbmsStore; -import com.haulmont.cuba.core.app.StoreFactory; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManagerAPI; -import com.haulmont.cuba.core.app.serialization.EntitySerializationAPI; -import com.haulmont.cuba.core.app.serialization.EntitySerializationOption; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.global.validation.CustomValidationException; -import com.haulmont.cuba.core.global.validation.EntityValidationException; -import com.haulmont.cuba.core.global.validation.groups.RestApiChecks; -import org.apache.commons.compress.archivers.ArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; -import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; -import org.apache.commons.io.IOUtils; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.validation.ConstraintViolation; -import javax.validation.Validator; -import javax.validation.groups.Default; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.stream.Collectors; -import java.util.zip.CRC32; - -import static java.lang.String.format; - -@Component(EntityImportExportAPI.NAME) -public class EntityImportExport implements EntityImportExportAPI { - - @Inject - protected EntitySerializationAPI entitySerialization; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected DataManager dataManager; - - @Inject - protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; - - @Inject - protected PersistenceSecurity persistenceSecurity; - - @Inject - protected StoreFactory storeFactory; - - @Inject - protected ViewRepository viewRepository; - - @Inject - protected BeanValidation beanValidation; - - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - - @Override - public byte[] exportEntitiesToZIP(Collection entities, View view) { - return exportEntitiesToZIP(reloadEntities(entities, view)); - } - - @Override - public byte[] exportEntitiesToZIP(Collection entities) { - String json = entitySerialization.toJson(entities, null, EntitySerializationOption.COMPACT_REPEATED_ENTITIES); - byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8); - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(byteArrayOutputStream); - zipOutputStream.setMethod(ZipArchiveOutputStream.STORED); - zipOutputStream.setEncoding(StandardCharsets.UTF_8.name()); - ArchiveEntry singleDesignEntry = newStoredEntry("entities.json", jsonBytes); - try { - zipOutputStream.putArchiveEntry(singleDesignEntry); - zipOutputStream.write(jsonBytes); - zipOutputStream.closeArchiveEntry(); - } catch (Exception e) { - throw new RuntimeException("Error on creating zip archive during entities export", e); - } finally { - IOUtils.closeQuietly(zipOutputStream); - } - return byteArrayOutputStream.toByteArray(); - } - - @Override - public String exportEntitiesToJSON(Collection entities, View view) { - return exportEntitiesToJSON(reloadEntities(entities, view)); - } - - @Override - public String exportEntitiesToJSON(Collection entities) { - return entitySerialization.toJson(entities, null, - EntitySerializationOption.COMPACT_REPEATED_ENTITIES, EntitySerializationOption.PRETTY_PRINT); - } - - protected Collection reloadEntities(Collection entities, View view) { - List ids = entities.stream() - .map(Entity::getId) - .collect(Collectors.toList()); - - MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); - LoadContext.Query query = LoadContext.createQuery("select e from " + metaClass.getName() + " e where e.id in :ids") - .setParameter("ids", ids); - LoadContext ctx = LoadContext.create(view.getEntityClass()) - .setQuery(query) - .setView(view); - - return dataManager.loadList(ctx); - } - - protected ArchiveEntry newStoredEntry(String name, byte[] data) { - ZipArchiveEntry zipEntry = new ZipArchiveEntry(name); - zipEntry.setSize(data.length); - zipEntry.setCompressedSize(zipEntry.getSize()); - CRC32 crc32 = new CRC32(); - crc32.update(data); - zipEntry.setCrc(crc32.getValue()); - return zipEntry; - } - - @Override - public Collection importEntitiesFromJson(String json, EntityImportView view) { - Collection result = new ArrayList<>(); - Collection entities = entitySerialization.entitiesCollectionFromJson(json, - null, - EntitySerializationOption.COMPACT_REPEATED_ENTITIES); - result.addAll(importEntities(entities, view)); - return result; - } - - @Override - public Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView view) { - Collection result = new ArrayList<>(); - Collection entities; - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); - ZipArchiveInputStream archiveReader = new ZipArchiveInputStream(byteArrayInputStream); - try { - try { - while (archiveReader.getNextZipEntry() != null) { - String json = new String(readBytesFromEntry(archiveReader), StandardCharsets.UTF_8); - entities = entitySerialization.entitiesCollectionFromJson(json, - null, - EntitySerializationOption.COMPACT_REPEATED_ENTITIES); - result.addAll(importEntities(entities, view)); - } - } catch (IOException e) { - throw new RuntimeException("Exception occurred while importing report", e); - } - } finally { - IOUtils.closeQuietly(archiveReader); - } - return result; - } - - protected byte[] readBytesFromEntry(ZipArchiveInputStream archiveReader) throws IOException { - return IOUtils.toByteArray(archiveReader); - } - - @Override - public Collection importEntities(Collection entities, EntityImportView importView) { - return importEntities(entities, importView, false); - } - - @Override - public Collection importEntities(Collection entities, EntityImportView importView, boolean validate) { - List referenceInfoList = new ArrayList<>(); - CommitContext commitContext = new CommitContext(); - - //import is performed in two steps. We have to do so, because imported entity may have a reference to - //the reference that is imported in the same batch. - // - //1. entities that should be persisted are processed first, fields that should be references to existing entities - //are stored in the referenceInfoList variable - for (Entity srcEntity : entities) { - View regularView = buildViewFromImportView(importView); - //set softDeletion to false because we can import deleted entity, so we'll restore it and update - LoadContext ctx = LoadContext.create(srcEntity.getClass()) - .setSoftDeletion(false) - .setView(regularView) - .setId(srcEntity.getId()); - Entity dstEntity = dataManager.secure().load(ctx); - - importEntity(srcEntity, dstEntity, importView, regularView, commitContext, referenceInfoList); - } - - //2. references to existing entities are processed - - //store a list of loaded entities in the collection to prevent unnecessary database requests for searching the - //same instance - Set loadedEntities = new HashSet<>(); - for (ReferenceInfo referenceInfo : referenceInfoList) { - processReferenceInfo(referenceInfo, commitContext, loadedEntities); - } - - for (Entity commitInstance : commitContext.getCommitInstances()) { - if (!PersistenceHelper.isNew(commitInstance)) { - if (commitInstance instanceof SoftDelete && ((SoftDelete) commitInstance).isDeleted()) { - ((SoftDelete) commitInstance).setDeleteTs(null); - } - } - if (entityHasDynamicAttributes(commitInstance)) { - dynamicAttributesManagerAPI.storeDynamicAttributes((BaseGenericIdEntity) commitInstance); - } - } - - if (validate) { - Validator validator = beanValidation.getValidator(); - for (Entity entity : commitContext.getCommitInstances()) { - Set> violations = validator.validate(entity, Default.class, RestApiChecks.class); - if (!violations.isEmpty()) { - throw new EntityValidationException("Entity validation failed", violations); - } - } - } - - return dataManager.secure().commit(commitContext); - } - - /** - * Method imports the entity. - * - * @param srcEntity entity that came to the {@code EntityImportExport} bean - * @param dstEntity reloaded srcEntity or null if entity doesn't exist in the database - * @param importView importView used for importing the entity - * @param regularView view that was used for loading dstEntity - * @param commitContext entities that must be commited or deleted will be set to the commitContext - * @param referenceInfoList list of referenceInfos for further processing - * @return dstEntity that has fields values from the srcEntity - */ - protected Entity importEntity(Entity srcEntity, - @Nullable Entity dstEntity, - EntityImportView importView, - View regularView, - CommitContext commitContext, - Collection referenceInfoList) { - MetaClass metaClass = srcEntity.getMetaClass(); - boolean isNew = false; - if (dstEntity == null) { - dstEntity = metadata.create(metaClass); - dstEntity.setValue("id", srcEntity.getId()); - isNew = true; - } - - //we must specify a view here because otherwise we may get UnfetchedAttributeException during merge - commitContext.addInstanceToCommit(dstEntity, regularView); - - SecurityState securityState = null; - if (srcEntity instanceof BaseGenericIdEntity && !isNew) { - String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); - DataStore dataStore = storeFactory.get(storeName); - //row-level security works only for entities from RdbmsStore - if (dataStore instanceof RdbmsStore) { - persistenceSecurity.restoreSecurityState(srcEntity); - securityState = BaseEntityInternalAccess.getSecurityState(srcEntity); - } - } - - for (EntityImportViewProperty importViewProperty : importView.getProperties()) { - String propertyName = importViewProperty.getName(); - MetaProperty metaProperty = metaClass.getPropertyNN(propertyName); - if (BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, propertyName)) { - continue; - } - if (BaseEntityInternalAccess.isRequired(securityState, propertyName) && srcEntity.getValue(propertyName) == null) { - throw new CustomValidationException(format("Attribute [%s] is required for entity %s", propertyName, srcEntity)); - } - if ((metaProperty.getRange().isDatatype() && !"version".equals(metaProperty.getName())) || metaProperty.getRange().isEnum()) { - dstEntity.setValue(propertyName, srcEntity.getValue(propertyName)); - } else if (metaProperty.getRange().isClass()) { - View regularPropertyView = regularView.getProperty(propertyName) != null ? regularView.getProperty(propertyName).getView() : null; - if (metadata.getTools().isEmbedded(metaProperty)) { - if (importViewProperty.getView() != null) { - Entity embeddedEntity = importEmbeddedAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); - dstEntity.setValue(propertyName, embeddedEntity); - } - } else { - switch (metaProperty.getRange().getCardinality()) { - case MANY_TO_MANY: - importManyToManyCollectionAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); - break; - case ONE_TO_MANY: - importOneToManyCollectionAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); - break; - default: - importReference(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); - } - } - } - } - - if (entityHasDynamicAttributes(srcEntity)) { - ((BaseGenericIdEntity) dstEntity).setDynamicAttributes(((BaseGenericIdEntity) srcEntity).getDynamicAttributes()); - } - - return dstEntity; - } - - private boolean entityHasDynamicAttributes(Entity entity) { - return entity instanceof BaseGenericIdEntity && ((BaseGenericIdEntity) entity).getDynamicAttributes() != null; - } - - protected void importReference(Entity srcEntity, - Entity dstEntity, - EntityImportViewProperty importViewProperty, - View regularView, - CommitContext commitContext, - Collection referenceInfoList) { - Entity srcPropertyValue = srcEntity.getValue(importViewProperty.getName()); - Entity dstPropertyValue = dstEntity.getValue(importViewProperty.getName()); - if (importViewProperty.getView() == null) { - ReferenceInfo referenceInfo = new ReferenceInfo(dstEntity, importViewProperty, srcPropertyValue); - referenceInfoList.add(referenceInfo); - } else { - dstPropertyValue = importEntity(srcPropertyValue, dstPropertyValue, importViewProperty.getView(), regularView, commitContext, referenceInfoList); - dstEntity.setValue(importViewProperty.getName(), dstPropertyValue); - } - } - - protected void importOneToManyCollectionAttribute(Entity srcEntity, - Entity dstEntity, - EntityImportViewProperty importViewProperty, - View regularView, - CommitContext commitContext, - Collection referenceInfoList) { - String propertyName = importViewProperty.getName(); - MetaProperty metaProperty = srcEntity.getMetaClass().getPropertyNN(propertyName); - MetaProperty inverseMetaProperty = metaProperty.getInverse(); - - //filteredItems collection will contain entities filtered by the row-level security - Multimap filteredItems = ArrayListMultimap.create(); - if (srcEntity instanceof BaseGenericIdEntity) { - String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); - DataStore dataStore = storeFactory.get(storeName); - //row-level security works only for entities from RdbmsStore - if (dataStore instanceof RdbmsStore) { - filteredItems = BaseEntityInternalAccess.getFilteredData(srcEntity); - } - } - - Collection srcPropertyValue = srcEntity.getValue(propertyName); - Collection dstPropertyValue = dstEntity.getValue(propertyName); - if (dstPropertyValue == null) dstPropertyValue = new ArrayList<>(); - Collection collection; - try { - collection = srcPropertyValue.getClass().newInstance(); - } catch (Exception e) { - throw new RuntimeException("Error on import entities", e); - } - - if (srcPropertyValue != null) { - for (Entity srcChildEntity : srcPropertyValue) { - if (importViewProperty.getView() != null) { - //create new referenced entity - Entity dstChildEntity = null; - for (Entity _entity : dstPropertyValue) { - if (_entity.equals(srcChildEntity)) { - dstChildEntity = _entity; - break; - } - } - dstChildEntity = importEntity(srcChildEntity, dstChildEntity, importViewProperty.getView(), regularView, commitContext, referenceInfoList); - if (inverseMetaProperty != null) { - dstChildEntity.setValue(inverseMetaProperty.getName(), dstEntity); - } - collection.add(dstChildEntity); - } - } - } - - if (importViewProperty.getCollectionImportPolicy() == CollectionImportPolicy.REMOVE_ABSENT_ITEMS) { - Collection dstValue = dstEntity.getValue(propertyName); - if (dstValue != null) { - Multimap finalFilteredItems = filteredItems; - List collectionItemsToRemove = dstValue.stream() - .filter(entity -> !collection.contains(entity) && - (finalFilteredItems == null || !finalFilteredItems.containsValue(referenceToEntitySupport.getReferenceId(entity)))) - .collect(Collectors.toList()); - for (Entity _entity : collectionItemsToRemove) { - commitContext.addInstanceToRemove(_entity); - } - } - } - - dstEntity.setValue(propertyName, collection); - } - - protected void importManyToManyCollectionAttribute(Entity srcEntity, - Entity dstEntity, - EntityImportViewProperty importViewProperty, - View regularView, - CommitContext commitContext, - Collection referenceInfoList) { - Collection srcPropertyValue = srcEntity.getValue(importViewProperty.getName()); - Collection dstPropertyValue = dstEntity.getValue(importViewProperty.getName()); - if (dstPropertyValue == null) dstPropertyValue = new ArrayList<>(); - if (importViewProperty.getView() != null) { - //create/update passed entities - Collection collection; - try { - collection = srcPropertyValue.getClass().newInstance(); - } catch (Exception e) { - throw new RuntimeException("Error on import entities", e); - } - - for (Entity srcChildEntity : srcPropertyValue) { - //create new referenced entity - Entity dstChildEntity = null; - for (Entity _entity : dstPropertyValue) { - if (_entity.equals(srcChildEntity)) { - dstChildEntity = _entity; - break; - } - } - dstChildEntity = importEntity(srcChildEntity, dstChildEntity, importViewProperty.getView(), regularView, commitContext, referenceInfoList); - collection.add(dstChildEntity); - } - - if (importViewProperty.getCollectionImportPolicy() == CollectionImportPolicy.KEEP_ABSENT_ITEMS) { - Collection existingCollectionValue = dstEntity.getValue(importViewProperty.getName()); - if (existingCollectionValue != null) { - for (Entity existingCollectionItem : existingCollectionValue) { - if (!collection.contains(existingCollectionItem)) collection.add(existingCollectionItem); - } - } - } - - dstEntity.setValue(importViewProperty.getName(), collection); - } else { - //create ReferenceInfo objects - they will be parsed later - Collection existingCollectionValue = dstEntity.getValue(importViewProperty.getName()); - ReferenceInfo referenceInfo = new ReferenceInfo(dstEntity, importViewProperty, srcPropertyValue, existingCollectionValue); - referenceInfoList.add(referenceInfo); - } - } - - protected Entity importEmbeddedAttribute(Entity srcEntity, - Entity dstEntity, - EntityImportViewProperty importViewProperty, - View regularView, - CommitContext commitContext, - Collection referenceInfoList) { - String propertyName = importViewProperty.getName(); - MetaProperty metaProperty = srcEntity.getMetaClass().getPropertyNN(propertyName); - Entity srcEmbeddedEntity = srcEntity.getValue(propertyName); - if (srcEmbeddedEntity == null) { - return null; - } - Entity dstEmbeddedEntity = dstEntity.getValue(propertyName); - MetaClass embeddedAttrMetaClass = metaProperty.getRange().asClass(); - if (dstEmbeddedEntity == null) { - dstEmbeddedEntity = metadata.create(embeddedAttrMetaClass); - } - - SecurityState securityState = null; - if (srcEntity instanceof BaseGenericIdEntity) { - String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); - DataStore dataStore = storeFactory.get(storeName); - //row-level security works only for entities from RdbmsStore - if (dataStore instanceof RdbmsStore) { - persistenceSecurity.restoreSecurityState(srcEmbeddedEntity); - securityState = BaseEntityInternalAccess.getSecurityState(srcEmbeddedEntity); - } - } - - for (EntityImportViewProperty vp : importViewProperty.getView().getProperties()) { - MetaProperty mp = embeddedAttrMetaClass.getPropertyNN(vp.getName()); - if (BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, mp.getName())) { - continue; - } - if (BaseEntityInternalAccess.isRequired(securityState, mp.getName()) && srcEmbeddedEntity.getValue(mp.getName()) == null) { - throw new CustomValidationException(format("Attribute [%s] is required for entity %s", mp.getName(), srcEmbeddedEntity)); - } - if ((mp.getRange().isDatatype() && !"version".equals(mp.getName())) || mp.getRange().isEnum()) { - dstEmbeddedEntity.setValue(vp.getName(), srcEmbeddedEntity.getValue(vp.getName())); - } else if (mp.getRange().isClass()) { - View propertyRegularView = regularView.getProperty(propertyName) != null ? regularView.getProperty(propertyName).getView() : null; - if (metaProperty.getRange().getCardinality() == Range.Cardinality.ONE_TO_MANY) { - importOneToManyCollectionAttribute(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); - } else if (metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) { - importManyToManyCollectionAttribute(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); - } else { - importReference(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); - } - } - } - - return dstEmbeddedEntity; - } - - /** - * Method finds and set a reference value to the entity or throws EntityImportException if ERROR_ON_MISSING policy - * is violated - */ - protected void processReferenceInfo(ReferenceInfo referenceInfo, CommitContext commitContext, Set loadedEntities) { - Entity entity = referenceInfo.getEntity(); - String propertyName = referenceInfo.getViewProperty().getName(); - MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(propertyName); - if (metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) { - Collection propertyValue = (Collection) referenceInfo.getPropertyValue(); - if (propertyValue == null) { - entity.setValue(propertyName, null); - return; - } - - Collection collection; - try { - collection = propertyValue.getClass().newInstance(); - } catch (Exception e) { - throw new RuntimeException("Error on import entities", e); - } - - for (Entity childEntity : propertyValue) { - Entity entityFromLoadedEntities = findEntityInCollection(loadedEntities, childEntity); - if (entityFromLoadedEntities != null) { - collection.add(entityFromLoadedEntities); - } else { - Entity entityFromCommitContext = findEntityInCollection(commitContext.getCommitInstances(), childEntity); - if (entityFromCommitContext != null) { - collection.add(entityFromCommitContext); - } else { - LoadContext ctx = LoadContext.create(childEntity.getClass()) - .setSoftDeletion(false) - .setView(View.MINIMAL) - .setId(childEntity.getId()); - Entity loadedReference = dataManager.load(ctx); - if (loadedReference == null) { - if (referenceInfo.getViewProperty().getReferenceImportBehaviour() == ReferenceImportBehaviour.ERROR_ON_MISSING) { - throw new EntityImportException("Referenced entity for property '" + propertyName + "' with id = " + entity.getId() + " is missing"); - } - } else { - collection.add(loadedReference); - loadedEntities.add(loadedReference); - } - } - } - } - - //keep absent collection members if we need it - if (referenceInfo.getViewProperty().getCollectionImportPolicy() == CollectionImportPolicy.KEEP_ABSENT_ITEMS) { - Collection prevCollectionValue = (Collection) referenceInfo.getPrevPropertyValue(); - if (prevCollectionValue != null) { - for (Entity prevCollectionItem : prevCollectionValue) { - if (!collection.contains(prevCollectionItem)) { - collection.add(prevCollectionItem); - } - } - } - } - - entity.setValue(propertyName, collection); - - //row-level security works only for entities from RdbmsStore - String storeName = metadata.getTools().getStoreName(entity.getMetaClass()); - DataStore dataStore = storeFactory.get(storeName); - if (dataStore instanceof RdbmsStore) { - //restore filtered data, otherwise they will be lost - try (Transaction tx = persistence.getTransaction()) { - persistenceSecurity.restoreSecurityStateAndFilteredData((BaseGenericIdEntity) entity); - tx.commit(); - } - } - //end of many-to-many processing block - } else { - //all other reference types (except many-to-many) - Entity propertyValue = (Entity) referenceInfo.getPropertyValue(); - if (propertyValue == null) { - entity.setValue(propertyName, null); - } else { - Entity entityFromLoadedEntities = findEntityInCollection(loadedEntities, propertyValue); - if (entityFromLoadedEntities != null) { - entity.setValue(propertyName, entityFromLoadedEntities); - } else { - Entity entityFromCommitContext = findEntityInCollection(commitContext.getCommitInstances(), propertyValue); - - if (entityFromCommitContext != null) { - entity.setValue(propertyName, entityFromCommitContext); - } else { - LoadContext ctx = LoadContext.create(propertyValue.getClass()) - .setId(propertyValue.getId()); - dataManager.load(ctx); - Entity loadedReference = dataManager.load(ctx); - if (loadedReference == null) { - if (referenceInfo.getViewProperty().getReferenceImportBehaviour() == ReferenceImportBehaviour.ERROR_ON_MISSING) { - throw new EntityImportException("Referenced entity for property '" + propertyName + "' with id = " + propertyValue.getId() + " is missing"); - } - } else { - entity.setValue(propertyName, loadedReference); - loadedEntities.add(loadedReference); - } - } - } - } - } - } - - /** - * Method builds a regular {@link View} from the {@link EntityImportView}. The regular view will include all - * properties defined in the import view. - */ - protected View buildViewFromImportView(EntityImportView importView) { - View regularView = new View(importView.getEntityClass()); - MetaClass metaClass = metadata.getClassNN(importView.getEntityClass()); - for (EntityImportViewProperty importViewProperty : importView.getProperties()) { - EntityImportView importViewPropertyView = importViewProperty.getView(); - if (importViewPropertyView == null) { - MetaProperty metaProperty = metaClass.getPropertyNN(importViewProperty.getName()); - if (metaProperty.getRange().isClass()) { - MetaClass propertyMetaClass = metaProperty.getRange().asClass(); - regularView.addProperty(importViewProperty.getName(), viewRepository.getView(propertyMetaClass, View.MINIMAL)); - } else { - regularView.addProperty(importViewProperty.getName()); - } - } else { - regularView.addProperty(importViewProperty.getName(), buildViewFromImportView(importViewPropertyView)); - } - } - return regularView; - } - - @Nullable - protected Entity findEntityInCollection(Collection collection, Entity entity) { - for (Entity entityFromCollection : collection) { - if (entityFromCollection.equals(entity)) return entityFromCollection; - } - return null; - } - - protected class ReferenceInfo { - protected Entity entity; - protected EntityImportViewProperty viewProperty; - protected Object propertyValue; - protected Object prevPropertyValue; - - public ReferenceInfo(Entity entity, EntityImportViewProperty viewProperty, Object propertyValue) { - this.entity = entity; - this.viewProperty = viewProperty; - this.propertyValue = propertyValue; - } - - public ReferenceInfo(Entity entity, EntityImportViewProperty viewProperty, Object propertyValue, Object prevPropertyValue) { - this.entity = entity; - this.viewProperty = viewProperty; - this.propertyValue = propertyValue; - this.prevPropertyValue = prevPropertyValue; - } - - public EntityImportViewProperty getViewProperty() { - return viewProperty; - } - - public Object getPrevPropertyValue() { - return prevPropertyValue; - } - - public Entity getEntity() { - return entity; - } - - public Object getPropertyValue() { - return propertyValue; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.Range; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.PersistenceSecurity; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.app.DataStore; +import com.haulmont.cuba.core.app.RdbmsStore; +import com.haulmont.cuba.core.app.StoreFactory; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManagerAPI; +import com.haulmont.cuba.core.app.serialization.EntitySerializationAPI; +import com.haulmont.cuba.core.app.serialization.EntitySerializationOption; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.global.validation.CustomValidationException; +import com.haulmont.cuba.core.global.validation.EntityValidationException; +import com.haulmont.cuba.core.global.validation.groups.RestApiChecks; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.io.IOUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import javax.validation.groups.Default; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; +import java.util.zip.CRC32; + +import static java.lang.String.format; + +@Component(EntityImportExportAPI.NAME) +public class EntityImportExport implements EntityImportExportAPI { + + @Inject + protected EntitySerializationAPI entitySerialization; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected DataManager dataManager; + + @Inject + protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; + + @Inject + protected PersistenceSecurity persistenceSecurity; + + @Inject + protected StoreFactory storeFactory; + + @Inject + protected ViewRepository viewRepository; + + @Inject + protected BeanValidation beanValidation; + + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + + @Override + public byte[] exportEntitiesToZIP(Collection entities, View view) { + return exportEntitiesToZIP(reloadEntities(entities, view)); + } + + @Override + public byte[] exportEntitiesToZIP(Collection entities) { + String json = entitySerialization.toJson(entities, null, EntitySerializationOption.COMPACT_REPEATED_ENTITIES); + byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ZipArchiveOutputStream zipOutputStream = new ZipArchiveOutputStream(byteArrayOutputStream); + zipOutputStream.setMethod(ZipArchiveOutputStream.STORED); + zipOutputStream.setEncoding(StandardCharsets.UTF_8.name()); + ArchiveEntry singleDesignEntry = newStoredEntry("entities.json", jsonBytes); + try { + zipOutputStream.putArchiveEntry(singleDesignEntry); + zipOutputStream.write(jsonBytes); + zipOutputStream.closeArchiveEntry(); + } catch (Exception e) { + throw new RuntimeException("Error on creating zip archive during entities export", e); + } finally { + IOUtils.closeQuietly(zipOutputStream); + } + return byteArrayOutputStream.toByteArray(); + } + + @Override + public String exportEntitiesToJSON(Collection entities, View view) { + return exportEntitiesToJSON(reloadEntities(entities, view)); + } + + @Override + public String exportEntitiesToJSON(Collection entities) { + return entitySerialization.toJson(entities, null, + EntitySerializationOption.COMPACT_REPEATED_ENTITIES, EntitySerializationOption.PRETTY_PRINT); + } + + protected Collection reloadEntities(Collection entities, View view) { + List ids = entities.stream() + .map(Entity::getId) + .collect(Collectors.toList()); + + MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); + LoadContext.Query query = LoadContext.createQuery("select e from " + metaClass.getName() + " e where e.id in :ids") + .setParameter("ids", ids); + LoadContext ctx = LoadContext.create(view.getEntityClass()) + .setQuery(query) + .setView(view); + + return dataManager.loadList(ctx); + } + + protected ArchiveEntry newStoredEntry(String name, byte[] data) { + ZipArchiveEntry zipEntry = new ZipArchiveEntry(name); + zipEntry.setSize(data.length); + zipEntry.setCompressedSize(zipEntry.getSize()); + CRC32 crc32 = new CRC32(); + crc32.update(data); + zipEntry.setCrc(crc32.getValue()); + return zipEntry; + } + + @Override + public Collection importEntitiesFromJson(String json, EntityImportView view) { + Collection result = new ArrayList<>(); + Collection entities = entitySerialization.entitiesCollectionFromJson(json, + null, + EntitySerializationOption.COMPACT_REPEATED_ENTITIES); + result.addAll(importEntities(entities, view)); + return result; + } + + @Override + public Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView view) { + Collection result = new ArrayList<>(); + Collection entities; + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipBytes); + ZipArchiveInputStream archiveReader = new ZipArchiveInputStream(byteArrayInputStream); + try { + try { + while (archiveReader.getNextZipEntry() != null) { + String json = new String(readBytesFromEntry(archiveReader), StandardCharsets.UTF_8); + entities = entitySerialization.entitiesCollectionFromJson(json, + null, + EntitySerializationOption.COMPACT_REPEATED_ENTITIES); + result.addAll(importEntities(entities, view)); + } + } catch (IOException e) { + throw new RuntimeException("Exception occurred while importing report", e); + } + } finally { + IOUtils.closeQuietly(archiveReader); + } + return result; + } + + protected byte[] readBytesFromEntry(ZipArchiveInputStream archiveReader) throws IOException { + return IOUtils.toByteArray(archiveReader); + } + + @Override + public Collection importEntities(Collection entities, EntityImportView importView) { + return importEntities(entities, importView, false); + } + + @Override + public Collection importEntities(Collection entities, EntityImportView importView, boolean validate) { + List referenceInfoList = new ArrayList<>(); + CommitContext commitContext = new CommitContext(); + + //import is performed in two steps. We have to do so, because imported entity may have a reference to + //the reference that is imported in the same batch. + // + //1. entities that should be persisted are processed first, fields that should be references to existing entities + //are stored in the referenceInfoList variable + for (Entity srcEntity : entities) { + View regularView = buildViewFromImportView(importView); + //set softDeletion to false because we can import deleted entity, so we'll restore it and update + LoadContext ctx = LoadContext.create(srcEntity.getClass()) + .setSoftDeletion(false) + .setView(regularView) + .setId(srcEntity.getId()); + Entity dstEntity = dataManager.secure().load(ctx); + + importEntity(srcEntity, dstEntity, importView, regularView, commitContext, referenceInfoList); + } + + //2. references to existing entities are processed + + //store a list of loaded entities in the collection to prevent unnecessary database requests for searching the + //same instance + Set loadedEntities = new HashSet<>(); + for (ReferenceInfo referenceInfo : referenceInfoList) { + processReferenceInfo(referenceInfo, commitContext, loadedEntities); + } + + for (Entity commitInstance : commitContext.getCommitInstances()) { + if (!PersistenceHelper.isNew(commitInstance)) { + if (commitInstance instanceof SoftDelete && ((SoftDelete) commitInstance).isDeleted()) { + ((SoftDelete) commitInstance).setDeleteTs(null); + } + } + if (entityHasDynamicAttributes(commitInstance)) { + dynamicAttributesManagerAPI.storeDynamicAttributes((BaseGenericIdEntity) commitInstance); + } + } + + if (validate) { + Validator validator = beanValidation.getValidator(); + for (Entity entity : commitContext.getCommitInstances()) { + Set> violations = validator.validate(entity, Default.class, RestApiChecks.class); + if (!violations.isEmpty()) { + throw new EntityValidationException("Entity validation failed", violations); + } + } + } + + return dataManager.secure().commit(commitContext); + } + + /** + * Method imports the entity. + * + * @param srcEntity entity that came to the {@code EntityImportExport} bean + * @param dstEntity reloaded srcEntity or null if entity doesn't exist in the database + * @param importView importView used for importing the entity + * @param regularView view that was used for loading dstEntity + * @param commitContext entities that must be commited or deleted will be set to the commitContext + * @param referenceInfoList list of referenceInfos for further processing + * @return dstEntity that has fields values from the srcEntity + */ + protected Entity importEntity(Entity srcEntity, + @Nullable Entity dstEntity, + EntityImportView importView, + View regularView, + CommitContext commitContext, + Collection referenceInfoList) { + MetaClass metaClass = srcEntity.getMetaClass(); + boolean isNew = false; + if (dstEntity == null) { + dstEntity = metadata.create(metaClass); + dstEntity.setValue("id", srcEntity.getId()); + isNew = true; + } + + //we must specify a view here because otherwise we may get UnfetchedAttributeException during merge + commitContext.addInstanceToCommit(dstEntity, regularView); + + SecurityState securityState = null; + if (srcEntity instanceof BaseGenericIdEntity && !isNew) { + String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); + DataStore dataStore = storeFactory.get(storeName); + //row-level security works only for entities from RdbmsStore + if (dataStore instanceof RdbmsStore) { + persistenceSecurity.restoreSecurityState(srcEntity); + securityState = BaseEntityInternalAccess.getSecurityState(srcEntity); + } + } + + for (EntityImportViewProperty importViewProperty : importView.getProperties()) { + String propertyName = importViewProperty.getName(); + MetaProperty metaProperty = metaClass.getPropertyNN(propertyName); + if (BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, propertyName)) { + continue; + } + if (BaseEntityInternalAccess.isRequired(securityState, propertyName) && srcEntity.getValue(propertyName) == null) { + throw new CustomValidationException(format("Attribute [%s] is required for entity %s", propertyName, srcEntity)); + } + if ((metaProperty.getRange().isDatatype() && !"version".equals(metaProperty.getName())) || metaProperty.getRange().isEnum()) { + dstEntity.setValue(propertyName, srcEntity.getValue(propertyName)); + } else if (metaProperty.getRange().isClass()) { + View regularPropertyView = regularView.getProperty(propertyName) != null ? regularView.getProperty(propertyName).getView() : null; + if (metadata.getTools().isEmbedded(metaProperty)) { + if (importViewProperty.getView() != null) { + Entity embeddedEntity = importEmbeddedAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); + dstEntity.setValue(propertyName, embeddedEntity); + } + } else { + switch (metaProperty.getRange().getCardinality()) { + case MANY_TO_MANY: + importManyToManyCollectionAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); + break; + case ONE_TO_MANY: + importOneToManyCollectionAttribute(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); + break; + default: + importReference(srcEntity, dstEntity, importViewProperty, regularPropertyView, commitContext, referenceInfoList); + } + } + } + } + + if (entityHasDynamicAttributes(srcEntity)) { + ((BaseGenericIdEntity) dstEntity).setDynamicAttributes(((BaseGenericIdEntity) srcEntity).getDynamicAttributes()); + } + + return dstEntity; + } + + private boolean entityHasDynamicAttributes(Entity entity) { + return entity instanceof BaseGenericIdEntity && ((BaseGenericIdEntity) entity).getDynamicAttributes() != null; + } + + protected void importReference(Entity srcEntity, + Entity dstEntity, + EntityImportViewProperty importViewProperty, + View regularView, + CommitContext commitContext, + Collection referenceInfoList) { + Entity srcPropertyValue = srcEntity.getValue(importViewProperty.getName()); + Entity dstPropertyValue = dstEntity.getValue(importViewProperty.getName()); + if (importViewProperty.getView() == null) { + ReferenceInfo referenceInfo = new ReferenceInfo(dstEntity, importViewProperty, srcPropertyValue); + referenceInfoList.add(referenceInfo); + } else { + dstPropertyValue = importEntity(srcPropertyValue, dstPropertyValue, importViewProperty.getView(), regularView, commitContext, referenceInfoList); + dstEntity.setValue(importViewProperty.getName(), dstPropertyValue); + } + } + + protected void importOneToManyCollectionAttribute(Entity srcEntity, + Entity dstEntity, + EntityImportViewProperty importViewProperty, + View regularView, + CommitContext commitContext, + Collection referenceInfoList) { + String propertyName = importViewProperty.getName(); + MetaProperty metaProperty = srcEntity.getMetaClass().getPropertyNN(propertyName); + MetaProperty inverseMetaProperty = metaProperty.getInverse(); + + //filteredItems collection will contain entities filtered by the row-level security + Multimap filteredItems = ArrayListMultimap.create(); + if (srcEntity instanceof BaseGenericIdEntity) { + String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); + DataStore dataStore = storeFactory.get(storeName); + //row-level security works only for entities from RdbmsStore + if (dataStore instanceof RdbmsStore) { + filteredItems = BaseEntityInternalAccess.getFilteredData(srcEntity); + } + } + + Collection srcPropertyValue = srcEntity.getValue(propertyName); + Collection dstPropertyValue = dstEntity.getValue(propertyName); + if (dstPropertyValue == null) dstPropertyValue = new ArrayList<>(); + Collection collection; + try { + collection = srcPropertyValue.getClass().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Error on import entities", e); + } + + if (srcPropertyValue != null) { + for (Entity srcChildEntity : srcPropertyValue) { + if (importViewProperty.getView() != null) { + //create new referenced entity + Entity dstChildEntity = null; + for (Entity _entity : dstPropertyValue) { + if (_entity.equals(srcChildEntity)) { + dstChildEntity = _entity; + break; + } + } + dstChildEntity = importEntity(srcChildEntity, dstChildEntity, importViewProperty.getView(), regularView, commitContext, referenceInfoList); + if (inverseMetaProperty != null) { + dstChildEntity.setValue(inverseMetaProperty.getName(), dstEntity); + } + collection.add(dstChildEntity); + } + } + } + + if (importViewProperty.getCollectionImportPolicy() == CollectionImportPolicy.REMOVE_ABSENT_ITEMS) { + Collection dstValue = dstEntity.getValue(propertyName); + if (dstValue != null) { + Multimap finalFilteredItems = filteredItems; + List collectionItemsToRemove = dstValue.stream() + .filter(entity -> !collection.contains(entity) && + (finalFilteredItems == null || !finalFilteredItems.containsValue(referenceToEntitySupport.getReferenceId(entity)))) + .collect(Collectors.toList()); + for (Entity _entity : collectionItemsToRemove) { + commitContext.addInstanceToRemove(_entity); + } + } + } + + dstEntity.setValue(propertyName, collection); + } + + protected void importManyToManyCollectionAttribute(Entity srcEntity, + Entity dstEntity, + EntityImportViewProperty importViewProperty, + View regularView, + CommitContext commitContext, + Collection referenceInfoList) { + Collection srcPropertyValue = srcEntity.getValue(importViewProperty.getName()); + Collection dstPropertyValue = dstEntity.getValue(importViewProperty.getName()); + if (dstPropertyValue == null) dstPropertyValue = new ArrayList<>(); + if (importViewProperty.getView() != null) { + //create/update passed entities + Collection collection; + try { + collection = srcPropertyValue.getClass().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Error on import entities", e); + } + + for (Entity srcChildEntity : srcPropertyValue) { + //create new referenced entity + Entity dstChildEntity = null; + for (Entity _entity : dstPropertyValue) { + if (_entity.equals(srcChildEntity)) { + dstChildEntity = _entity; + break; + } + } + dstChildEntity = importEntity(srcChildEntity, dstChildEntity, importViewProperty.getView(), regularView, commitContext, referenceInfoList); + collection.add(dstChildEntity); + } + + if (importViewProperty.getCollectionImportPolicy() == CollectionImportPolicy.KEEP_ABSENT_ITEMS) { + Collection existingCollectionValue = dstEntity.getValue(importViewProperty.getName()); + if (existingCollectionValue != null) { + for (Entity existingCollectionItem : existingCollectionValue) { + if (!collection.contains(existingCollectionItem)) collection.add(existingCollectionItem); + } + } + } + + dstEntity.setValue(importViewProperty.getName(), collection); + } else { + //create ReferenceInfo objects - they will be parsed later + Collection existingCollectionValue = dstEntity.getValue(importViewProperty.getName()); + ReferenceInfo referenceInfo = new ReferenceInfo(dstEntity, importViewProperty, srcPropertyValue, existingCollectionValue); + referenceInfoList.add(referenceInfo); + } + } + + protected Entity importEmbeddedAttribute(Entity srcEntity, + Entity dstEntity, + EntityImportViewProperty importViewProperty, + View regularView, + CommitContext commitContext, + Collection referenceInfoList) { + String propertyName = importViewProperty.getName(); + MetaProperty metaProperty = srcEntity.getMetaClass().getPropertyNN(propertyName); + Entity srcEmbeddedEntity = srcEntity.getValue(propertyName); + if (srcEmbeddedEntity == null) { + return null; + } + Entity dstEmbeddedEntity = dstEntity.getValue(propertyName); + MetaClass embeddedAttrMetaClass = metaProperty.getRange().asClass(); + if (dstEmbeddedEntity == null) { + dstEmbeddedEntity = metadata.create(embeddedAttrMetaClass); + } + + SecurityState securityState = null; + if (srcEntity instanceof BaseGenericIdEntity) { + String storeName = metadata.getTools().getStoreName(srcEntity.getMetaClass()); + DataStore dataStore = storeFactory.get(storeName); + //row-level security works only for entities from RdbmsStore + if (dataStore instanceof RdbmsStore) { + persistenceSecurity.restoreSecurityState(srcEmbeddedEntity); + securityState = BaseEntityInternalAccess.getSecurityState(srcEmbeddedEntity); + } + } + + for (EntityImportViewProperty vp : importViewProperty.getView().getProperties()) { + MetaProperty mp = embeddedAttrMetaClass.getPropertyNN(vp.getName()); + if (BaseEntityInternalAccess.isHiddenOrReadOnly(securityState, mp.getName())) { + continue; + } + if (BaseEntityInternalAccess.isRequired(securityState, mp.getName()) && srcEmbeddedEntity.getValue(mp.getName()) == null) { + throw new CustomValidationException(format("Attribute [%s] is required for entity %s", mp.getName(), srcEmbeddedEntity)); + } + if ((mp.getRange().isDatatype() && !"version".equals(mp.getName())) || mp.getRange().isEnum()) { + dstEmbeddedEntity.setValue(vp.getName(), srcEmbeddedEntity.getValue(vp.getName())); + } else if (mp.getRange().isClass()) { + View propertyRegularView = regularView.getProperty(propertyName) != null ? regularView.getProperty(propertyName).getView() : null; + if (metaProperty.getRange().getCardinality() == Range.Cardinality.ONE_TO_MANY) { + importOneToManyCollectionAttribute(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); + } else if (metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) { + importManyToManyCollectionAttribute(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); + } else { + importReference(srcEmbeddedEntity, dstEmbeddedEntity, vp, propertyRegularView, commitContext, referenceInfoList); + } + } + } + + return dstEmbeddedEntity; + } + + /** + * Method finds and set a reference value to the entity or throws EntityImportException if ERROR_ON_MISSING policy + * is violated + */ + protected void processReferenceInfo(ReferenceInfo referenceInfo, CommitContext commitContext, Set loadedEntities) { + Entity entity = referenceInfo.getEntity(); + String propertyName = referenceInfo.getViewProperty().getName(); + MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(propertyName); + if (metaProperty.getRange().getCardinality() == Range.Cardinality.MANY_TO_MANY) { + Collection propertyValue = (Collection) referenceInfo.getPropertyValue(); + if (propertyValue == null) { + entity.setValue(propertyName, null); + return; + } + + Collection collection; + try { + collection = propertyValue.getClass().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Error on import entities", e); + } + + for (Entity childEntity : propertyValue) { + Entity entityFromLoadedEntities = findEntityInCollection(loadedEntities, childEntity); + if (entityFromLoadedEntities != null) { + collection.add(entityFromLoadedEntities); + } else { + Entity entityFromCommitContext = findEntityInCollection(commitContext.getCommitInstances(), childEntity); + if (entityFromCommitContext != null) { + collection.add(entityFromCommitContext); + } else { + LoadContext ctx = LoadContext.create(childEntity.getClass()) + .setSoftDeletion(false) + .setView(View.MINIMAL) + .setId(childEntity.getId()); + Entity loadedReference = dataManager.load(ctx); + if (loadedReference == null) { + if (referenceInfo.getViewProperty().getReferenceImportBehaviour() == ReferenceImportBehaviour.ERROR_ON_MISSING) { + throw new EntityImportException("Referenced entity for property '" + propertyName + "' with id = " + entity.getId() + " is missing"); + } + } else { + collection.add(loadedReference); + loadedEntities.add(loadedReference); + } + } + } + } + + //keep absent collection members if we need it + if (referenceInfo.getViewProperty().getCollectionImportPolicy() == CollectionImportPolicy.KEEP_ABSENT_ITEMS) { + Collection prevCollectionValue = (Collection) referenceInfo.getPrevPropertyValue(); + if (prevCollectionValue != null) { + for (Entity prevCollectionItem : prevCollectionValue) { + if (!collection.contains(prevCollectionItem)) { + collection.add(prevCollectionItem); + } + } + } + } + + entity.setValue(propertyName, collection); + + //row-level security works only for entities from RdbmsStore + String storeName = metadata.getTools().getStoreName(entity.getMetaClass()); + DataStore dataStore = storeFactory.get(storeName); + if (dataStore instanceof RdbmsStore) { + //restore filtered data, otherwise they will be lost + try (Transaction tx = persistence.getTransaction()) { + persistenceSecurity.restoreSecurityStateAndFilteredData((BaseGenericIdEntity) entity); + tx.commit(); + } + } + //end of many-to-many processing block + } else { + //all other reference types (except many-to-many) + Entity propertyValue = (Entity) referenceInfo.getPropertyValue(); + if (propertyValue == null) { + entity.setValue(propertyName, null); + } else { + Entity entityFromLoadedEntities = findEntityInCollection(loadedEntities, propertyValue); + if (entityFromLoadedEntities != null) { + entity.setValue(propertyName, entityFromLoadedEntities); + } else { + Entity entityFromCommitContext = findEntityInCollection(commitContext.getCommitInstances(), propertyValue); + + if (entityFromCommitContext != null) { + entity.setValue(propertyName, entityFromCommitContext); + } else { + LoadContext ctx = LoadContext.create(propertyValue.getClass()) + .setId(propertyValue.getId()); + dataManager.load(ctx); + Entity loadedReference = dataManager.load(ctx); + if (loadedReference == null) { + if (referenceInfo.getViewProperty().getReferenceImportBehaviour() == ReferenceImportBehaviour.ERROR_ON_MISSING) { + throw new EntityImportException("Referenced entity for property '" + propertyName + "' with id = " + propertyValue.getId() + " is missing"); + } + } else { + entity.setValue(propertyName, loadedReference); + loadedEntities.add(loadedReference); + } + } + } + } + } + } + + /** + * Method builds a regular {@link View} from the {@link EntityImportView}. The regular view will include all + * properties defined in the import view. + */ + protected View buildViewFromImportView(EntityImportView importView) { + View regularView = new View(importView.getEntityClass()); + MetaClass metaClass = metadata.getClassNN(importView.getEntityClass()); + for (EntityImportViewProperty importViewProperty : importView.getProperties()) { + EntityImportView importViewPropertyView = importViewProperty.getView(); + if (importViewPropertyView == null) { + MetaProperty metaProperty = metaClass.getPropertyNN(importViewProperty.getName()); + if (metaProperty.getRange().isClass()) { + MetaClass propertyMetaClass = metaProperty.getRange().asClass(); + regularView.addProperty(importViewProperty.getName(), viewRepository.getView(propertyMetaClass, View.MINIMAL)); + } else { + regularView.addProperty(importViewProperty.getName()); + } + } else { + regularView.addProperty(importViewProperty.getName(), buildViewFromImportView(importViewPropertyView)); + } + } + return regularView; + } + + @Nullable + protected Entity findEntityInCollection(Collection collection, Entity entity) { + for (Entity entityFromCollection : collection) { + if (entityFromCollection.equals(entity)) return entityFromCollection; + } + return null; + } + + protected class ReferenceInfo { + protected Entity entity; + protected EntityImportViewProperty viewProperty; + protected Object propertyValue; + protected Object prevPropertyValue; + + public ReferenceInfo(Entity entity, EntityImportViewProperty viewProperty, Object propertyValue) { + this.entity = entity; + this.viewProperty = viewProperty; + this.propertyValue = propertyValue; + } + + public ReferenceInfo(Entity entity, EntityImportViewProperty viewProperty, Object propertyValue, Object prevPropertyValue) { + this.entity = entity; + this.viewProperty = viewProperty; + this.propertyValue = propertyValue; + this.prevPropertyValue = prevPropertyValue; + } + + public EntityImportViewProperty getViewProperty() { + return viewProperty; + } + + public Object getPrevPropertyValue() { + return prevPropertyValue; + } + + public Entity getEntity() { + return entity; + } + + public Object getPropertyValue() { + return propertyValue; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportAPI.java b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportAPI.java index 739d47fe78..9c6fbfe762 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportAPI.java +++ b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportAPI.java @@ -1,72 +1,72 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import java.util.Collection; - -/** - * Class that is used for exporting a collection of entities and importing them. See full javadocs in the {@link - * EntityImportExportService} - */ -public interface EntityImportExportAPI { - - String NAME = "cuba_EntityImportExport"; - - /** - * See documentation for {@link EntityImportExportService#exportEntitiesToZIP(Collection)} - */ - byte[] exportEntitiesToZIP(Collection entities); - - /** - * See documentation for {@link EntityImportExportService#exportEntitiesToZIP(Collection, View)} - */ - byte[] exportEntitiesToZIP(Collection entities, View view); - - /** - * See documentation for {@link EntityImportExportService#exportEntitiesToJSON(Collection, View)} - */ - String exportEntitiesToJSON(Collection entities, View view); - - /** - * See documentation for {@link EntityImportExportService#exportEntitiesToJSON(Collection)} - */ - String exportEntitiesToJSON(Collection entities); - - /** - * See documentation for {@link EntityImportExportService#importEntitiesFromJSON(String, EntityImportView)} - */ - Collection importEntitiesFromJson(String json, EntityImportView view); - - /** - * See documentation for {@link EntityImportExportService#importEntitiesFromZIP(byte[], EntityImportView)} - */ - Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView entityImportView); - - /** - * See documentation for {@link EntityImportExportService#importEntities(Collection, EntityImportView)} - */ - Collection importEntities(Collection entities, EntityImportView view); - - /** - * See documentation for {@link EntityImportExportService#importEntities(Collection, EntityImportView, boolean)} - */ - Collection importEntities(Collection entities, EntityImportView importView, boolean validate); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import java.util.Collection; + +/** + * Class that is used for exporting a collection of entities and importing them. See full javadocs in the {@link + * EntityImportExportService} + */ +public interface EntityImportExportAPI { + + String NAME = "cuba_EntityImportExport"; + + /** + * See documentation for {@link EntityImportExportService#exportEntitiesToZIP(Collection)} + */ + byte[] exportEntitiesToZIP(Collection entities); + + /** + * See documentation for {@link EntityImportExportService#exportEntitiesToZIP(Collection, View)} + */ + byte[] exportEntitiesToZIP(Collection entities, View view); + + /** + * See documentation for {@link EntityImportExportService#exportEntitiesToJSON(Collection, View)} + */ + String exportEntitiesToJSON(Collection entities, View view); + + /** + * See documentation for {@link EntityImportExportService#exportEntitiesToJSON(Collection)} + */ + String exportEntitiesToJSON(Collection entities); + + /** + * See documentation for {@link EntityImportExportService#importEntitiesFromJSON(String, EntityImportView)} + */ + Collection importEntitiesFromJson(String json, EntityImportView view); + + /** + * See documentation for {@link EntityImportExportService#importEntitiesFromZIP(byte[], EntityImportView)} + */ + Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView entityImportView); + + /** + * See documentation for {@link EntityImportExportService#importEntities(Collection, EntityImportView)} + */ + Collection importEntities(Collection entities, EntityImportView view); + + /** + * See documentation for {@link EntityImportExportService#importEntities(Collection, EntityImportView, boolean)} + */ + Collection importEntities(Collection entities, EntityImportView importView, boolean validate); +} diff --git a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportServiceBean.java b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportServiceBean.java index 1275f5974d..3c531c2ac1 100644 --- a/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/app/importexport/EntityImportExportServiceBean.java @@ -1,72 +1,72 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.util.Collection; - -@Service(EntityImportExportService.NAME) -public class EntityImportExportServiceBean implements EntityImportExportService { - - @Inject - protected EntityImportExportAPI entityImportExport; - - @Override - public byte[] exportEntitiesToZIP(Collection entities) { - return entityImportExport.exportEntitiesToZIP(entities); - } - - @Override - public byte[] exportEntitiesToZIP(Collection entities, View view) { - return entityImportExport.exportEntitiesToZIP(entities, view); - } - - @Override - public String exportEntitiesToJSON(Collection entities) { - return entityImportExport.exportEntitiesToJSON(entities); - } - - @Override - public String exportEntitiesToJSON(Collection entities, View view) { - return entityImportExport.exportEntitiesToJSON(entities, view); - } - - @Override - public Collection importEntitiesFromJSON(String json, EntityImportView entityImportView) { - return entityImportExport.importEntitiesFromJson(json, entityImportView); - } - - @Override - public Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView view) { - return entityImportExport.importEntitiesFromZIP(zipBytes, view); - } - - @Override - public Collection importEntities(Collection entities, EntityImportView entityImportView) { - return entityImportExport.importEntities(entities, entityImportView); - } - - @Override - public Collection importEntities(Collection entities, EntityImportView importView, boolean validate) { - return entityImportExport.importEntities(entities, importView, validate); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.Collection; + +@Service(EntityImportExportService.NAME) +public class EntityImportExportServiceBean implements EntityImportExportService { + + @Inject + protected EntityImportExportAPI entityImportExport; + + @Override + public byte[] exportEntitiesToZIP(Collection entities) { + return entityImportExport.exportEntitiesToZIP(entities); + } + + @Override + public byte[] exportEntitiesToZIP(Collection entities, View view) { + return entityImportExport.exportEntitiesToZIP(entities, view); + } + + @Override + public String exportEntitiesToJSON(Collection entities) { + return entityImportExport.exportEntitiesToJSON(entities); + } + + @Override + public String exportEntitiesToJSON(Collection entities, View view) { + return entityImportExport.exportEntitiesToJSON(entities, view); + } + + @Override + public Collection importEntitiesFromJSON(String json, EntityImportView entityImportView) { + return entityImportExport.importEntitiesFromJson(json, entityImportView); + } + + @Override + public Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView view) { + return entityImportExport.importEntitiesFromZIP(zipBytes, view); + } + + @Override + public Collection importEntities(Collection entities, EntityImportView entityImportView) { + return entityImportExport.importEntities(entities, entityImportView); + } + + @Override + public Collection importEntities(Collection entities, EntityImportView importView, boolean validate) { + return entityImportExport.importEntities(entities, importView, validate); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/controllers/FileDownloadController.java b/modules/core/src/com/haulmont/cuba/core/controllers/FileDownloadController.java index 462f9e8953..2a8023cd91 100644 --- a/modules/core/src/com/haulmont/cuba/core/controllers/FileDownloadController.java +++ b/modules/core/src/com/haulmont/cuba/core/controllers/FileDownloadController.java @@ -1,169 +1,169 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.controllers; - -import com.haulmont.bali.util.URLEncodeUtils; -import com.haulmont.cuba.core.app.DataService; -import com.haulmont.cuba.core.app.FileStorageAPI; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; -import com.haulmont.cuba.core.global.FileTypesHelper; -import com.haulmont.cuba.core.global.LoadContext; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.UserSessionManager; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import javax.inject.Inject; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - -/** - * Handles file download requests to the middleware. - *
This controller is deployed in Spring context defined by {@code cuba.dispatcherSpringContextConfig} - * app property. - */ -@Controller -public class FileDownloadController { - - private final Logger log = LoggerFactory.getLogger(FileDownloadController.class); - - @Inject - private UserSessionManager userSessionManager; - - @Inject - private FileStorageAPI fileStorage; - - @Inject - private DataService dataService; - - @RequestMapping(value = "/download", method = RequestMethod.GET) - public void download(HttpServletRequest request, HttpServletResponse response) throws IOException { - UserSession userSession = getSession(request, response); - if (userSession == null) - return; - - AppContext.setSecurityContext(new SecurityContext(userSession)); - try { - File file = null; - FileDescriptor fd = null; - if (request.getParameter("p") != null) - file = getFile(request, response); - else - fd = getFileDescriptor(request, response); - if (fd == null && file == null) - return; - - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Pragma", "no-cache"); - response.setIntHeader("Expires", -1); - response.setHeader("Content-Type", FileTypesHelper.DEFAULT_MIME_TYPE); - - InputStream is = null; - ServletOutputStream os = null; - try { - is = fd != null ? fileStorage.openStream(fd) : FileUtils.openInputStream(file); - os = response.getOutputStream(); - IOUtils.copy(is, os); - os.flush(); - } catch (FileStorageException e) { - log.error("Unable to download file", e); - response.sendError(e.getType().getHttpStatus()); - } catch (Exception ex) { - log.error("Unable to download file", ex); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } finally { - IOUtils.closeQuietly(is); - IOUtils.closeQuietly(os); - } - } finally { - AppContext.setSecurityContext(null); - } - } - - protected UserSession getSession(HttpServletRequest request, HttpServletResponse response) throws IOException { - UUID sessionId; - try { - sessionId = UUID.fromString(request.getParameter("s")); - } catch (Exception e) { - log.error("Error parsing sessionId from URL param", e); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return null; - } - UserSession session = userSessionManager.findSession(sessionId); - if (session == null) - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return session; - } - - protected FileDescriptor getFileDescriptor(HttpServletRequest request, HttpServletResponse response) throws IOException { - UUID fileId; - try { - fileId = UUID.fromString(request.getParameter("f")); - } catch (Exception e) { - log.error("Error parsing fileId from URL param", e); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return null; - } - FileDescriptor fileDescriptor = dataService.load(new LoadContext<>(FileDescriptor.class).setId(fileId)); - if (fileDescriptor == null) - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return fileDescriptor; - } - - public File getFile(HttpServletRequest request, HttpServletResponse response) throws IOException { - String filePath = URLEncodeUtils.decodeUtf8(request.getParameter("p")); - if (filePath != null) { - if (isPermittedDirectory(filePath)) { - return new File(filePath); - } else { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - } - } else { - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - } - return null; - } - - protected boolean isPermittedDirectory(String filePath) { - String directories = AppContext.getProperty("cuba.download.directories"); - if (directories != null && filePath != null ) { - filePath = filePath.replace("\\", "/"); - for (String d : directories.split(";")) { - d = d.replace("\\", "/"); - if (!d.endsWith("/")) - d = d + "/"; - if (filePath.startsWith(d)) { - return true; - } - } - } - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.controllers; + +import com.haulmont.bali.util.URLEncodeUtils; +import com.haulmont.cuba.core.app.DataService; +import com.haulmont.cuba.core.app.FileStorageAPI; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; +import com.haulmont.cuba.core.global.FileTypesHelper; +import com.haulmont.cuba.core.global.LoadContext; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.UserSessionManager; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.inject.Inject; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +/** + * Handles file download requests to the middleware. + *
This controller is deployed in Spring context defined by {@code cuba.dispatcherSpringContextConfig} + * app property. + */ +@Controller +public class FileDownloadController { + + private final Logger log = LoggerFactory.getLogger(FileDownloadController.class); + + @Inject + private UserSessionManager userSessionManager; + + @Inject + private FileStorageAPI fileStorage; + + @Inject + private DataService dataService; + + @RequestMapping(value = "/download", method = RequestMethod.GET) + public void download(HttpServletRequest request, HttpServletResponse response) throws IOException { + UserSession userSession = getSession(request, response); + if (userSession == null) + return; + + AppContext.setSecurityContext(new SecurityContext(userSession)); + try { + File file = null; + FileDescriptor fd = null; + if (request.getParameter("p") != null) + file = getFile(request, response); + else + fd = getFileDescriptor(request, response); + if (fd == null && file == null) + return; + + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setIntHeader("Expires", -1); + response.setHeader("Content-Type", FileTypesHelper.DEFAULT_MIME_TYPE); + + InputStream is = null; + ServletOutputStream os = null; + try { + is = fd != null ? fileStorage.openStream(fd) : FileUtils.openInputStream(file); + os = response.getOutputStream(); + IOUtils.copy(is, os); + os.flush(); + } catch (FileStorageException e) { + log.error("Unable to download file", e); + response.sendError(e.getType().getHttpStatus()); + } catch (Exception ex) { + log.error("Unable to download file", ex); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } finally { + IOUtils.closeQuietly(is); + IOUtils.closeQuietly(os); + } + } finally { + AppContext.setSecurityContext(null); + } + } + + protected UserSession getSession(HttpServletRequest request, HttpServletResponse response) throws IOException { + UUID sessionId; + try { + sessionId = UUID.fromString(request.getParameter("s")); + } catch (Exception e) { + log.error("Error parsing sessionId from URL param", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return null; + } + UserSession session = userSessionManager.findSession(sessionId); + if (session == null) + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return session; + } + + protected FileDescriptor getFileDescriptor(HttpServletRequest request, HttpServletResponse response) throws IOException { + UUID fileId; + try { + fileId = UUID.fromString(request.getParameter("f")); + } catch (Exception e) { + log.error("Error parsing fileId from URL param", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return null; + } + FileDescriptor fileDescriptor = dataService.load(new LoadContext<>(FileDescriptor.class).setId(fileId)); + if (fileDescriptor == null) + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return fileDescriptor; + } + + public File getFile(HttpServletRequest request, HttpServletResponse response) throws IOException { + String filePath = URLEncodeUtils.decodeUtf8(request.getParameter("p")); + if (filePath != null) { + if (isPermittedDirectory(filePath)) { + return new File(filePath); + } else { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } else { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + return null; + } + + protected boolean isPermittedDirectory(String filePath) { + String directories = AppContext.getProperty("cuba.download.directories"); + if (directories != null && filePath != null ) { + filePath = filePath.replace("\\", "/"); + for (String d : directories.split(";")) { + d = d.replace("\\", "/"); + if (!d.endsWith("/")) + d = d + "/"; + if (filePath.startsWith(d)) { + return true; + } + } + } + return false; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/controllers/FileUploadController.java b/modules/core/src/com/haulmont/cuba/core/controllers/FileUploadController.java index f4e7fbab83..8bac755821 100644 --- a/modules/core/src/com/haulmont/cuba/core/controllers/FileUploadController.java +++ b/modules/core/src/com/haulmont/cuba/core/controllers/FileUploadController.java @@ -1,109 +1,109 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.controllers; - -import com.haulmont.cuba.core.app.FileStorageAPI; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.UserSessionManager; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - -@Controller -public class FileUploadController { - - private Logger log = LoggerFactory.getLogger(FileUploadController.class); - - @Inject - private UserSessionManager userSessionManager; - - @Inject - private FileStorageAPI fileStorage; - - @RequestMapping(value = "/upload", method = RequestMethod.POST) - public void upload(HttpServletRequest request, HttpServletResponse response) throws IOException { - UserSession userSession = getSession(request, response); - if (userSession == null) - return; - - AppContext.setSecurityContext(new SecurityContext(userSession)); - try { - InputStream is = request.getInputStream(); - if (is == null) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return; - } - - FileDescriptor fd = getFileDescriptor(request, response); - if (fd == null) - return; - - try { - fileStorage.saveStream(fd, is); - } catch (FileStorageException e) { - log.error("Unable to upload file", e); - response.sendError(e.getType().getHttpStatus()); - } finally { - IOUtils.closeQuietly(is); - } - } finally { - AppContext.setSecurityContext(null); - } - } - - private UserSession getSession(HttpServletRequest request, HttpServletResponse response) throws IOException { - UUID sessionId; - try { - sessionId = UUID.fromString(request.getParameter("s")); - } catch (Exception e) { - log.error("Error parsing sessionId from URL param", e); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return null; - } - UserSession session = userSessionManager.findSession(sessionId); - if (session == null) - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return session; - } - - private FileDescriptor getFileDescriptor(HttpServletRequest request, HttpServletResponse response) throws IOException { - FileDescriptor fd; - try { - fd = FileDescriptor.fromUrlParam(request.getParameter("f")); - } catch (Exception e) { - log.error("Error parsing FileDescriptor from URL param", e); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - return null; - } - return fd; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.controllers; + +import com.haulmont.cuba.core.app.FileStorageAPI; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.UserSessionManager; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +@Controller +public class FileUploadController { + + private Logger log = LoggerFactory.getLogger(FileUploadController.class); + + @Inject + private UserSessionManager userSessionManager; + + @Inject + private FileStorageAPI fileStorage; + + @RequestMapping(value = "/upload", method = RequestMethod.POST) + public void upload(HttpServletRequest request, HttpServletResponse response) throws IOException { + UserSession userSession = getSession(request, response); + if (userSession == null) + return; + + AppContext.setSecurityContext(new SecurityContext(userSession)); + try { + InputStream is = request.getInputStream(); + if (is == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + FileDescriptor fd = getFileDescriptor(request, response); + if (fd == null) + return; + + try { + fileStorage.saveStream(fd, is); + } catch (FileStorageException e) { + log.error("Unable to upload file", e); + response.sendError(e.getType().getHttpStatus()); + } finally { + IOUtils.closeQuietly(is); + } + } finally { + AppContext.setSecurityContext(null); + } + } + + private UserSession getSession(HttpServletRequest request, HttpServletResponse response) throws IOException { + UUID sessionId; + try { + sessionId = UUID.fromString(request.getParameter("s")); + } catch (Exception e) { + log.error("Error parsing sessionId from URL param", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return null; + } + UserSession session = userSessionManager.findSession(sessionId); + if (session == null) + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return session; + } + + private FileDescriptor getFileDescriptor(HttpServletRequest request, HttpServletResponse response) throws IOException { + FileDescriptor fd; + try { + fd = FileDescriptor.fromUrlParam(request.getParameter("f")); + } catch (Exception e) { + log.error("Error parsing FileDescriptor from URL param", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return null; + } + return fd; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacade.java b/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacade.java index 1f0a2c0e7a..ac05e03164 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacade.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacade.java @@ -1,85 +1,85 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.app.ConfigStorageAPI; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManagerAPI; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.Scripting; -import com.haulmont.cuba.core.global.ViewRepository; -import com.haulmont.cuba.core.sys.AbstractViewRepository; -import com.haulmont.cuba.security.app.EntityLogAPI; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; - -@Component("cuba_CachingFacadeMBean") -public class CachingFacade implements CachingFacadeMBean { - - @Inject - private ConfigStorageAPI configStorage; - - @Inject - private EntityLogAPI entityLog; - - @Inject - private Scripting scripting; - - @Inject - private Messages messages; - - @Inject - private ViewRepository viewRepository; - - @Inject - protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; - - @Override - public int getMessagesCacheSize() { - return messages.getCacheSize(); - } - - @Override - public void clearGroovyCache() { - scripting.clearCache(); - } - - @Override - public void clearMessagesCache() { - messages.clearCache(); - } - - @Override - public void clearConfigStorageCache() { - configStorage.clearCache(); - } - - @Override - public void clearEntityLogCache() { - entityLog.invalidateCache(); - } - - @Override - public void clearDynamicAttributesCache() { - dynamicAttributesManagerAPI.loadCache(); - } - - @Override - public void clearViewRepositoryCache() { - ((AbstractViewRepository) viewRepository).reset(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.app.ConfigStorageAPI; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManagerAPI; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.Scripting; +import com.haulmont.cuba.core.global.ViewRepository; +import com.haulmont.cuba.core.sys.AbstractViewRepository; +import com.haulmont.cuba.security.app.EntityLogAPI; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; + +@Component("cuba_CachingFacadeMBean") +public class CachingFacade implements CachingFacadeMBean { + + @Inject + private ConfigStorageAPI configStorage; + + @Inject + private EntityLogAPI entityLog; + + @Inject + private Scripting scripting; + + @Inject + private Messages messages; + + @Inject + private ViewRepository viewRepository; + + @Inject + protected DynamicAttributesManagerAPI dynamicAttributesManagerAPI; + + @Override + public int getMessagesCacheSize() { + return messages.getCacheSize(); + } + + @Override + public void clearGroovyCache() { + scripting.clearCache(); + } + + @Override + public void clearMessagesCache() { + messages.clearCache(); + } + + @Override + public void clearConfigStorageCache() { + configStorage.clearCache(); + } + + @Override + public void clearEntityLogCache() { + entityLog.invalidateCache(); + } + + @Override + public void clearDynamicAttributesCache() { + dynamicAttributesManagerAPI.loadCache(); + } + + @Override + public void clearViewRepositoryCache() { + ((AbstractViewRepository) viewRepository).reset(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacadeMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacadeMBean.java index b7c09ba941..1779f66115 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacadeMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/CachingFacadeMBean.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -public interface CachingFacadeMBean { - - int getMessagesCacheSize(); - - void clearGroovyCache(); - - void clearMessagesCache(); - - void clearConfigStorageCache(); - - void clearEntityLogCache(); - - void clearViewRepositoryCache(); - - void clearDynamicAttributesCache(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +public interface CachingFacadeMBean { + + int getMessagesCacheSize(); + + void clearGroovyCache(); + + void clearMessagesCache(); + + void clearConfigStorageCache(); + + void clearEntityLogCache(); + + void clearViewRepositoryCache(); + + void clearDynamicAttributesCache(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ClusterManagerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/ClusterManagerMBean.java index 8cb8a55d14..0f949db605 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ClusterManagerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ClusterManagerMBean.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedResource; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.ClusterManagerAPI}. - * - */ -@ManagedResource(description = "Controls Middleware cluster membership") -public interface ClusterManagerMBean { - - @ManagedOperation(description = "Join a cluster") - String start(); - - @ManagedOperation(description = "Leave the cluster") - String stop(); - - /** - * @return true if clustering started on this node - */ - boolean isStarted(); - - /** - * @return true if the current node is the master - * @see com.haulmont.cuba.core.app.ClusterManagerAPI#isMaster() - */ - boolean isMaster(); - - /** - * @return string representation of a set of active nodes - * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getCurrentView() - */ - String getCurrentView(); - - /** - * @return threads count that are actively sending cluster messages - * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getActiveThreadsCount() - */ - int getActiveThreadsCount(); - - /** - * @return message count queued to send - * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getMessagesCount() - */ - int getMessagesCount(); - - @ManagedOperation(description = "Shared state statistics") - String printSharedStateStat(); - - @ManagedOperation(description = "Sent/received messages statistics") - String printMessagesStat(); - - @ManagedOperation(description = "Get sent messages count for specified class") - long getSentMessages(String className); - - @ManagedOperation(description = "Get sent bytes for specified class") - long getSentBytes(String className); - - @ManagedOperation(description = "Get received messages count for specified class") - long getReceivedMessages(String className); - - @ManagedOperation(description = "Get received bytes for specified class") - long getReceivedBytes(String className); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.ClusterManagerAPI}. + * + */ +@ManagedResource(description = "Controls Middleware cluster membership") +public interface ClusterManagerMBean { + + @ManagedOperation(description = "Join a cluster") + String start(); + + @ManagedOperation(description = "Leave the cluster") + String stop(); + + /** + * @return true if clustering started on this node + */ + boolean isStarted(); + + /** + * @return true if the current node is the master + * @see com.haulmont.cuba.core.app.ClusterManagerAPI#isMaster() + */ + boolean isMaster(); + + /** + * @return string representation of a set of active nodes + * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getCurrentView() + */ + String getCurrentView(); + + /** + * @return threads count that are actively sending cluster messages + * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getActiveThreadsCount() + */ + int getActiveThreadsCount(); + + /** + * @return message count queued to send + * @see com.haulmont.cuba.core.app.ClusterManagerAPI#getMessagesCount() + */ + int getMessagesCount(); + + @ManagedOperation(description = "Shared state statistics") + String printSharedStateStat(); + + @ManagedOperation(description = "Sent/received messages statistics") + String printMessagesStat(); + + @ManagedOperation(description = "Get sent messages count for specified class") + long getSentMessages(String className); + + @ManagedOperation(description = "Get sent bytes for specified class") + long getSentBytes(String className); + + @ManagedOperation(description = "Get received messages count for specified class") + long getReceivedMessages(String className); + + @ManagedOperation(description = "Get received bytes for specified class") + long getReceivedBytes(String className); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorage.java b/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorage.java index 5316ddb4d6..bba925c744 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorage.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorage.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.app.ConfigStorageAPI; -import com.haulmont.cuba.core.config.ConfigStorageCommon; -import com.haulmont.cuba.security.app.Authenticated; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Map; - -@Component("cuba_ConfigStorageMBean") -public class ConfigStorage implements ConfigStorageMBean { - - @Inject - protected ConfigStorageAPI configStorage; - - @Inject - protected ConfigStorageCommon configStorageCommon; - - @Override - public String printDbProperties() { - return printDbProperties(null); - } - - @Authenticated - @Override - public String printDbProperties(String prefix) { - try { - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : configStorage.getDbProperties().entrySet()) { - if (prefix == null || entry.getKey().startsWith(prefix)) { - sb.append(entry.getKey()).append("=").append(entry.getValue()).append("\n"); - } - } - return sb.toString(); - } catch (Exception e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String getDbProperty(String name) { - if (StringUtils.isBlank(name)) - return "Enter a property name"; - - try { - String value = configStorage.getDbProperty(name); - return name + "=" + value; - } catch (Exception e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String setDbProperty(String name, String value) { - if (StringUtils.isBlank(name)) - return "Enter a property name"; - if (StringUtils.isBlank(value)) - return "Enter a property value"; - - try { - configStorage.setDbProperty(name, value); - return "Property " + name + " set to " + value; - } catch (Exception e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String removeDbProperty(String name) { - try { - configStorage.setDbProperty(name, null); - return "Property " + name + " removed"; - } catch (Exception e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Override - public void clearCache() { - configStorage.clearCache(); - } - - @Override - public String printAppProperties() { - return printAppProperties(null); - } - - @Override - public String printAppProperties(String prefix) { - return configStorageCommon.printAppProperties(prefix); - } - - @Override - public String getAppProperty(String name) { - return configStorageCommon.getAppProperty(name); - } - - @Override - public String setAppProperty(String name, String value) { - return configStorageCommon.setAppProperty(name, value); - } - - @Override - @Authenticated - public String getConfigValue(String classFQN, String methodName) { - return configStorageCommon.getConfigValue(classFQN, methodName, null, null); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.app.ConfigStorageAPI; +import com.haulmont.cuba.core.config.ConfigStorageCommon; +import com.haulmont.cuba.security.app.Authenticated; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Map; + +@Component("cuba_ConfigStorageMBean") +public class ConfigStorage implements ConfigStorageMBean { + + @Inject + protected ConfigStorageAPI configStorage; + + @Inject + protected ConfigStorageCommon configStorageCommon; + + @Override + public String printDbProperties() { + return printDbProperties(null); + } + + @Authenticated + @Override + public String printDbProperties(String prefix) { + try { + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : configStorage.getDbProperties().entrySet()) { + if (prefix == null || entry.getKey().startsWith(prefix)) { + sb.append(entry.getKey()).append("=").append(entry.getValue()).append("\n"); + } + } + return sb.toString(); + } catch (Exception e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String getDbProperty(String name) { + if (StringUtils.isBlank(name)) + return "Enter a property name"; + + try { + String value = configStorage.getDbProperty(name); + return name + "=" + value; + } catch (Exception e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String setDbProperty(String name, String value) { + if (StringUtils.isBlank(name)) + return "Enter a property name"; + if (StringUtils.isBlank(value)) + return "Enter a property value"; + + try { + configStorage.setDbProperty(name, value); + return "Property " + name + " set to " + value; + } catch (Exception e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String removeDbProperty(String name) { + try { + configStorage.setDbProperty(name, null); + return "Property " + name + " removed"; + } catch (Exception e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Override + public void clearCache() { + configStorage.clearCache(); + } + + @Override + public String printAppProperties() { + return printAppProperties(null); + } + + @Override + public String printAppProperties(String prefix) { + return configStorageCommon.printAppProperties(prefix); + } + + @Override + public String getAppProperty(String name) { + return configStorageCommon.getAppProperty(name); + } + + @Override + public String setAppProperty(String name, String value) { + return configStorageCommon.setAppProperty(name, value); + } + + @Override + @Authenticated + public String getConfigValue(String classFQN, String methodName) { + return configStorageCommon.getConfigValue(classFQN, methodName, null, null); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorageMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorageMBean.java index b1846c2cde..2029fec182 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorageMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ConfigStorageMBean.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.security.app.Authenticated; -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; -import org.springframework.jmx.export.annotation.ManagedResource; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.ConfigStorageAPI}. - * - */ -@ManagedResource(description = "Manages configuration properties on Middleware") -public interface ConfigStorageMBean { - - @ManagedOperation(description = "Print all DB-stored properties") - String printDbProperties(); - - @ManagedOperation(description = "Print DB-stored properties, filtering properties by beginning of name") - @ManagedOperationParameters({@ManagedOperationParameter(name = "prefix", description = "")}) - String printDbProperties(String prefix); - - @ManagedOperation(description = "Print a DB-stored property value") - @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) - String getDbProperty(String name); - - @ManagedOperation(description = "Store a property value into the database") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "name", description = ""), - @ManagedOperationParameter(name = "value", description = "") - }) - String setDbProperty(String name, String value); - - @ManagedOperation(description = "Remove a property from the database") - @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) - String removeDbProperty(String name); - - @ManagedOperation(description = "Print all file-stored properties") - String printAppProperties(); - - @ManagedOperation(description = "Print file-stored properties, filtering properties by beginning of name") - @ManagedOperationParameters({@ManagedOperationParameter(name = "prefix", description = "")}) - String printAppProperties(String prefix); - - @ManagedOperation(description = "Print a file-stored property value") - @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) - String getAppProperty(String name); - - @ManagedOperation(description = "Set a file-stored property value in memory until the server restart") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "name", description = ""), - @ManagedOperationParameter(name = "value", description = "") - }) - String setAppProperty(String name, String value); - - @ManagedOperation(description = "Clear cache of DB-based properties") - void clearCache(); - - @ManagedOperation(description = "Invoke a getter method of configuration interface and print the result") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "classFQN", description = "Fully qualified name of a configuration interface"), - @ManagedOperationParameter(name = "methodName", description = "Getter method name") - }) - String getConfigValue(String classFQN, String methodName); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.security.app.Authenticated; +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.ConfigStorageAPI}. + * + */ +@ManagedResource(description = "Manages configuration properties on Middleware") +public interface ConfigStorageMBean { + + @ManagedOperation(description = "Print all DB-stored properties") + String printDbProperties(); + + @ManagedOperation(description = "Print DB-stored properties, filtering properties by beginning of name") + @ManagedOperationParameters({@ManagedOperationParameter(name = "prefix", description = "")}) + String printDbProperties(String prefix); + + @ManagedOperation(description = "Print a DB-stored property value") + @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) + String getDbProperty(String name); + + @ManagedOperation(description = "Store a property value into the database") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "name", description = ""), + @ManagedOperationParameter(name = "value", description = "") + }) + String setDbProperty(String name, String value); + + @ManagedOperation(description = "Remove a property from the database") + @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) + String removeDbProperty(String name); + + @ManagedOperation(description = "Print all file-stored properties") + String printAppProperties(); + + @ManagedOperation(description = "Print file-stored properties, filtering properties by beginning of name") + @ManagedOperationParameters({@ManagedOperationParameter(name = "prefix", description = "")}) + String printAppProperties(String prefix); + + @ManagedOperation(description = "Print a file-stored property value") + @ManagedOperationParameters({@ManagedOperationParameter(name = "name", description = "")}) + String getAppProperty(String name); + + @ManagedOperation(description = "Set a file-stored property value in memory until the server restart") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "name", description = ""), + @ManagedOperationParameter(name = "value", description = "") + }) + String setAppProperty(String name, String value); + + @ManagedOperation(description = "Clear cache of DB-based properties") + void clearCache(); + + @ManagedOperation(description = "Invoke a getter method of configuration interface and print the result") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "classFQN", description = "Fully qualified name of a configuration interface"), + @ManagedOperationParameter(name = "methodName", description = "Getter method name") + }) + String getConfigValue(String classFQN, String methodName); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/EmailerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/EmailerMBean.java index d344245b36..8caa901bd1 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/EmailerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/EmailerMBean.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.sys.jmx.JmxRunAsync; -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; - -/** - * Management interface of the {@link com.haulmont.cuba.core.app.Emailer} MBean. - * - */ -public interface EmailerMBean { - - String getFromAddress(); - void setFromAddress(String address); - - String getSmtpHost(); - void setSmtpHost(String host); - - int getSmtpPort(); - void setSmtpPort(int port); - - String getSmtpUser(); - void setSmtpUser(String user); - - boolean getSmtpAuthRequired(); - void setSmtpAuthRequired(boolean authRequired); - - boolean getStarttlsEnable(); - void setStarttlsEnable(boolean enable); - - boolean getSmtpSslEnabled(); - void setSmtpSslEnabled(boolean enabled); - - int getSmtpTimeoutSec(); - void setSmtpTimeoutSec(int timeoutSec); - - int getSmtpConnectionTimeoutSec(); - void setSmtpConnectionTimeoutSec(int timeoutSec); - - @ManagedOperationParameters({@ManagedOperationParameter(name = "addresses", description = "")}) - String sendTestEmail(String addresses); - - @JmxRunAsync - @ManagedOperation(description = "Migrate existing email history to use file storage") - String migrateEmailsToFileStorage(String password); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.sys.jmx.JmxRunAsync; +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; + +/** + * Management interface of the {@link com.haulmont.cuba.core.app.Emailer} MBean. + * + */ +public interface EmailerMBean { + + String getFromAddress(); + void setFromAddress(String address); + + String getSmtpHost(); + void setSmtpHost(String host); + + int getSmtpPort(); + void setSmtpPort(int port); + + String getSmtpUser(); + void setSmtpUser(String user); + + boolean getSmtpAuthRequired(); + void setSmtpAuthRequired(boolean authRequired); + + boolean getStarttlsEnable(); + void setStarttlsEnable(boolean enable); + + boolean getSmtpSslEnabled(); + void setSmtpSslEnabled(boolean enabled); + + int getSmtpTimeoutSec(); + void setSmtpTimeoutSec(int timeoutSec); + + int getSmtpConnectionTimeoutSec(); + void setSmtpConnectionTimeoutSec(int timeoutSec); + + @ManagedOperationParameters({@ManagedOperationParameter(name = "addresses", description = "")}) + String sendTestEmail(String addresses); + + @JmxRunAsync + @ManagedOperation(description = "Migrate existing email history to use file storage") + String migrateEmailsToFileStorage(String password); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/FileStorageMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/FileStorageMBean.java index f2cd4549ad..0dce0f00a1 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/FileStorageMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/FileStorageMBean.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import java.io.File; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.FileStorageAPI}. - * - */ -public interface FileStorageMBean { - - /** - * @return the root directories of all registered storages - */ - File[] getStorageRoots(); - - /** - * @return the list of file descriptors in the database which have no corresponding files in the storage - */ - String findOrphanDescriptors(); - - /** - * @return the list of files in the storage which have no corresponding descriptors in the database - */ - String findOrphanFiles(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import java.io.File; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.FileStorageAPI}. + * + */ +public interface FileStorageMBean { + + /** + * @return the root directories of all registered storages + */ + File[] getStorageRoots(); + + /** + * @return the list of file descriptors in the database which have no corresponding files in the storage + */ + String findOrphanDescriptors(); + + /** + * @return the list of files in the storage which have no corresponding descriptors in the database + */ + String findOrphanFiles(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/LockManagerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/LockManagerMBean.java index d80cb2c815..c7824b9dbb 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/LockManagerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/LockManagerMBean.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.LockManagerAPI}. - * - */ -public interface LockManagerMBean { - - int getLockCount(); - - String showLocks(); - - void reloadConfiguration(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.LockManagerAPI}. + * + */ +public interface LockManagerMBean { + + int getLockCount(); + + String showLocks(); + + void reloadConfiguration(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ObjectsCacheManagerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/ObjectsCacheManagerMBean.java index ba97d531ee..1f120872c8 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ObjectsCacheManagerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ObjectsCacheManagerMBean.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.cache.ObjectsCacheManagerAPI}. - * - */ -public interface ObjectsCacheManagerMBean { - - int getCacheCount(); - - String printActiveCaches(); - - @ManagedOperationParameters({@ManagedOperationParameter(name = "cacheName", description = "")}) - String printStatsByName(String cacheName); - - @ManagedOperationParameters({@ManagedOperationParameter(name = "cacheName", description = "")}) - String reloadByName(String cacheName); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.cache.ObjectsCacheManagerAPI}. + * + */ +public interface ObjectsCacheManagerMBean { + + int getCacheCount(); + + String printActiveCaches(); + + @ManagedOperationParameters({@ManagedOperationParameter(name = "cacheName", description = "")}) + String printStatsByName(String cacheName); + + @ManagedOperationParameters({@ManagedOperationParameter(name = "cacheName", description = "")}) + String reloadByName(String cacheName); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupport.java b/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupport.java index f1b7263078..2106f8a713 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupport.java @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.PasswordEncryption; -import com.haulmont.cuba.core.sys.encryption.EncryptionModule; -import com.haulmont.cuba.core.sys.encryption.UnsupportedHashMethodException; -import org.apache.commons.lang.StringUtils; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -/** - * PasswordEncryptionSupport MBean implementation - * - */ -@Component("cuba_PasswordEncryptionSupportMBean") -public class PasswordEncryptionSupport implements PasswordEncryptionSupportMBean { - - private static final String UNSUPPORTED_HASH_METHOD = "Unsupported Hash method"; - - @Inject - protected PasswordEncryption passwordEncryption; - - @Override - public String getPasswordHashMethod() { - return passwordEncryption.getHashMethod(); - } - - @Override - public String getSupportedHashMethods() { - Map encryptionModules = AppBeans.getAll(EncryptionModule.class); - Set methods = new HashSet<>(); - for (EncryptionModule module : encryptionModules.values()) { - methods.add(module.getHashMethod()); - } - - return StringUtils.join(methods, ", "); - } - - @Override - public String getRandomPassword() { - return passwordEncryption.generateRandomPassword(); - } - - @Override - public String getHash(String content) { - return passwordEncryption.getHash(content).toString(); - } - - @Override - public String getHash(String content, String salt) { - return passwordEncryption.getHash(content, salt); - } - - @Override - public String getPlainHash(String content) { - return passwordEncryption.getPlainHash(content); - } - - @Override - public String getPasswordHash(String userId, String password) { - UUID userUUID; - try { - userUUID = UUID.fromString(userId); - } catch (Exception e) { - return "Invalid user Id"; - } - - return passwordEncryption.getPasswordHash(userUUID, password); - } - - @Override - public String getSpecificHash(String content, String method) { - EncryptionModule module; - try { - module = getEncryptionModule(method); - } catch (UnsupportedHashMethodException ex) { - return UNSUPPORTED_HASH_METHOD; - } - return module.getHash(content).toString(); - } - - @Override - public String getSpecificPasswordHash(String userId, String password, String method) { - UUID userUUID; - try { - userUUID = UUID.fromString(userId); - } catch (Exception e) { - return "Invalid user Id"; - } - - EncryptionModule module; - try { - module = getEncryptionModule(method); - } catch (UnsupportedHashMethodException ex) { - return UNSUPPORTED_HASH_METHOD; - } - return module.getPasswordHash(userUUID, password); - } - - @Override - public String getSpecificHash(String content, String salt, String method) { - EncryptionModule module; - try { - module = getEncryptionModule(method); - } catch (UnsupportedHashMethodException ex) { - return UNSUPPORTED_HASH_METHOD; - } - return module.getHash(content, salt); - } - - @Override - public String getSpecificPlainHash(String content, String method) { - EncryptionModule module; - try { - module = getEncryptionModule(method); - } catch (UnsupportedHashMethodException ex) { - return UNSUPPORTED_HASH_METHOD; - } - return module.getPlainHash(content); - } - - protected EncryptionModule getEncryptionModule(String hashMethod) { - Map encryptionModules = AppBeans.getAll(EncryptionModule.class); - for (EncryptionModule module : encryptionModules.values()) { - if (StringUtils.equals(hashMethod, module.getHashMethod())) { - return module; - } - } - throw new UnsupportedHashMethodException(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.PasswordEncryption; +import com.haulmont.cuba.core.sys.encryption.EncryptionModule; +import com.haulmont.cuba.core.sys.encryption.UnsupportedHashMethodException; +import org.apache.commons.lang.StringUtils; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * PasswordEncryptionSupport MBean implementation + * + */ +@Component("cuba_PasswordEncryptionSupportMBean") +public class PasswordEncryptionSupport implements PasswordEncryptionSupportMBean { + + private static final String UNSUPPORTED_HASH_METHOD = "Unsupported Hash method"; + + @Inject + protected PasswordEncryption passwordEncryption; + + @Override + public String getPasswordHashMethod() { + return passwordEncryption.getHashMethod(); + } + + @Override + public String getSupportedHashMethods() { + Map encryptionModules = AppBeans.getAll(EncryptionModule.class); + Set methods = new HashSet<>(); + for (EncryptionModule module : encryptionModules.values()) { + methods.add(module.getHashMethod()); + } + + return StringUtils.join(methods, ", "); + } + + @Override + public String getRandomPassword() { + return passwordEncryption.generateRandomPassword(); + } + + @Override + public String getHash(String content) { + return passwordEncryption.getHash(content).toString(); + } + + @Override + public String getHash(String content, String salt) { + return passwordEncryption.getHash(content, salt); + } + + @Override + public String getPlainHash(String content) { + return passwordEncryption.getPlainHash(content); + } + + @Override + public String getPasswordHash(String userId, String password) { + UUID userUUID; + try { + userUUID = UUID.fromString(userId); + } catch (Exception e) { + return "Invalid user Id"; + } + + return passwordEncryption.getPasswordHash(userUUID, password); + } + + @Override + public String getSpecificHash(String content, String method) { + EncryptionModule module; + try { + module = getEncryptionModule(method); + } catch (UnsupportedHashMethodException ex) { + return UNSUPPORTED_HASH_METHOD; + } + return module.getHash(content).toString(); + } + + @Override + public String getSpecificPasswordHash(String userId, String password, String method) { + UUID userUUID; + try { + userUUID = UUID.fromString(userId); + } catch (Exception e) { + return "Invalid user Id"; + } + + EncryptionModule module; + try { + module = getEncryptionModule(method); + } catch (UnsupportedHashMethodException ex) { + return UNSUPPORTED_HASH_METHOD; + } + return module.getPasswordHash(userUUID, password); + } + + @Override + public String getSpecificHash(String content, String salt, String method) { + EncryptionModule module; + try { + module = getEncryptionModule(method); + } catch (UnsupportedHashMethodException ex) { + return UNSUPPORTED_HASH_METHOD; + } + return module.getHash(content, salt); + } + + @Override + public String getSpecificPlainHash(String content, String method) { + EncryptionModule module; + try { + module = getEncryptionModule(method); + } catch (UnsupportedHashMethodException ex) { + return UNSUPPORTED_HASH_METHOD; + } + return module.getPlainHash(content); + } + + protected EncryptionModule getEncryptionModule(String hashMethod) { + Map encryptionModules = AppBeans.getAll(EncryptionModule.class); + for (EncryptionModule module : encryptionModules.values()) { + if (StringUtils.equals(hashMethod, module.getHashMethod())) { + return module; + } + } + throw new UnsupportedHashMethodException(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupportMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupportMBean.java index 4d3f3c1edb..bc63853236 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupportMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/PasswordEncryptionSupportMBean.java @@ -1,89 +1,89 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.*; - -@ManagedResource(description = "Generate hashes for passwords") -public interface PasswordEncryptionSupportMBean { - - @ManagedAttribute(description = "Default Hash method") - String getPasswordHashMethod(); - - @ManagedAttribute(description = "Supported hash methods") - String getSupportedHashMethods(); - - @ManagedOperation(description = "Get random password") - String getRandomPassword(); - - @ManagedOperation(description = "Get hash and salt for content") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash") - }) - String getHash(String content); - - @ManagedOperation(description = "Get hash for content with specified salt") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash"), - @ManagedOperationParameter(name = "salt", description = "Salt") - }) - String getHash(String content, String salt); - - @ManagedOperation(description = "Get plain hash without salt") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash") - }) - String getPlainHash(String content); - - @ManagedOperation(description = "Get hash and salt for password") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "userId", description = "User id"), - @ManagedOperationParameter(name = "password", description = "Password for hash") - }) - String getPasswordHash(String userId, String password); - - @ManagedOperation(description = "Get hash and salt with specified method") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash"), - @ManagedOperationParameter(name = "method", description = "Hash method") - }) - String getSpecificHash(String content, String method); - - @ManagedOperation(description = "Get hash and salt for password") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "userId", description = "User id"), - @ManagedOperationParameter(name = "password", description = "Password for hash"), - @ManagedOperationParameter(name = "method", description = "Hash method") - }) - String getSpecificPasswordHash(String userId, String password, String method); - - @ManagedOperation(description = "Get hash with specified salt and method") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash"), - @ManagedOperationParameter(name = "salt", description = "Salt"), - @ManagedOperationParameter(name = "method", description = "Hash method") - }) - String getSpecificHash(String content, String salt, String method); - - @ManagedOperation(description = "Get plain hash without salt with specified method") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "content", description = "String for hash"), - @ManagedOperationParameter(name = "method", description = "Hash method") - }) - String getSpecificPlainHash(String content, String method); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.*; + +@ManagedResource(description = "Generate hashes for passwords") +public interface PasswordEncryptionSupportMBean { + + @ManagedAttribute(description = "Default Hash method") + String getPasswordHashMethod(); + + @ManagedAttribute(description = "Supported hash methods") + String getSupportedHashMethods(); + + @ManagedOperation(description = "Get random password") + String getRandomPassword(); + + @ManagedOperation(description = "Get hash and salt for content") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash") + }) + String getHash(String content); + + @ManagedOperation(description = "Get hash for content with specified salt") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash"), + @ManagedOperationParameter(name = "salt", description = "Salt") + }) + String getHash(String content, String salt); + + @ManagedOperation(description = "Get plain hash without salt") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash") + }) + String getPlainHash(String content); + + @ManagedOperation(description = "Get hash and salt for password") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "userId", description = "User id"), + @ManagedOperationParameter(name = "password", description = "Password for hash") + }) + String getPasswordHash(String userId, String password); + + @ManagedOperation(description = "Get hash and salt with specified method") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash"), + @ManagedOperationParameter(name = "method", description = "Hash method") + }) + String getSpecificHash(String content, String method); + + @ManagedOperation(description = "Get hash and salt for password") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "userId", description = "User id"), + @ManagedOperationParameter(name = "password", description = "Password for hash"), + @ManagedOperationParameter(name = "method", description = "Hash method") + }) + String getSpecificPasswordHash(String userId, String password, String method); + + @ManagedOperation(description = "Get hash with specified salt and method") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash"), + @ManagedOperationParameter(name = "salt", description = "Salt"), + @ManagedOperationParameter(name = "method", description = "Hash method") + }) + String getSpecificHash(String content, String salt, String method); + + @ManagedOperation(description = "Get plain hash without salt with specified method") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "content", description = "String for hash"), + @ManagedOperationParameter(name = "method", description = "Hash method") + }) + String getSpecificPlainHash(String content, String method); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManager.java b/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManager.java index 8044a7d53d..0d2256f2ac 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManager.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManager.java @@ -1,353 +1,353 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.app.PersistenceConfig; -import com.haulmont.cuba.core.app.PersistenceManagerAPI; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.entity.EntityStatistics; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.QueryParser; -import com.haulmont.cuba.core.global.QueryTransformerFactory; -import com.haulmont.cuba.core.sys.DbInitializationException; -import com.haulmont.cuba.core.sys.DbUpdater; -import com.haulmont.cuba.core.sys.persistence.DbmsType; -import com.haulmont.cuba.security.app.Authenticated; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import javax.persistence.Table; -import java.io.File; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; - -@Component("cuba_PersistenceManagerMBean") -public class PersistenceManager implements PersistenceManagerMBean { - - protected static final Logger log = LoggerFactory.getLogger(PersistenceManager.class); - - @Inject - protected PersistenceManagerAPI persistenceManager; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected DbUpdater dbUpdater; - - @Inject - protected PersistenceSecurity security; - - protected PersistenceConfig persistenceConfig; - - protected ServerConfig serverConfig; - - @Inject - public void setConfiguration(Configuration configuration) { - persistenceConfig = configuration.getConfig(PersistenceConfig.class); - serverConfig = configuration.getConfig(ServerConfig.class); - } - - @Override - public String getDbmsType() { - return DbmsType.getType(); - } - - @Override - public String getDbmsVersion() { - return DbmsType.getVersion(); - } - - @Override - public int getDefaultLookupScreenThreshold() { - return persistenceConfig.getDefaultLookupScreenThreshold(); - } - - @Authenticated - @Override - public void setDefaultLookupScreenThreshold(int value) { - persistenceConfig.setDefaultLookupScreenThreshold(value); - } - - @Override - public int getDefaultLazyCollectionThreshold() { - return persistenceConfig.getDefaultLazyCollectionThreshold(); - } - - @Authenticated - @Override - public void setDefaultLazyCollectionThreshold(int value) { - persistenceConfig.setDefaultLazyCollectionThreshold(value); - } - - @Override - public int getDefaultFetchUI() { - return persistenceConfig.getDefaultFetchUI(); - } - - @Authenticated - @Override - public void setDefaultFetchUI(int value) { - persistenceConfig.setDefaultFetchUI(value); - } - - @Override - public int getDefaultMaxFetchUI() { - return persistenceConfig.getDefaultMaxFetchUI(); - } - - @Authenticated - @Override - public void setDefaultMaxFetchUI(int value) { - persistenceConfig.setDefaultMaxFetchUI(value); - } - - @Override - public String printSoftDeleteTables() { - StringBuilder sb = new StringBuilder(); - for (String table : persistenceManager.getSoftDeleteTables()) { - sb.append(table).append("\n"); - } - return sb.toString(); - } - - @Override - public String printViewRepositoryDump() { - return new ViewRepositoryInfo(metadata).dump(); - } - - @Override - public String printViewRepositoryDumpHtml() { - return new ViewRepositoryInfo(metadata).dumpHtml(); - } - - @Authenticated - @Override - public String updateDatabase(String token) { - if (!"update".equals(token)) - return "Pass 'update' in the method parameter if you really want to update database."; - try { - dbUpdater.updateDatabase(); - return "Updated"; - } catch (Throwable e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Override - public String findUpdateDatabaseScripts() { - try { - List list = dbUpdater.findUpdateDatabaseScripts(); - if (!list.isEmpty()) { - File dbDir = new File(serverConfig.getDbDir()); - - String indent = "\t"; - StrBuilder sb = new StrBuilder(); - sb.append(dbDir.getPath().replace('\\', '/') + "/" + "\n"); - for (String path : list) { - sb.append(indent + path + "\n"); - } - - return sb.toString(); - } else - return "No updates available"; - } catch (DbInitializationException e) { - return e.getMessage(); - } catch (Throwable e) { - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String jpqlLoadList(String queryString) { - try { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - Query query = em.createQuery(queryString); - QueryParser parser = QueryTransformerFactory.createParser(queryString); - Set paramNames = parser.getParamNames(); - for (String paramName : paramNames) { - security.setQueryParam(query, paramName); - } - List resultList = query.getResultList(); - tx.commit(); - - StrBuilder sb = new StrBuilder(); - for (Object element : resultList) { - if (element instanceof Object[]) { - sb.appendWithSeparators((Object[]) element, " | "); - } else { - sb.append(element); - } - sb.append("\n"); - } - return sb.toString(); - } finally { - tx.end(); - } - } catch (Throwable e) { - log.error("jpqlLoadList error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String jpqlExecuteUpdate(String queryString, boolean softDeletion) { - try { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - em.setSoftDeletion(softDeletion); - Query query = em.createQuery(queryString); - int count = query.executeUpdate(); - tx.commit(); - - return "Done: " + count + " entities affected, softDeletion=" + softDeletion; - } finally { - tx.end(); - } - } catch (Throwable e) { - log.error("jpqlExecuteUpdate error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Override - public synchronized String flushStatisticsCache() { - try { - persistenceManager.flushStatisticsCache(); - return "Done"; - } catch (Exception e) { - log.error("flushStatisticsCache error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String refreshStatistics(String entityName) { - if (StringUtils.isBlank(entityName)) - return "Pass an entity name (MetaClass name, e.g. sec$User) or 'all' to refresh statistics for all entities.\n" + - "Be careful, it can take very long time."; - - try { - log.info("Refreshing statistics for " + entityName); - - Consumer refreshStatisticsForEntity = mc -> { - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(mc); - Class javaClass = originalMetaClass.getJavaClass(); - Table annotation = (Table) javaClass.getAnnotation(Table.class); - if (annotation != null) { - persistenceManager.refreshStatisticsForEntity(originalMetaClass.getName()); - } - }; - - if ("all".equals(entityName)) { - for (MetaClass metaClass : metadata.getSession().getClasses()) { - refreshStatisticsForEntity.accept(metaClass); - } - } else { - MetaClass metaClass = metadata.getSession().getClass(entityName); - if (metaClass == null) - return "MetaClass not found: " + entityName; - refreshStatisticsForEntity.accept(metaClass); - } - return "Done"; - } catch (Exception e) { - log.error("refreshStatistics error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Override - public String showStatistics(String entityName) { - try { - Map statistics = persistenceManager.getEntityStatistics(); - if (StringUtils.isBlank(entityName)) { - StringBuilder sb = new StringBuilder(); - sb.append("Displaying statistics for all entities.\n"); - sb.append("To show a particular entity only, pass its name in the method parameter.\n\n"); - - for (EntityStatistics stat : statistics.values()) { - sb.append(stat).append("\n"); - } - - return sb.toString(); - } else { - EntityStatistics es = statistics.get(entityName); - return es == null ? "No such entity" : es.toString(); - } - } catch (Exception e) { - log.error("showStatistics error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public synchronized String enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, - Integer lazyCollectionThreshold, Integer lookupScreenThreshold) { - if (StringUtils.isBlank(name)) - return "Entity name is required"; - try { - EntityStatistics es = persistenceManager.enterStatistics( - name, instanceCount, fetchUI, maxFetchUI, lazyCollectionThreshold, lookupScreenThreshold); - - StringBuilder sb = new StringBuilder("Statistics for ").append(name).append(" changed:\n"); - sb.append("instanceCount=").append(es.getInstanceCount()).append("\n"); - sb.append("fetchUI=").append(es.getFetchUI()).append("\n"); - sb.append("maxFetchUI=").append(es.getMaxFetchUI()).append("\n"); - sb.append("lazyCollectionThreshold=").append(es.getLazyCollectionThreshold()).append("\n"); - sb.append("lookupScreenThreshold=").append(es.getLookupScreenThreshold()).append("\n"); - return sb.toString(); - } catch (Exception e) { - log.error("enterStatistics error", e); - return ExceptionUtils.getStackTrace(e); - } - } - - @Authenticated - @Override - public String deleteStatistics(String name) { - if (StringUtils.isBlank(name)) - return "Entity name is required"; - try { - persistenceManager.deleteStatistics(name); - return "Entity statistics for " + name + " has been deleted"; - } catch (Exception e) { - log.error("deleteStatistics error", e); - return ExceptionUtils.getStackTrace(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.app.PersistenceConfig; +import com.haulmont.cuba.core.app.PersistenceManagerAPI; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.entity.EntityStatistics; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.QueryParser; +import com.haulmont.cuba.core.global.QueryTransformerFactory; +import com.haulmont.cuba.core.sys.DbInitializationException; +import com.haulmont.cuba.core.sys.DbUpdater; +import com.haulmont.cuba.core.sys.persistence.DbmsType; +import com.haulmont.cuba.security.app.Authenticated; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.persistence.Table; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +@Component("cuba_PersistenceManagerMBean") +public class PersistenceManager implements PersistenceManagerMBean { + + protected static final Logger log = LoggerFactory.getLogger(PersistenceManager.class); + + @Inject + protected PersistenceManagerAPI persistenceManager; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected DbUpdater dbUpdater; + + @Inject + protected PersistenceSecurity security; + + protected PersistenceConfig persistenceConfig; + + protected ServerConfig serverConfig; + + @Inject + public void setConfiguration(Configuration configuration) { + persistenceConfig = configuration.getConfig(PersistenceConfig.class); + serverConfig = configuration.getConfig(ServerConfig.class); + } + + @Override + public String getDbmsType() { + return DbmsType.getType(); + } + + @Override + public String getDbmsVersion() { + return DbmsType.getVersion(); + } + + @Override + public int getDefaultLookupScreenThreshold() { + return persistenceConfig.getDefaultLookupScreenThreshold(); + } + + @Authenticated + @Override + public void setDefaultLookupScreenThreshold(int value) { + persistenceConfig.setDefaultLookupScreenThreshold(value); + } + + @Override + public int getDefaultLazyCollectionThreshold() { + return persistenceConfig.getDefaultLazyCollectionThreshold(); + } + + @Authenticated + @Override + public void setDefaultLazyCollectionThreshold(int value) { + persistenceConfig.setDefaultLazyCollectionThreshold(value); + } + + @Override + public int getDefaultFetchUI() { + return persistenceConfig.getDefaultFetchUI(); + } + + @Authenticated + @Override + public void setDefaultFetchUI(int value) { + persistenceConfig.setDefaultFetchUI(value); + } + + @Override + public int getDefaultMaxFetchUI() { + return persistenceConfig.getDefaultMaxFetchUI(); + } + + @Authenticated + @Override + public void setDefaultMaxFetchUI(int value) { + persistenceConfig.setDefaultMaxFetchUI(value); + } + + @Override + public String printSoftDeleteTables() { + StringBuilder sb = new StringBuilder(); + for (String table : persistenceManager.getSoftDeleteTables()) { + sb.append(table).append("\n"); + } + return sb.toString(); + } + + @Override + public String printViewRepositoryDump() { + return new ViewRepositoryInfo(metadata).dump(); + } + + @Override + public String printViewRepositoryDumpHtml() { + return new ViewRepositoryInfo(metadata).dumpHtml(); + } + + @Authenticated + @Override + public String updateDatabase(String token) { + if (!"update".equals(token)) + return "Pass 'update' in the method parameter if you really want to update database."; + try { + dbUpdater.updateDatabase(); + return "Updated"; + } catch (Throwable e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Override + public String findUpdateDatabaseScripts() { + try { + List list = dbUpdater.findUpdateDatabaseScripts(); + if (!list.isEmpty()) { + File dbDir = new File(serverConfig.getDbDir()); + + String indent = "\t"; + StrBuilder sb = new StrBuilder(); + sb.append(dbDir.getPath().replace('\\', '/') + "/" + "\n"); + for (String path : list) { + sb.append(indent + path + "\n"); + } + + return sb.toString(); + } else + return "No updates available"; + } catch (DbInitializationException e) { + return e.getMessage(); + } catch (Throwable e) { + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String jpqlLoadList(String queryString) { + try { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + Query query = em.createQuery(queryString); + QueryParser parser = QueryTransformerFactory.createParser(queryString); + Set paramNames = parser.getParamNames(); + for (String paramName : paramNames) { + security.setQueryParam(query, paramName); + } + List resultList = query.getResultList(); + tx.commit(); + + StrBuilder sb = new StrBuilder(); + for (Object element : resultList) { + if (element instanceof Object[]) { + sb.appendWithSeparators((Object[]) element, " | "); + } else { + sb.append(element); + } + sb.append("\n"); + } + return sb.toString(); + } finally { + tx.end(); + } + } catch (Throwable e) { + log.error("jpqlLoadList error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String jpqlExecuteUpdate(String queryString, boolean softDeletion) { + try { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + em.setSoftDeletion(softDeletion); + Query query = em.createQuery(queryString); + int count = query.executeUpdate(); + tx.commit(); + + return "Done: " + count + " entities affected, softDeletion=" + softDeletion; + } finally { + tx.end(); + } + } catch (Throwable e) { + log.error("jpqlExecuteUpdate error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Override + public synchronized String flushStatisticsCache() { + try { + persistenceManager.flushStatisticsCache(); + return "Done"; + } catch (Exception e) { + log.error("flushStatisticsCache error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String refreshStatistics(String entityName) { + if (StringUtils.isBlank(entityName)) + return "Pass an entity name (MetaClass name, e.g. sec$User) or 'all' to refresh statistics for all entities.\n" + + "Be careful, it can take very long time."; + + try { + log.info("Refreshing statistics for " + entityName); + + Consumer refreshStatisticsForEntity = mc -> { + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalOrThisMetaClass(mc); + Class javaClass = originalMetaClass.getJavaClass(); + Table annotation = (Table) javaClass.getAnnotation(Table.class); + if (annotation != null) { + persistenceManager.refreshStatisticsForEntity(originalMetaClass.getName()); + } + }; + + if ("all".equals(entityName)) { + for (MetaClass metaClass : metadata.getSession().getClasses()) { + refreshStatisticsForEntity.accept(metaClass); + } + } else { + MetaClass metaClass = metadata.getSession().getClass(entityName); + if (metaClass == null) + return "MetaClass not found: " + entityName; + refreshStatisticsForEntity.accept(metaClass); + } + return "Done"; + } catch (Exception e) { + log.error("refreshStatistics error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Override + public String showStatistics(String entityName) { + try { + Map statistics = persistenceManager.getEntityStatistics(); + if (StringUtils.isBlank(entityName)) { + StringBuilder sb = new StringBuilder(); + sb.append("Displaying statistics for all entities.\n"); + sb.append("To show a particular entity only, pass its name in the method parameter.\n\n"); + + for (EntityStatistics stat : statistics.values()) { + sb.append(stat).append("\n"); + } + + return sb.toString(); + } else { + EntityStatistics es = statistics.get(entityName); + return es == null ? "No such entity" : es.toString(); + } + } catch (Exception e) { + log.error("showStatistics error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public synchronized String enterStatistics(String name, Long instanceCount, Integer fetchUI, Integer maxFetchUI, + Integer lazyCollectionThreshold, Integer lookupScreenThreshold) { + if (StringUtils.isBlank(name)) + return "Entity name is required"; + try { + EntityStatistics es = persistenceManager.enterStatistics( + name, instanceCount, fetchUI, maxFetchUI, lazyCollectionThreshold, lookupScreenThreshold); + + StringBuilder sb = new StringBuilder("Statistics for ").append(name).append(" changed:\n"); + sb.append("instanceCount=").append(es.getInstanceCount()).append("\n"); + sb.append("fetchUI=").append(es.getFetchUI()).append("\n"); + sb.append("maxFetchUI=").append(es.getMaxFetchUI()).append("\n"); + sb.append("lazyCollectionThreshold=").append(es.getLazyCollectionThreshold()).append("\n"); + sb.append("lookupScreenThreshold=").append(es.getLookupScreenThreshold()).append("\n"); + return sb.toString(); + } catch (Exception e) { + log.error("enterStatistics error", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @Authenticated + @Override + public String deleteStatistics(String name) { + if (StringUtils.isBlank(name)) + return "Entity name is required"; + try { + persistenceManager.deleteStatistics(name); + return "Entity statistics for " + name + " has been deleted"; + } catch (Exception e) { + log.error("deleteStatistics error", e); + return ExceptionUtils.getStackTrace(e); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManagerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManagerMBean.java index 09bf9b0adb..573aeac35d 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManagerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/PersistenceManagerMBean.java @@ -1,148 +1,148 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; -import org.springframework.jmx.export.annotation.ManagedResource; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.PersistenceManagerAPI}. - * - */ -@ManagedResource(description = "Manages entity statistics and updates database") -public interface PersistenceManagerMBean { - - String getDbmsType(); - String getDbmsVersion(); - - int getDefaultLookupScreenThreshold(); - void setDefaultLookupScreenThreshold(int value); - - int getDefaultLazyCollectionThreshold(); - void setDefaultLazyCollectionThreshold(int value); - - int getDefaultFetchUI(); - void setDefaultFetchUI(int value); - - int getDefaultMaxFetchUI(); - void setDefaultMaxFetchUI(int value); - - /** - * Show list of tables supporting soft deletion. - * @return operation result - */ - @ManagedOperation(description = "Show list of tables supporting soft deletion") - String printSoftDeleteTables(); - - @ManagedOperation(description = "Show list of views with properties from ViewRepository") - String printViewRepositoryDump(); - - @ManagedOperation(description = "Print list of views with properties from ViewRepository as HTML markup") - String printViewRepositoryDumpHtml(); - - /** - * Start the database update. - * @param token 'update' string must be passed to avoid accidental invocation - * @return operation result - */ - @ManagedOperation(description = "Start the database update") - @ManagedOperationParameters({@ManagedOperationParameter(name = "token", description = "Enter 'update' here")}) - String updateDatabase(String token); - - /** - * Show database update scripts that will be executed on next update. - * @return operation result - */ - @ManagedOperation(description = "Show database update scripts that will be executed on next update") - String findUpdateDatabaseScripts(); - - /** - * Execute a JPQL query. - *

The query may contain security-related parameters specified in - * {@link com.haulmont.cuba.core.PersistenceSecurity}. This is a way to test some JPQL code in the real server - * environment

- * @param queryString JPQL query string - * @return list of loaded entities as string - */ - @ManagedOperation(description = "Execute a JPQL query") - @ManagedOperationParameters({@ManagedOperationParameter(name = "queryString", - description = "May contain security-related parameters: session$userLogin, session$userId, session$userGroupId, session$")}) - String jpqlLoadList(String queryString); - - /** - * Execute a JPQL update statement. - * @param queryString JPQL update statement - * @param softDeletion soft deletion sign - * @return number of entity instances affected by update - */ - @ManagedOperation(description = "Execute a JPQL update statement") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "queryString", description = ""), - @ManagedOperationParameter(name = "softDeletion", description = "") - }) - String jpqlExecuteUpdate(String queryString, boolean softDeletion); - - /** - * Calculate and refresh statistics for the specified entity. This method updates statistics in the database table - * and in cache. - * @param entityName entity name or 'all' to refresh for all entities - * @return operation result - */ - @ManagedOperation(description = "Calculate and refresh statistics for the specified entity") - @ManagedOperationParameters({@ManagedOperationParameter(name = "entityName", - description = "MetaClass name, e.g. 'sec$User', or 'all' to refresh for all entities")}) - String refreshStatistics(String entityName); - - /** - * Show current statistics for the specified entity. - * @param entityName entity name or blank to show all entities - * @return operation result - */ - @ManagedOperation(description = "Show current statistics for the specified entity") - @ManagedOperationParameters({@ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User")}) - String showStatistics(String entityName); - - /** - * Manually update statistics for an entity. - */ - @ManagedOperation(description = "Enter statistics for the specified entity") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User"), - @ManagedOperationParameter(name = "instanceCount", description = ""), - @ManagedOperationParameter(name = "fetchUI", description = ""), - @ManagedOperationParameter(name = "maxFetchUI", description = ""), - @ManagedOperationParameter(name = "lazyCollectionThreshold", description = ""), - @ManagedOperationParameter(name = "lookupScreenThreshold", description = "") - }) - String enterStatistics(String entityName, Long instanceCount, Integer fetchUI, Integer maxFetchUI, - Integer lazyCollectionThreshold, Integer lookupScreenThreshold); - - @ManagedOperation(description = "Delete statistics for the specified entity") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User") - }) - String deleteStatistics(String entityName); - - /** - * Flush statistics cache. It will be loaded on a next request. - * @return operation result - */ - @ManagedOperation(description = "Flush statistics cache. It will be reloaded on a next request") - String flushStatisticsCache(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.PersistenceManagerAPI}. + * + */ +@ManagedResource(description = "Manages entity statistics and updates database") +public interface PersistenceManagerMBean { + + String getDbmsType(); + String getDbmsVersion(); + + int getDefaultLookupScreenThreshold(); + void setDefaultLookupScreenThreshold(int value); + + int getDefaultLazyCollectionThreshold(); + void setDefaultLazyCollectionThreshold(int value); + + int getDefaultFetchUI(); + void setDefaultFetchUI(int value); + + int getDefaultMaxFetchUI(); + void setDefaultMaxFetchUI(int value); + + /** + * Show list of tables supporting soft deletion. + * @return operation result + */ + @ManagedOperation(description = "Show list of tables supporting soft deletion") + String printSoftDeleteTables(); + + @ManagedOperation(description = "Show list of views with properties from ViewRepository") + String printViewRepositoryDump(); + + @ManagedOperation(description = "Print list of views with properties from ViewRepository as HTML markup") + String printViewRepositoryDumpHtml(); + + /** + * Start the database update. + * @param token 'update' string must be passed to avoid accidental invocation + * @return operation result + */ + @ManagedOperation(description = "Start the database update") + @ManagedOperationParameters({@ManagedOperationParameter(name = "token", description = "Enter 'update' here")}) + String updateDatabase(String token); + + /** + * Show database update scripts that will be executed on next update. + * @return operation result + */ + @ManagedOperation(description = "Show database update scripts that will be executed on next update") + String findUpdateDatabaseScripts(); + + /** + * Execute a JPQL query. + *

The query may contain security-related parameters specified in + * {@link com.haulmont.cuba.core.PersistenceSecurity}. This is a way to test some JPQL code in the real server + * environment

+ * @param queryString JPQL query string + * @return list of loaded entities as string + */ + @ManagedOperation(description = "Execute a JPQL query") + @ManagedOperationParameters({@ManagedOperationParameter(name = "queryString", + description = "May contain security-related parameters: session$userLogin, session$userId, session$userGroupId, session$")}) + String jpqlLoadList(String queryString); + + /** + * Execute a JPQL update statement. + * @param queryString JPQL update statement + * @param softDeletion soft deletion sign + * @return number of entity instances affected by update + */ + @ManagedOperation(description = "Execute a JPQL update statement") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "queryString", description = ""), + @ManagedOperationParameter(name = "softDeletion", description = "") + }) + String jpqlExecuteUpdate(String queryString, boolean softDeletion); + + /** + * Calculate and refresh statistics for the specified entity. This method updates statistics in the database table + * and in cache. + * @param entityName entity name or 'all' to refresh for all entities + * @return operation result + */ + @ManagedOperation(description = "Calculate and refresh statistics for the specified entity") + @ManagedOperationParameters({@ManagedOperationParameter(name = "entityName", + description = "MetaClass name, e.g. 'sec$User', or 'all' to refresh for all entities")}) + String refreshStatistics(String entityName); + + /** + * Show current statistics for the specified entity. + * @param entityName entity name or blank to show all entities + * @return operation result + */ + @ManagedOperation(description = "Show current statistics for the specified entity") + @ManagedOperationParameters({@ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User")}) + String showStatistics(String entityName); + + /** + * Manually update statistics for an entity. + */ + @ManagedOperation(description = "Enter statistics for the specified entity") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User"), + @ManagedOperationParameter(name = "instanceCount", description = ""), + @ManagedOperationParameter(name = "fetchUI", description = ""), + @ManagedOperationParameter(name = "maxFetchUI", description = ""), + @ManagedOperationParameter(name = "lazyCollectionThreshold", description = ""), + @ManagedOperationParameter(name = "lookupScreenThreshold", description = "") + }) + String enterStatistics(String entityName, Long instanceCount, Integer fetchUI, Integer maxFetchUI, + Integer lazyCollectionThreshold, Integer lookupScreenThreshold); + + @ManagedOperation(description = "Delete statistics for the specified entity") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "entityName", description = "MetaClass name, e.g. sec$User") + }) + String deleteStatistics(String entityName); + + /** + * Flush statistics cache. It will be loaded on a next request. + * @return operation result + */ + @ManagedOperation(description = "Flush statistics cache. It will be reloaded on a next request") + String flushStatisticsCache(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManager.java b/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManager.java index e20b7b257f..bb2658aad1 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManager.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManager.java @@ -1,71 +1,71 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.app.Authenticated; -import groovy.lang.Binding; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component("cuba_ScriptingManagerMBean") -public class ScriptingManager implements ScriptingManagerMBean { - - private final Logger log = LoggerFactory.getLogger(ScriptingManager.class); - - @Inject - protected Configuration configuration; - - @Inject - protected Scripting scripting; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected DataManager dataManager; - - @Override - public String getRootPath() { - return configuration.getConfig(GlobalConfig.class).getConfDir(); - } - - @Authenticated - @Override - public String runGroovyScript(String scriptName) { - try { - Binding binding = new Binding(); - binding.setVariable("persistence", persistence); - binding.setVariable("metadata", metadata); - binding.setVariable("configuration", configuration); - binding.setVariable("dataManager", dataManager); - Object result = scripting.runGroovyScript(scriptName, binding); - return String.valueOf(result); - } catch (Exception e) { - log.error("Error runGroovyScript", e); - return ExceptionUtils.getStackTrace(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.app.Authenticated; +import groovy.lang.Binding; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; + +@Component("cuba_ScriptingManagerMBean") +public class ScriptingManager implements ScriptingManagerMBean { + + private final Logger log = LoggerFactory.getLogger(ScriptingManager.class); + + @Inject + protected Configuration configuration; + + @Inject + protected Scripting scripting; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected DataManager dataManager; + + @Override + public String getRootPath() { + return configuration.getConfig(GlobalConfig.class).getConfDir(); + } + + @Authenticated + @Override + public String runGroovyScript(String scriptName) { + try { + Binding binding = new Binding(); + binding.setVariable("persistence", persistence); + binding.setVariable("metadata", metadata); + binding.setVariable("configuration", configuration); + binding.setVariable("dataManager", dataManager); + Object result = scripting.runGroovyScript(scriptName, binding); + return String.valueOf(result); + } catch (Exception e) { + log.error("Error runGroovyScript", e); + return ExceptionUtils.getStackTrace(e); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManagerMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManagerMBean.java index 2fa30b1f71..a01182fa12 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManagerMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ScriptingManagerMBean.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; -import org.springframework.jmx.export.annotation.ManagedResource; - -/** - * JMX interface for {@link com.haulmont.cuba.core.global.Scripting}. - * - */ -@ManagedResource(description = "Executes Groovy scripts on Middleware") -public interface ScriptingManagerMBean { - - String getRootPath(); - - @ManagedOperation(description = "Execute a Groovy script. Binding contains variables: persistence, metadata, configuration") - @ManagedOperationParameters( - {@ManagedOperationParameter(name = "scriptName", - description = "path to the script relative to conf dir or to the classpath root")}) - String runGroovyScript(String scriptName); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedOperation; +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * JMX interface for {@link com.haulmont.cuba.core.global.Scripting}. + * + */ +@ManagedResource(description = "Executes Groovy scripts on Middleware") +public interface ScriptingManagerMBean { + + String getRootPath(); + + @ManagedOperation(description = "Execute a Groovy script. Binding contains variables: persistence, metadata, configuration") + @ManagedOperationParameters( + {@ManagedOperationParameter(name = "scriptName", + description = "path to the script relative to conf dir or to the classpath root")}) + String runGroovyScript(String scriptName); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/ServerInfoMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/ServerInfoMBean.java index 2f09cafdfd..020df0ce23 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/ServerInfoMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/ServerInfoMBean.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedResource; - -/** - * JMX interface for {@link com.haulmont.cuba.core.app.ServerInfoAPI}. - * - */ -@ManagedResource(description = "Provides basic information about this Middleware unit") -public interface ServerInfoMBean -{ - /** - * @return release number - */ - String getReleaseNumber(); - - /** - * @return release timestamp - */ - String getReleaseTimestamp(); - - /** - * @return this middleware instance identifier - * @see com.haulmont.cuba.core.app.ServerInfoAPI#getServerId() - */ - String getServerId(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * JMX interface for {@link com.haulmont.cuba.core.app.ServerInfoAPI}. + * + */ +@ManagedResource(description = "Provides basic information about this Middleware unit") +public interface ServerInfoMBean +{ + /** + * @return release number + */ + String getReleaseNumber(); + + /** + * @return release timestamp + */ + String getReleaseTimestamp(); + + /** + * @return this middleware instance identifier + * @see com.haulmont.cuba.core.app.ServerInfoAPI#getServerId() + */ + String getServerId(); +} diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounter.java b/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounter.java index 906ca7a913..eeb7435d23 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounter.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounter.java @@ -1,207 +1,207 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import com.haulmont.cuba.core.app.MiddlewareStatisticsAccumulator; -import com.haulmont.cuba.core.sys.AppContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import java.lang.management.ManagementFactory; -import java.util.Set; -import java.util.regex.Pattern; - -@Component("cuba_StatisticsCounterMBean") -public class StatisticsCounter implements StatisticsCounterMBean { - - private Logger log = LoggerFactory.getLogger(StatisticsCounter.class); - - protected final Pattern DS_MBEAN_PATTERN; - - @Inject - protected MiddlewareStatisticsAccumulator accumulator; - - protected volatile ObjectName dbConnPoolObjectName; - - protected volatile boolean dbConnPoolNotFound; - - public StatisticsCounter() { - String name = "CubaDS"; - String jndiName = AppContext.getProperty("cuba.dataSourceJndiName"); - if (jndiName != null) { - String[] parts = jndiName.split("/"); - name = parts[parts.length - 1]; - } - String re = "Catalina:type=DataSource,.*,class=javax.sql.DataSource,name=\".*" + name + "\""; - DS_MBEAN_PATTERN = Pattern.compile(re); - } - - @Override - public Long getActiveTransactionsCount() { - return accumulator.getActiveTransactionsCount(); - } - - @Override - public double getStartedTransactionsCount() { - return accumulator.getStartedTransactionsCount(); - } - - @Override - public Long getCommittedTransactionsCount() { - return accumulator.getCommittedTransactionsCount(); - } - - @Override - public Long getRolledBackTransactionsCount() { - return accumulator.getRolledBackTransactionsCount(); - } - - @Override - public double getTransactionsPerSecond() { - return accumulator.getTransactionsPerSecond(); - } - - @Override - public double getMiddlewareRequestsCount() { - return accumulator.getMiddlewareRequestsCount(); - } - - @Override - public double getMiddlewareRequestsPerSecond() { - return accumulator.getMiddlewareRequestsPerSecond(); - } - - @Override - public double getCubaScheduledTasksCount() { - return accumulator.getCubaScheduledTasksCount(); - } - - @Override - public double getCubaScheduledTasksPerSecond() { - return accumulator.getCubaScheduledTasksPerSecond(); - } - - @Override - public double getSpringScheduledTasksCount() { - return accumulator.getSpringScheduledTasksCount(); - } - - @Override - public double getSpringScheduledTasksPerSecond() { - return accumulator.getSpringScheduledTasksPerSecond(); - } - - private int getDbConnectionPoolMBeanAttr(String attrName) { - if (dbConnPoolNotFound) - return 0; - try { - MBeanServerConnection connection = ManagementFactory.getPlatformMBeanServer(); - if (dbConnPoolObjectName == null) { - Set names = connection.queryNames(null, null); - for (ObjectName name : names) { - if (DS_MBEAN_PATTERN.matcher(name.toString()).matches()) { - dbConnPoolObjectName = name; - break; - } - } - } - if (dbConnPoolObjectName != null) { - return (int) connection.getAttribute(dbConnPoolObjectName, attrName); - } else { - dbConnPoolNotFound = true; - } - } catch (Exception e) { - log.warn("Error DB connection pool attribute " + attrName + ": " + e); - } - return 0; - } - - @Override - public int getDbConnectionPoolNumActive() { - return getDbConnectionPoolMBeanAttr("numActive"); - } - - @Override - public int getDbConnectionPoolNumIdle() { - return getDbConnectionPoolMBeanAttr("numIdle"); - } - - @Override - public int getDbConnectionPoolMaxTotal() { - return getDbConnectionPoolMBeanAttr("maxTotal"); - } - - @Override - public double getAvgDbConnectionPoolNumActive() { - return accumulator.getAvgDbConnectionPoolNumActive(); - } - - @Override - public double getAvgDbConnectionPoolNumIdle() { - return accumulator.getAvgDbConnectionPoolNumIdle(); - } - - @Override - public double getAvgActiveTransactions() { - return accumulator.getAvgActiveTransactionsCount(); - } - - @Override - public double getAvgUserSessions() { - return accumulator.getAvgUserSessions(); - } - - @Override - public double getAvgHeapMemoryUsage() { - return accumulator.getAvgHeapMemoryUsage(); - } - - @Override - public double getAvgNonHeapMemoryUsage() { - return accumulator.getAvgNonHeapMemoryUsage(); - } - - @Override - public double getAvgFreePhysicalMemorySize() { - return accumulator.getAvgFreePhysicalMemorySize(); - } - - @Override - public double getAvgFreeSwapSpaceSize() { - return accumulator.getAvgFreeSwapSpaceSize(); - } - - @Override - public double getAvgSystemCpuLoad() { - return accumulator.getAvgSystemCpuLoad(); - } - - @Override - public double getAvgProcessCpuLoad() { - return accumulator.getAvgProcessCpuLoad(); - } - - @Override - public double getAvgThreadCount() { - return accumulator.getAvgThreadCount(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import com.haulmont.cuba.core.app.MiddlewareStatisticsAccumulator; +import com.haulmont.cuba.core.sys.AppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.Set; +import java.util.regex.Pattern; + +@Component("cuba_StatisticsCounterMBean") +public class StatisticsCounter implements StatisticsCounterMBean { + + private Logger log = LoggerFactory.getLogger(StatisticsCounter.class); + + protected final Pattern DS_MBEAN_PATTERN; + + @Inject + protected MiddlewareStatisticsAccumulator accumulator; + + protected volatile ObjectName dbConnPoolObjectName; + + protected volatile boolean dbConnPoolNotFound; + + public StatisticsCounter() { + String name = "CubaDS"; + String jndiName = AppContext.getProperty("cuba.dataSourceJndiName"); + if (jndiName != null) { + String[] parts = jndiName.split("/"); + name = parts[parts.length - 1]; + } + String re = "Catalina:type=DataSource,.*,class=javax.sql.DataSource,name=\".*" + name + "\""; + DS_MBEAN_PATTERN = Pattern.compile(re); + } + + @Override + public Long getActiveTransactionsCount() { + return accumulator.getActiveTransactionsCount(); + } + + @Override + public double getStartedTransactionsCount() { + return accumulator.getStartedTransactionsCount(); + } + + @Override + public Long getCommittedTransactionsCount() { + return accumulator.getCommittedTransactionsCount(); + } + + @Override + public Long getRolledBackTransactionsCount() { + return accumulator.getRolledBackTransactionsCount(); + } + + @Override + public double getTransactionsPerSecond() { + return accumulator.getTransactionsPerSecond(); + } + + @Override + public double getMiddlewareRequestsCount() { + return accumulator.getMiddlewareRequestsCount(); + } + + @Override + public double getMiddlewareRequestsPerSecond() { + return accumulator.getMiddlewareRequestsPerSecond(); + } + + @Override + public double getCubaScheduledTasksCount() { + return accumulator.getCubaScheduledTasksCount(); + } + + @Override + public double getCubaScheduledTasksPerSecond() { + return accumulator.getCubaScheduledTasksPerSecond(); + } + + @Override + public double getSpringScheduledTasksCount() { + return accumulator.getSpringScheduledTasksCount(); + } + + @Override + public double getSpringScheduledTasksPerSecond() { + return accumulator.getSpringScheduledTasksPerSecond(); + } + + private int getDbConnectionPoolMBeanAttr(String attrName) { + if (dbConnPoolNotFound) + return 0; + try { + MBeanServerConnection connection = ManagementFactory.getPlatformMBeanServer(); + if (dbConnPoolObjectName == null) { + Set names = connection.queryNames(null, null); + for (ObjectName name : names) { + if (DS_MBEAN_PATTERN.matcher(name.toString()).matches()) { + dbConnPoolObjectName = name; + break; + } + } + } + if (dbConnPoolObjectName != null) { + return (int) connection.getAttribute(dbConnPoolObjectName, attrName); + } else { + dbConnPoolNotFound = true; + } + } catch (Exception e) { + log.warn("Error DB connection pool attribute " + attrName + ": " + e); + } + return 0; + } + + @Override + public int getDbConnectionPoolNumActive() { + return getDbConnectionPoolMBeanAttr("numActive"); + } + + @Override + public int getDbConnectionPoolNumIdle() { + return getDbConnectionPoolMBeanAttr("numIdle"); + } + + @Override + public int getDbConnectionPoolMaxTotal() { + return getDbConnectionPoolMBeanAttr("maxTotal"); + } + + @Override + public double getAvgDbConnectionPoolNumActive() { + return accumulator.getAvgDbConnectionPoolNumActive(); + } + + @Override + public double getAvgDbConnectionPoolNumIdle() { + return accumulator.getAvgDbConnectionPoolNumIdle(); + } + + @Override + public double getAvgActiveTransactions() { + return accumulator.getAvgActiveTransactionsCount(); + } + + @Override + public double getAvgUserSessions() { + return accumulator.getAvgUserSessions(); + } + + @Override + public double getAvgHeapMemoryUsage() { + return accumulator.getAvgHeapMemoryUsage(); + } + + @Override + public double getAvgNonHeapMemoryUsage() { + return accumulator.getAvgNonHeapMemoryUsage(); + } + + @Override + public double getAvgFreePhysicalMemorySize() { + return accumulator.getAvgFreePhysicalMemorySize(); + } + + @Override + public double getAvgFreeSwapSpaceSize() { + return accumulator.getAvgFreeSwapSpaceSize(); + } + + @Override + public double getAvgSystemCpuLoad() { + return accumulator.getAvgSystemCpuLoad(); + } + + @Override + public double getAvgProcessCpuLoad() { + return accumulator.getAvgProcessCpuLoad(); + } + + @Override + public double getAvgThreadCount() { + return accumulator.getAvgThreadCount(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounterMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounterMBean.java index 4aa23c8570..c79b640eec 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounterMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/StatisticsCounterMBean.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedResource; - -@ManagedResource(description = "Provides various information about middleware performance statistics") -@SuppressWarnings("unused") -public interface StatisticsCounterMBean { - - Long getActiveTransactionsCount(); - - double getStartedTransactionsCount(); - - Long getCommittedTransactionsCount(); - - Long getRolledBackTransactionsCount(); - - double getTransactionsPerSecond(); - - double getMiddlewareRequestsCount(); - - double getMiddlewareRequestsPerSecond(); - - double getCubaScheduledTasksCount(); - - double getCubaScheduledTasksPerSecond(); - - double getSpringScheduledTasksCount(); - - double getSpringScheduledTasksPerSecond(); - - int getDbConnectionPoolNumActive(); - - int getDbConnectionPoolNumIdle(); - - int getDbConnectionPoolMaxTotal(); - - double getAvgDbConnectionPoolNumActive(); - - double getAvgDbConnectionPoolNumIdle(); - - double getAvgActiveTransactions(); - - double getAvgUserSessions(); - - double getAvgHeapMemoryUsage(); - - double getAvgNonHeapMemoryUsage(); - - double getAvgFreePhysicalMemorySize(); - - double getAvgFreeSwapSpaceSize(); - - double getAvgSystemCpuLoad(); - - double getAvgProcessCpuLoad(); - - double getAvgThreadCount(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedResource; + +@ManagedResource(description = "Provides various information about middleware performance statistics") +@SuppressWarnings("unused") +public interface StatisticsCounterMBean { + + Long getActiveTransactionsCount(); + + double getStartedTransactionsCount(); + + Long getCommittedTransactionsCount(); + + Long getRolledBackTransactionsCount(); + + double getTransactionsPerSecond(); + + double getMiddlewareRequestsCount(); + + double getMiddlewareRequestsPerSecond(); + + double getCubaScheduledTasksCount(); + + double getCubaScheduledTasksPerSecond(); + + double getSpringScheduledTasksCount(); + + double getSpringScheduledTasksPerSecond(); + + int getDbConnectionPoolNumActive(); + + int getDbConnectionPoolNumIdle(); + + int getDbConnectionPoolMaxTotal(); + + double getAvgDbConnectionPoolNumActive(); + + double getAvgDbConnectionPoolNumIdle(); + + double getAvgActiveTransactions(); + + double getAvgUserSessions(); + + double getAvgHeapMemoryUsage(); + + double getAvgNonHeapMemoryUsage(); + + double getAvgFreePhysicalMemorySize(); + + double getAvgFreeSwapSpaceSize(); + + double getAvgSystemCpuLoad(); + + double getAvgProcessCpuLoad(); + + double getAvgThreadCount(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/jmx/UniqueNumbersMBean.java b/modules/core/src/com/haulmont/cuba/core/jmx/UniqueNumbersMBean.java index e9534909f5..5ed4958efc 100644 --- a/modules/core/src/com/haulmont/cuba/core/jmx/UniqueNumbersMBean.java +++ b/modules/core/src/com/haulmont/cuba/core/jmx/UniqueNumbersMBean.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.jmx; - -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; - -/** - * {@link com.haulmont.cuba.core.app.UniqueNumbersAPI} JMX interface. - * - */ -public interface UniqueNumbersMBean { - - @ManagedOperationParameters({@ManagedOperationParameter(name = "domain", description = "")}) - long getCurrentNumber(String domain); - - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "domain", description = ""), - @ManagedOperationParameter(name = "value", description = "") - }) - void setCurrentNumber(String domain, long value); - - @ManagedOperationParameters({@ManagedOperationParameter(name = "domain", description = "")}) - long getNextNumber(String domain); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.jmx; + +import org.springframework.jmx.export.annotation.ManagedOperationParameter; +import org.springframework.jmx.export.annotation.ManagedOperationParameters; + +/** + * {@link com.haulmont.cuba.core.app.UniqueNumbersAPI} JMX interface. + * + */ +public interface UniqueNumbersMBean { + + @ManagedOperationParameters({@ManagedOperationParameter(name = "domain", description = "")}) + long getCurrentNumber(String domain); + + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "domain", description = ""), + @ManagedOperationParameter(name = "value", description = "") + }) + void setCurrentNumber(String domain, long value); + + @ManagedOperationParameters({@ManagedOperationParameter(name = "domain", description = "")}) + long getNextNumber(String domain); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/AfterDeleteEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/AfterDeleteEntityListener.java index 92a30e68e3..507d0af94a 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/AfterDeleteEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/AfterDeleteEntityListener.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.entity.Entity; - -import java.sql.Connection; - -/** - * Defines the contract for handling of entities after they have been deleted or marked as deleted in DB. - */ -public interface AfterDeleteEntityListener { - - /** - * Executes after the object has been deleted or marked as deleted in DB. - *

- * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you - * need to make changes in the database. - * - * @param entity deleted entity - * @param connection JDBC connection to the database of the deleted entity - */ - void onAfterDelete(T entity, Connection connection); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.entity.Entity; + +import java.sql.Connection; + +/** + * Defines the contract for handling of entities after they have been deleted or marked as deleted in DB. + */ +public interface AfterDeleteEntityListener { + + /** + * Executes after the object has been deleted or marked as deleted in DB. + *

+ * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you + * need to make changes in the database. + * + * @param entity deleted entity + * @param connection JDBC connection to the database of the deleted entity + */ + void onAfterDelete(T entity, Connection connection); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/AfterInsertEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/AfterInsertEntityListener.java index f4e56c6d3f..617b92c582 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/AfterInsertEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/AfterInsertEntityListener.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.entity.Entity; - -import java.sql.Connection; - -/** - * Defines the contract for handling entities after they have been inserted into DB. - */ -public interface AfterInsertEntityListener { - - /** - * Executes after the object has been inserted into DB. - *

- * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you - * need to make changes in the database. - * - * @param entity inserted entity - * @param connection JDBC connection to the database with the inserted entity - */ - void onAfterInsert(T entity, Connection connection); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.entity.Entity; + +import java.sql.Connection; + +/** + * Defines the contract for handling entities after they have been inserted into DB. + */ +public interface AfterInsertEntityListener { + + /** + * Executes after the object has been inserted into DB. + *

+ * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you + * need to make changes in the database. + * + * @param entity inserted entity + * @param connection JDBC connection to the database with the inserted entity + */ + void onAfterInsert(T entity, Connection connection); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/AfterUpdateEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/AfterUpdateEntityListener.java index 5ff26e8a71..209d5a8ffb 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/AfterUpdateEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/AfterUpdateEntityListener.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.entity.Entity; - -import java.sql.Connection; - -/** - * Defines the contract for handling of entities after they have been updated in DB. - */ -public interface AfterUpdateEntityListener { - - /** - * Executes after the object has been updated in DB. - *

- * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you - * need to make changes in the database. - * - * @param entity updated entity - * @param connection JDBC connection to the database with the updated entity - */ - void onAfterUpdate(T entity, Connection connection); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.entity.Entity; + +import java.sql.Connection; + +/** + * Defines the contract for handling of entities after they have been updated in DB. + */ +public interface AfterUpdateEntityListener { + + /** + * Executes after the object has been updated in DB. + *

+ * Modification of the entity state or using {@code EntityManager} is impossible here. Use {@code connection} if you + * need to make changes in the database. + * + * @param entity updated entity + * @param connection JDBC connection to the database with the updated entity + */ + void onAfterUpdate(T entity, Connection connection); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/BeforeAttachEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/BeforeAttachEntityListener.java index c9e33d87d0..6ae8775745 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/BeforeAttachEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/BeforeAttachEntityListener.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.entity.Entity; - -/** - * Defines the contract for handling entities right before they are attached to an EntityManager on merge operation. - * - */ -public interface BeforeAttachEntityListener { - - /** - * Executes before the object is attached to an EntityManager on merge operation. - * - * @param entity detached entity - */ - void onBeforeAttach(T entity); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.entity.Entity; + +/** + * Defines the contract for handling entities right before they are attached to an EntityManager on merge operation. + * + */ +public interface BeforeAttachEntityListener { + + /** + * Executes before the object is attached to an EntityManager on merge operation. + * + * @param entity detached entity + */ + void onBeforeAttach(T entity); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/BeforeDeleteEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/BeforeDeleteEntityListener.java index 8608c7af32..7ebc5ed98b 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/BeforeDeleteEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/BeforeDeleteEntityListener.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Defines the contract for handling of entities before they have been deleted or - * marked as deleted in DB. - * - */ -public interface BeforeDeleteEntityListener { - - /** - * Executes before the object has been deleted or marked as deleted in DB. - * - * @param entity deleted entity instance - * @param entityManager EntityManager that owns the entity instance - */ - void onBeforeDelete(T entity, EntityManager entityManager); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Defines the contract for handling of entities before they have been deleted or + * marked as deleted in DB. + * + */ +public interface BeforeDeleteEntityListener { + + /** + * Executes before the object has been deleted or marked as deleted in DB. + * + * @param entity deleted entity instance + * @param entityManager EntityManager that owns the entity instance + */ + void onBeforeDelete(T entity, EntityManager entityManager); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/BeforeDetachEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/BeforeDetachEntityListener.java index 89610d6002..ad03d96de5 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/BeforeDetachEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/BeforeDetachEntityListener.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Defines the contract for handling entities right before they are detached from an EntityManager - * on transaction commit. - * - */ -public interface BeforeDetachEntityListener { - - /** - * Executes before the object is detached from an EntityManager on transaction commit. - * - * @param entity entity instance in managed state - * @param entityManager EntityManager that owns the entity instance - */ - void onBeforeDetach(T entity, EntityManager entityManager); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Defines the contract for handling entities right before they are detached from an EntityManager + * on transaction commit. + * + */ +public interface BeforeDetachEntityListener { + + /** + * Executes before the object is detached from an EntityManager on transaction commit. + * + * @param entity entity instance in managed state + * @param entityManager EntityManager that owns the entity instance + */ + void onBeforeDetach(T entity, EntityManager entityManager); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/BeforeInsertEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/BeforeInsertEntityListener.java index 0252b0d8e8..5e271ba171 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/BeforeInsertEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/BeforeInsertEntityListener.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Defines the contract for handling entities before they have been inserted into DB. - * - */ -public interface BeforeInsertEntityListener { - - /** - * Executes before the object has been inserted into DB. - * - * @param entity inserted entity instance - * @param entityManager EntityManager that owns the entity instance - */ - void onBeforeInsert(T entity, EntityManager entityManager); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Defines the contract for handling entities before they have been inserted into DB. + * + */ +public interface BeforeInsertEntityListener { + + /** + * Executes before the object has been inserted into DB. + * + * @param entity inserted entity instance + * @param entityManager EntityManager that owns the entity instance + */ + void onBeforeInsert(T entity, EntityManager entityManager); +} diff --git a/modules/core/src/com/haulmont/cuba/core/listener/BeforeUpdateEntityListener.java b/modules/core/src/com/haulmont/cuba/core/listener/BeforeUpdateEntityListener.java index 06d35e4f19..e2afab6c69 100644 --- a/modules/core/src/com/haulmont/cuba/core/listener/BeforeUpdateEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/core/listener/BeforeUpdateEntityListener.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Defines the contract for handling of entities before they have been updated in DB. - * - */ -public interface BeforeUpdateEntityListener { - - /** - * Executes before the object has been updated in DB. - * - * @param entity updated entity instance - * @param entityManager EntityManager that owns the entity instance - */ - void onBeforeUpdate(T entity, EntityManager entityManager); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Defines the contract for handling of entities before they have been updated in DB. + * + */ +public interface BeforeUpdateEntityListener { + + /** + * Executes before the object has been updated in DB. + * + * @param entity updated entity instance + * @param entityManager EntityManager that owns the entity instance + */ + void onBeforeUpdate(T entity, EntityManager entityManager); +} diff --git a/modules/core/src/com/haulmont/cuba/core/sys/AppContextLoader.java b/modules/core/src/com/haulmont/cuba/core/sys/AppContextLoader.java index a88b9bb7f5..4272c0e2a2 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/AppContextLoader.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/AppContextLoader.java @@ -1,152 +1,152 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.base.Strings; -import com.haulmont.cuba.core.app.ClusterManagerAPI; -import com.haulmont.cuba.core.global.Stores; -import com.haulmont.cuba.core.sys.persistence.DbmsType; -import com.haulmont.cuba.core.sys.persistence.PersistenceConfigProcessor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link AppContext} loader of the middleware web application. - * - */ -public class AppContextLoader extends AbstractWebAppContextLoader { - - public static final String PERSISTENCE_CONFIG = "cuba.persistenceConfig"; - - private static Logger log = LoggerFactory.getLogger(AppContextLoader.class); - - public static void createPersistenceXml(String storeName) { - String configPropertyName = AppContextLoader.PERSISTENCE_CONFIG; - String fileName = "persistence.xml"; - if (!Stores.isMain(storeName)) { - configPropertyName = configPropertyName + "_" + storeName; - fileName = storeName + "-" + fileName; - } - - String configProperty = AppContext.getProperty(configPropertyName); - if (Strings.isNullOrEmpty(configProperty)) { - log.debug("Property {} is not set, assuming {} is not a RdbmsStore", configPropertyName, storeName); - return; - } - - List files = Splitter.on(AppProperties.SEPARATOR_PATTERN).omitEmptyStrings().trimResults() - .splitToList(configProperty); - if (!Stores.isMain(storeName) && !files.contains("base-persistence.xml")) { - files = new ArrayList<>(files); - files.add(0, "base-persistence.xml"); - } - - PersistenceConfigProcessor processor = new PersistenceConfigProcessor(); - processor.setStorageName(storeName); - processor.setSourceFiles(files); - - String dataDir = AppContext.getProperty("cuba.dataDir"); - processor.setOutputFile(dataDir + "/" + fileName); - - processor.create(); - } - - @Override - protected String getBlock() { - return "core"; - } - - @Override - protected void beforeInitAppContext() { - super.beforeInitAppContext(); - - log.info("DbmsType of the main database is set to " + DbmsType.getType() + DbmsType.getVersion()); - - // Init persistence.xml - Stores.getAll().forEach(AppContextLoader::createPersistenceXml); - } - - @Override - protected ClassPathXmlApplicationContext createApplicationContext(String[] locations) { - return new CubaCoreApplicationContext(locations); - } - - @Override - protected void afterInitAppContext() { - // Start cluster - boolean isMaster = true; - if (Boolean.valueOf(AppContext.getProperty("cuba.cluster.enabled"))) { - ClusterManagerAPI clusterManager = - (ClusterManagerAPI) AppContext.getApplicationContext().getBean(ClusterManagerAPI.NAME); - clusterManager.start(); - isMaster = clusterManager.isMaster(); - } - // Init database - DbUpdater updater = (DbUpdater) AppContext.getApplicationContext().getBean(DbUpdater.NAME); - if (isMaster && Boolean.valueOf(AppContext.getProperty("cuba.automaticDatabaseUpdate"))) { - updateDatabase(updater); - } else { - checkDatabase(updater); - } - } - - protected void updateDatabase(DbUpdater updater) { - try { - updater.updateDatabase(); - } catch (DbInitializationException e) { - throw new RuntimeException("\n" + - "==============================================================================\n" + - "ERROR: Cannot check and update database. See the stacktrace below for details.\n" + - "==============================================================================", e); - } - } - - protected void checkDatabase(DbUpdater updater) { - try { - boolean initialized = updater.dbInitialized(); - if (!initialized) { - throw new IllegalStateException("\n" + - "============================================================================\n" + - "ERROR: Database is not initialized. Set 'cuba.automaticDatabaseUpdate'\n" + - "application property to 'true' to initialize and update database on startup.\n" + - "============================================================================"); - } - List scripts = updater.findUpdateDatabaseScripts(); - if (!scripts.isEmpty()) { - log.warn("\n" + - "====================================================================\n" + - "WARNING: The application contains unapplied database update scripts:\n\n" + - Joiner.on('\n').join(scripts) + "\n\n" + - "Set 'cuba.automaticDatabaseUpdate' application property to 'true' to\n " + - "initialize and update database on startup.\n" + - "===================================================================="); - } - } catch (DbInitializationException e) { - throw new RuntimeException("\n" + - "===================================================================\n" + - "ERROR: Cannot check database. See the stacktrace below for details.\n" + - "===================================================================", e); - } - - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import com.haulmont.cuba.core.app.ClusterManagerAPI; +import com.haulmont.cuba.core.global.Stores; +import com.haulmont.cuba.core.sys.persistence.DbmsType; +import com.haulmont.cuba.core.sys.persistence.PersistenceConfigProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@link AppContext} loader of the middleware web application. + * + */ +public class AppContextLoader extends AbstractWebAppContextLoader { + + public static final String PERSISTENCE_CONFIG = "cuba.persistenceConfig"; + + private static Logger log = LoggerFactory.getLogger(AppContextLoader.class); + + public static void createPersistenceXml(String storeName) { + String configPropertyName = AppContextLoader.PERSISTENCE_CONFIG; + String fileName = "persistence.xml"; + if (!Stores.isMain(storeName)) { + configPropertyName = configPropertyName + "_" + storeName; + fileName = storeName + "-" + fileName; + } + + String configProperty = AppContext.getProperty(configPropertyName); + if (Strings.isNullOrEmpty(configProperty)) { + log.debug("Property {} is not set, assuming {} is not a RdbmsStore", configPropertyName, storeName); + return; + } + + List files = Splitter.on(AppProperties.SEPARATOR_PATTERN).omitEmptyStrings().trimResults() + .splitToList(configProperty); + if (!Stores.isMain(storeName) && !files.contains("base-persistence.xml")) { + files = new ArrayList<>(files); + files.add(0, "base-persistence.xml"); + } + + PersistenceConfigProcessor processor = new PersistenceConfigProcessor(); + processor.setStorageName(storeName); + processor.setSourceFiles(files); + + String dataDir = AppContext.getProperty("cuba.dataDir"); + processor.setOutputFile(dataDir + "/" + fileName); + + processor.create(); + } + + @Override + protected String getBlock() { + return "core"; + } + + @Override + protected void beforeInitAppContext() { + super.beforeInitAppContext(); + + log.info("DbmsType of the main database is set to " + DbmsType.getType() + DbmsType.getVersion()); + + // Init persistence.xml + Stores.getAll().forEach(AppContextLoader::createPersistenceXml); + } + + @Override + protected ClassPathXmlApplicationContext createApplicationContext(String[] locations) { + return new CubaCoreApplicationContext(locations); + } + + @Override + protected void afterInitAppContext() { + // Start cluster + boolean isMaster = true; + if (Boolean.valueOf(AppContext.getProperty("cuba.cluster.enabled"))) { + ClusterManagerAPI clusterManager = + (ClusterManagerAPI) AppContext.getApplicationContext().getBean(ClusterManagerAPI.NAME); + clusterManager.start(); + isMaster = clusterManager.isMaster(); + } + // Init database + DbUpdater updater = (DbUpdater) AppContext.getApplicationContext().getBean(DbUpdater.NAME); + if (isMaster && Boolean.valueOf(AppContext.getProperty("cuba.automaticDatabaseUpdate"))) { + updateDatabase(updater); + } else { + checkDatabase(updater); + } + } + + protected void updateDatabase(DbUpdater updater) { + try { + updater.updateDatabase(); + } catch (DbInitializationException e) { + throw new RuntimeException("\n" + + "==============================================================================\n" + + "ERROR: Cannot check and update database. See the stacktrace below for details.\n" + + "==============================================================================", e); + } + } + + protected void checkDatabase(DbUpdater updater) { + try { + boolean initialized = updater.dbInitialized(); + if (!initialized) { + throw new IllegalStateException("\n" + + "============================================================================\n" + + "ERROR: Database is not initialized. Set 'cuba.automaticDatabaseUpdate'\n" + + "application property to 'true' to initialize and update database on startup.\n" + + "============================================================================"); + } + List scripts = updater.findUpdateDatabaseScripts(); + if (!scripts.isEmpty()) { + log.warn("\n" + + "====================================================================\n" + + "WARNING: The application contains unapplied database update scripts:\n\n" + + Joiner.on('\n').join(scripts) + "\n\n" + + "Set 'cuba.automaticDatabaseUpdate' application property to 'true' to\n " + + "initialize and update database on startup.\n" + + "===================================================================="); + } + } catch (DbInitializationException e) { + throw new RuntimeException("\n" + + "===================================================================\n" + + "ERROR: Cannot check database. See the stacktrace below for details.\n" + + "===================================================================", e); + } + + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/sys/ConfigPersisterImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/ConfigPersisterImpl.java index 01b1d1e585..0b5afd6302 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/ConfigPersisterImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/ConfigPersisterImpl.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.app.ConfigStorageAPI; -import com.haulmont.cuba.core.config.ConfigPersister; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ConfigPersisterImpl implements ConfigPersister { - protected static final Logger log = LoggerFactory.getLogger(ConfigPersisterImpl.class); - - @Override - public String getProperty(SourceType sourceType, String name) { - log.trace("Getting property '" + name + "', source=" + sourceType.name()); - String value; - switch (sourceType) { - case SYSTEM: - value = System.getProperty(name); - break; - case APP: - value = AppContext.getProperty(name); - break; - case DATABASE: - value = AppContext.getProperty(name); - if (StringUtils.isEmpty(value)) - value = getConfigStorageAPI().getDbProperty(name); - break; - default: - throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); - } - return value; - } - - @Override - public void setProperty(SourceType sourceType, String name, String value) { - log.debug("Setting property '" + name + "' to '" + value + "', source=" + sourceType.name()); - switch (sourceType) { - case SYSTEM: - System.setProperty(name, value); - break; - case APP: - AppContext.setProperty(name, value); - break; - case DATABASE: - getConfigStorageAPI().setDbProperty(name, value); - break; - default: - throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); - } - } - - private ConfigStorageAPI getConfigStorageAPI() { - return AppBeans.get(ConfigStorageAPI.NAME); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.app.ConfigStorageAPI; +import com.haulmont.cuba.core.config.ConfigPersister; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConfigPersisterImpl implements ConfigPersister { + protected static final Logger log = LoggerFactory.getLogger(ConfigPersisterImpl.class); + + @Override + public String getProperty(SourceType sourceType, String name) { + log.trace("Getting property '" + name + "', source=" + sourceType.name()); + String value; + switch (sourceType) { + case SYSTEM: + value = System.getProperty(name); + break; + case APP: + value = AppContext.getProperty(name); + break; + case DATABASE: + value = AppContext.getProperty(name); + if (StringUtils.isEmpty(value)) + value = getConfigStorageAPI().getDbProperty(name); + break; + default: + throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); + } + return value; + } + + @Override + public void setProperty(SourceType sourceType, String name, String value) { + log.debug("Setting property '" + name + "' to '" + value + "', source=" + sourceType.name()); + switch (sourceType) { + case SYSTEM: + System.setProperty(name, value); + break; + case APP: + AppContext.setProperty(name, value); + break; + case DATABASE: + getConfigStorageAPI().setDbProperty(name, value); + break; + default: + throw new UnsupportedOperationException("Unsupported config source type: " + sourceType); + } + } + + private ConfigStorageAPI getConfigStorageAPI() { + return AppBeans.get(ConfigStorageAPI.NAME); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/CorePersistentAttributesLoadChecker.java b/modules/core/src/com/haulmont/cuba/core/sys/CorePersistentAttributesLoadChecker.java index 2a37c85421..89b93ecc56 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/CorePersistentAttributesLoadChecker.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/CorePersistentAttributesLoadChecker.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.global.GlobalPersistentAttributesLoadChecker; - -import javax.inject.Inject; -import javax.persistence.EntityManagerFactory; - -public class CorePersistentAttributesLoadChecker extends GlobalPersistentAttributesLoadChecker { - - @Inject - protected Persistence persistence; - - @Override - protected boolean isLoadedSpecificCheck(Object entity, String property, MetaClass metaClass, MetaProperty metaProperty) { - if (metadataTools.isEmbeddable(metaClass) - || (entity instanceof BaseGenericIdEntity && BaseEntityInternalAccess.isNew((BaseGenericIdEntity) entity))) { - //TODO eude: - // this is workaround for unexpected EclipseLink behaviour when PersistenceUnitUtil.isLoaded - // throws exception if embedded entity refers to persistent entity - return checkIsLoadedWithGetter(entity, property); - } - EntityManagerFactory jpaEmf = ((PersistenceImpl) persistence).getJpaEmf(metadataTools.getStoreName(metaClass)); - return jpaEmf.getPersistenceUnitUtil().isLoaded(entity, property); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.global.GlobalPersistentAttributesLoadChecker; + +import javax.inject.Inject; +import javax.persistence.EntityManagerFactory; + +public class CorePersistentAttributesLoadChecker extends GlobalPersistentAttributesLoadChecker { + + @Inject + protected Persistence persistence; + + @Override + protected boolean isLoadedSpecificCheck(Object entity, String property, MetaClass metaClass, MetaProperty metaProperty) { + if (metadataTools.isEmbeddable(metaClass) + || (entity instanceof BaseGenericIdEntity && BaseEntityInternalAccess.isNew((BaseGenericIdEntity) entity))) { + //TODO eude: + // this is workaround for unexpected EclipseLink behaviour when PersistenceUnitUtil.isLoaded + // throws exception if embedded entity refers to persistent entity + return checkIsLoadedWithGetter(entity, property); + } + EntityManagerFactory jpaEmf = ((PersistenceImpl) persistence).getJpaEmf(metadataTools.getStoreName(metaClass)); + return jpaEmf.getPersistenceUnitUtil().isLoaded(entity, property); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/CubaEclipseLinkJpaVendorAdapter.java b/modules/core/src/com/haulmont/cuba/core/sys/CubaEclipseLinkJpaVendorAdapter.java index 29aa9ff8f8..caa0259a91 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/CubaEclipseLinkJpaVendorAdapter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/CubaEclipseLinkJpaVendorAdapter.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect; -import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter; - -import java.util.Map; - -public class CubaEclipseLinkJpaVendorAdapter extends EclipseLinkJpaVendorAdapter { - - protected final EclipseLinkJpaDialect jpaDialect; - - public CubaEclipseLinkJpaVendorAdapter() { - jpaDialect = new CubaEclipseLinkJpaDialect(); - jpaDialect.setLazyDatabaseTransaction(true); - } - - @Override - public Map getJpaPropertyMap() { - Map map = super.getJpaPropertyMap(); - for (String name : AppContext.getPropertyNames()) { - if (name.startsWith("eclipselink.")) { - map.put(name, AppContext.getProperty(name)); - } - } - return map; - } - - @Override - public EclipseLinkJpaDialect getJpaDialect() { - return jpaDialect; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect; +import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter; + +import java.util.Map; + +public class CubaEclipseLinkJpaVendorAdapter extends EclipseLinkJpaVendorAdapter { + + protected final EclipseLinkJpaDialect jpaDialect; + + public CubaEclipseLinkJpaVendorAdapter() { + jpaDialect = new CubaEclipseLinkJpaDialect(); + jpaDialect.setLazyDatabaseTransaction(true); + } + + @Override + public Map getJpaPropertyMap() { + Map map = super.getJpaPropertyMap(); + for (String name : AppContext.getPropertyNames()) { + if (name.startsWith("eclipselink.")) { + map.put(name, AppContext.getProperty(name)); + } + } + return map; + } + + @Override + public EclipseLinkJpaDialect getJpaDialect() { + return jpaDialect; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/DefaultPermissionValuesConfig.java b/modules/core/src/com/haulmont/cuba/core/sys/DefaultPermissionValuesConfig.java index b2c160659f..d7701a06bf 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/DefaultPermissionValuesConfig.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/DefaultPermissionValuesConfig.java @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.google.common.base.Strings; -import com.haulmont.bali.util.Dom4j; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.Resources; -import com.haulmont.cuba.security.entity.Permission; -import com.haulmont.cuba.security.entity.PermissionType; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; -import org.dom4j.Document; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Class is used for working with default permission values. - * Default permission values is used when no role define an explicit value for permissions from - * {@code cuba.defaultPermissionValuesConfig} files. - */ -@Component("cuba_DefaultPermissionValuesConfig") -public class DefaultPermissionValuesConfig { - - private final Logger log = LoggerFactory.getLogger(DefaultPermissionValuesConfig.class); - - protected ReadWriteLock lock = new ReentrantReadWriteLock(); - - protected Map permissionValues = new ConcurrentHashMap<>(); - - protected volatile boolean initialized; - - @Inject - protected Resources resources; - - @Inject - protected Metadata metadata; - - protected void checkInitialized() { - if (!initialized) { - lock.readLock().unlock(); - lock.writeLock().lock(); - try { - if (!initialized) { - log.info("Initializing default permission values"); - init(); - initialized = true; - } - } finally { - lock.readLock().lock(); - lock.writeLock().unlock(); - } - } - } - - protected void init() { - permissionValues.clear(); - - String configName = AppContext.getProperty("cuba.defaultPermissionValuesConfig"); - if (!StringUtils.isBlank(configName)) { - StrTokenizer tokenizer = new StrTokenizer(configName); - for (String fileName : tokenizer.getTokenArray()) { - parseConfigFile(fileName); - } - } - } - - protected void parseConfigFile(String fileName) { - String fileContent = resources.getResourceAsString(fileName); - if (!Strings.isNullOrEmpty(fileContent)) { - Document document = Dom4j.readDocument(fileContent); - List permissionElements = Dom4j.elements(document.getRootElement(), "permission"); - - for (Element element : permissionElements) { - String target = element.attributeValue("target"); - Integer value = Integer.valueOf(element.attributeValue("value")); - Integer type = Integer.valueOf(element.attributeValue("type")); - Permission permission = metadata.create(Permission.class); - permission.setTarget(target); - permission.setType(PermissionType.fromId(type)); - permission.setValue(value); - permissionValues.put(target, permission); - } - } else { - log.error("File {} not found", fileName); - } - } - - public Map getDefaultPermissionValues() { - lock.readLock().lock(); - try { - checkInitialized(); - return new HashMap<>(permissionValues); - } finally { - lock.readLock().unlock(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.google.common.base.Strings; +import com.haulmont.bali.util.Dom4j; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.Resources; +import com.haulmont.cuba.security.entity.Permission; +import com.haulmont.cuba.security.entity.PermissionType; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; +import org.dom4j.Document; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Class is used for working with default permission values. + * Default permission values is used when no role define an explicit value for permissions from + * {@code cuba.defaultPermissionValuesConfig} files. + */ +@Component("cuba_DefaultPermissionValuesConfig") +public class DefaultPermissionValuesConfig { + + private final Logger log = LoggerFactory.getLogger(DefaultPermissionValuesConfig.class); + + protected ReadWriteLock lock = new ReentrantReadWriteLock(); + + protected Map permissionValues = new ConcurrentHashMap<>(); + + protected volatile boolean initialized; + + @Inject + protected Resources resources; + + @Inject + protected Metadata metadata; + + protected void checkInitialized() { + if (!initialized) { + lock.readLock().unlock(); + lock.writeLock().lock(); + try { + if (!initialized) { + log.info("Initializing default permission values"); + init(); + initialized = true; + } + } finally { + lock.readLock().lock(); + lock.writeLock().unlock(); + } + } + } + + protected void init() { + permissionValues.clear(); + + String configName = AppContext.getProperty("cuba.defaultPermissionValuesConfig"); + if (!StringUtils.isBlank(configName)) { + StrTokenizer tokenizer = new StrTokenizer(configName); + for (String fileName : tokenizer.getTokenArray()) { + parseConfigFile(fileName); + } + } + } + + protected void parseConfigFile(String fileName) { + String fileContent = resources.getResourceAsString(fileName); + if (!Strings.isNullOrEmpty(fileContent)) { + Document document = Dom4j.readDocument(fileContent); + List permissionElements = Dom4j.elements(document.getRootElement(), "permission"); + + for (Element element : permissionElements) { + String target = element.attributeValue("target"); + Integer value = Integer.valueOf(element.attributeValue("value")); + Integer type = Integer.valueOf(element.attributeValue("type")); + Permission permission = metadata.create(Permission.class); + permission.setTarget(target); + permission.setType(PermissionType.fromId(type)); + permission.setValue(value); + permissionValues.put(target, permission); + } + } else { + log.error("File {} not found", fileName); + } + } + + public Map getDefaultPermissionValues() { + lock.readLock().lock(); + try { + checkInitialized(); + return new HashMap<>(permissionValues); + } finally { + lock.readLock().unlock(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerContext.java b/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerContext.java index 748dd1fb8c..8ee9efebb7 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerContext.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerContext.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; - -public class EntityManagerContext { - - private boolean softDeletion = true; - - private Map dbHints = new HashMap<>(); - - private Map attributes = new HashMap<>(); - - public boolean isSoftDeletion() { - return softDeletion; - } - - public void setSoftDeletion(boolean softDeletion) { - this.softDeletion = softDeletion; - } - - public Map getDbHints() { - return dbHints; - } - - public void setDbHints(Map dbHints) { - this.dbHints = dbHints; - } - - public void setAttribute(Object key, Object value) { - attributes.put(key, value); - } - - @Nullable - public T getAttribute(Object key) { - return (T) attributes.get(key); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +public class EntityManagerContext { + + private boolean softDeletion = true; + + private Map dbHints = new HashMap<>(); + + private Map attributes = new HashMap<>(); + + public boolean isSoftDeletion() { + return softDeletion; + } + + public void setSoftDeletion(boolean softDeletion) { + this.softDeletion = softDeletion; + } + + public Map getDbHints() { + return dbHints; + } + + public void setDbHints(Map dbHints) { + this.dbHints = dbHints; + } + + public void setAttribute(Object key, Object value) { + attributes.put(key, value); + } + + @Nullable + public T getAttribute(Object key) { + return (T) attributes.get(key); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerImpl.java index c55787ae58..f8d0a22de6 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/EntityManagerImpl.java @@ -1,455 +1,455 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.google.common.collect.Sets; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.listener.EntityListenerManager; -import com.haulmont.cuba.core.sys.listener.EntityListenerType; -import com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.reflect.FieldUtils; -import org.eclipse.persistence.internal.helper.CubaUtil; -import org.eclipse.persistence.sessions.UnitOfWork; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.persistence.EntityNotFoundException; -import java.lang.reflect.Field; -import java.sql.Connection; -import java.util.*; - -public class EntityManagerImpl implements EntityManager { - - protected javax.persistence.EntityManager delegate; - - protected UserSession userSession; - protected Metadata metadata; - protected EntityListenerManager entityListenerMgr; - protected PersistenceImplSupport support; - - protected boolean softDeletion = true; - - private Logger log = LoggerFactory.getLogger(EntityManagerImpl.class); - - protected EntityManagerImpl(javax.persistence.EntityManager jpaEntityManager, UserSession userSession) { - this.delegate = jpaEntityManager; - this.userSession = userSession; - this.metadata = AppBeans.get(Metadata.NAME); - this.entityListenerMgr = AppBeans.get(EntityListenerManager.NAME); - this.support = AppBeans.get(PersistenceImplSupport.NAME); - } - - @Override - public javax.persistence.EntityManager getDelegate() { - return delegate; - } - - @Override - public boolean isSoftDeletion() { - return softDeletion; - } - - @Override - public void setSoftDeletion(boolean softDeletion) { - this.softDeletion = softDeletion; - CubaUtil.setSoftDeletion(softDeletion); - CubaUtil.setOriginalSoftDeletion(softDeletion); - } - - @Override - public void persist(Entity entity) { - delegate.persist(entity); - support.registerInstance(entity, this); - } - - @Override - public T merge(T entity) { - log.debug("merge {}", entity); - - if (PersistenceHelper.isManaged(entity)) - return entity; - - String storeName = support.getStorageName(delegate.unwrap(UnitOfWork.class)); - entityListenerMgr.fireListener(entity, EntityListenerType.BEFORE_ATTACH, storeName); - - if ((PersistenceHelper.isNew(entity) || !PersistenceHelper.isDetached(entity)) && entity.getId() != null) { - // if a new instance is passed to merge(), we suppose it is persistent but "not detached" - Entity destEntity = findOrCreate(entity.getClass(), entity.getId()); - deepCopyIgnoringNulls(entity, destEntity, Sets.newIdentityHashSet()); - //noinspection unchecked - return (T) destEntity; - } - - T merged = internalMerge(entity); - support.registerInstance(merged, this); - return merged; - } - - @Override - @Deprecated - public T merge(T entity, @Nullable View view) { - T managed = merge(entity); - if (view != null) { - metadata.getTools().traverseAttributesByView(view, managed, (e, p) -> { /* do nothing, just fetch */ }); - } - return managed; - } - - @Override - @Deprecated - public T merge(T entity, @Nullable String viewName) { - if (viewName != null) { - return merge(entity, metadata.getViewRepository().getView(entity.getClass(), viewName)); - } else { - return merge(entity); - } - } - - @Override - public void remove(Entity entity) { - log.debug("remove {}", entity); - - if (PersistenceHelper.isDetached(entity)) { - entity = internalMerge(entity); - } - if (entity instanceof SoftDelete && softDeletion) { - TimeSource timeSource = AppBeans.get(TimeSource.NAME); - ((SoftDelete) entity).setDeleteTs(timeSource.currentTimestamp()); - ((SoftDelete) entity).setDeletedBy(userSession != null ? userSession.getUser().getLogin() : ""); - } else { - delegate.remove(entity); - if (entity instanceof BaseGenericIdEntity) { - BaseEntityInternalAccess.setRemoved((BaseGenericIdEntity) entity, true); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public , K> T find(Class entityClass, K id) { - Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); - Preconditions.checkNotNullArgument(id, "id is null"); - - Object realId = getRealId(id); - log.debug("find {} by id={}", entityClass.getSimpleName(), realId); - MetaClass metaClass = metadata.getExtendedEntities().getEffectiveMetaClass(entityClass); - Class javaClass = metaClass.getJavaClass(); - - T entity = delegate.find(javaClass, realId); - if (entity instanceof SoftDelete && ((SoftDelete) entity).isDeleted() && isSoftDeletion()) - return null; // in case of entity cache - else - return entity; - } - - @Nullable - @Override - public , K> T find(Class entityClass, K id, View... views) { - Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); - Preconditions.checkNotNullArgument(id, "id is null"); - - MetaClass metaClass = metadata.getExtendedEntities().getEffectiveMetaClass(entityClass); - return findWithViews(metaClass, id, Arrays.asList(views)); - } - - @Nullable - @Override - public , K> T find(Class entityClass, K id, String... viewNames) { - View[] viewArray = new View[viewNames.length]; - for (int i = 0; i < viewNames.length; i++) { - viewArray[i] = metadata.getViewRepository().getView(entityClass, viewNames[i]); - } - return find(entityClass, id, viewArray); - } - - protected T findWithViews(MetaClass metaClass, Object id, List views) { - Object realId = getRealId(id); - log.debug("find {} by id={}, views={}", metaClass.getJavaClass().getSimpleName(), realId, views); - - String pkName = metadata.getTools().getPrimaryKeyName(metaClass); - if (pkName == null) - throw new IllegalStateException("Cannot determine PK name for entity " + metaClass); - - Query query = createQuery(String.format("select e from %s e where e.%s = ?1", metaClass.getName(), pkName)); - ((QueryImpl) query).setSingleResultExpected(true); - query.setParameter(1, realId); - for (View view : views) { - query.addView(view); - } - //noinspection unchecked - return (T) query.getFirstResult(); - } - - @SuppressWarnings("unchecked") - @Override - public , K> T getReference(Class clazz, K id) { - Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(clazz); - - T reference = delegate.getReference(effectiveClass, getRealId(id)); - BaseEntityInternalAccess.setNew((BaseGenericIdEntity) reference, false); - return reference; - } - - protected TypedQuery createQueryInstance(boolean isNative, Class resultClass) { - return new QueryImpl<>(this, isNative, resultClass); - } - - @Override - public Query createQuery() { - return createQueryInstance(false, null); - } - - @Override - public Query createQuery(String qlStr) { - Query query = createQueryInstance(false, null); - query.setQueryString(qlStr); - return query; - } - - @Override - public TypedQuery createQuery(String qlString, Class resultClass) { - TypedQuery query = createQueryInstance(false, resultClass); - query.setQueryString(qlString); - return query; - } - - @Override - public Query createNativeQuery() { - return createQueryInstance(true, null); - } - - @Override - public Query createNativeQuery(String sql) { - Query query = createQueryInstance(true, null); - query.setQueryString(sql); - return query; - } - - @Override - public TypedQuery createNativeQuery(String sql, Class resultClass) { - TypedQuery query = createQueryInstance(true, resultClass); - query.setQueryString(sql); - return query; - } - - @Override - @Deprecated - public void fetch(Entity entity, View view) { - } - - @Nullable - @Override - public , K> T reload(Class entityClass, K id, String... viewNames) { - Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); - Preconditions.checkNotNullArgument(id, "id is null"); - - if (id instanceof IdProxy && ((IdProxy) id).get() == null) { - return null; - } - - T entity = find(entityClass, id, viewNames); - return entity; - } - - @SuppressWarnings("unchecked") - @Nullable - @Override - public T reload(T entity, String... viewNames) { - Preconditions.checkNotNullArgument(entity, "entity is null"); - - if (entity.getId() instanceof IdProxy && ((IdProxy) entity.getId()).get() == null) { - return null; - } - - Entity resultEntity = find(entity.getClass(), entity.getId(), viewNames); - return (T) resultEntity; - } - - @Override - public T reloadNN(T entity, String... viewNames) { - T reloaded = reload(entity, viewNames); - if (reloaded == null) - throw new EntityNotFoundException("Entity " + entity + " has been deleted"); - return reloaded; - } - - @Override - public void flush() { - log.debug("flush"); - support.fireEntityListeners(this); - delegate.flush(); - } - - @Override - public Connection getConnection() { - return delegate.unwrap(Connection.class); - } - - /** - * Copies all property values from source to dest excluding null values. - */ - protected void deepCopyIgnoringNulls(Entity source, Entity dest, Set visited) { - if (visited.contains(source)) - return; - visited.add(source); - - MetadataTools metadataTools = metadata.getTools(); - for (MetaProperty srcProperty : source.getMetaClass().getProperties()) { - String name = srcProperty.getName(); - - if (!PersistenceHelper.isLoaded(source, name)) { - continue; - } - - if (srcProperty.isReadOnly()) { - continue; - } - - Object value = source.getValue(name); - if (value == null) { - continue; - } - - if (srcProperty.getRange().isClass() && !metadataTools.isEmbedded(srcProperty)) { - if (!metadataTools.isOwningSide(srcProperty)) - continue; - - Class refClass = srcProperty.getRange().asClass().getJavaClass(); - if (!metadataTools.isPersistent(refClass)) - continue; - - if (srcProperty.getRange().getCardinality().isMany()) { - if (!metadataTools.isOwningSide(srcProperty)) - continue; - //noinspection unchecked - Collection srcCollection = (Collection) value; - Collection dstCollection = dest.getValue(name); - if (dstCollection == null) - throw new RuntimeException("Collection is null: " + srcProperty); - boolean equal = srcCollection.size() == dstCollection.size(); - if (equal) { - if (srcProperty.getRange().isOrdered()) { - equal = Arrays.equals(srcCollection.toArray(), dstCollection.toArray()); - } else { - equal = CollectionUtils.isEqualCollection(srcCollection, dstCollection); - } - } - if (!equal) { - dstCollection.clear(); - for (Entity srcRef : srcCollection) { - Entity reloadedRef = findOrCreate(refClass, srcRef.getId()); - dstCollection.add(reloadedRef); - deepCopyIgnoringNulls(srcRef, reloadedRef, visited); - } - } - } else { - Entity srcRef = (Entity) value; - Entity destRef = dest.getValue(name); - if (srcRef.equals(destRef)) { - deepCopyIgnoringNulls(srcRef, destRef, visited); - } else { - Entity reloadedRef = findOrCreate(refClass, srcRef.getId()); - dest.setValue(name, reloadedRef); - deepCopyIgnoringNulls(srcRef, reloadedRef, visited); - } - } - } else if (metadataTools.isEmbedded(srcProperty)) { - Entity srcRef = (Entity) value; - Entity destRef = dest.getValue(name); - if (destRef != null) { - deepCopyIgnoringNulls(srcRef, destRef, visited); - } else { - Entity newRef = (Entity) metadata.create(srcProperty.getRange().asClass().getJavaClass()); - dest.setValue(name, newRef); - deepCopyIgnoringNulls(srcRef, newRef, visited); - } - } else { - dest.setValue(name, value); - } - } - } - - protected T findOrCreate(Class entityClass, Object id) { - Entity reloadedRef = find(entityClass, id); - if (reloadedRef == null) { - reloadedRef = metadata.create(entityClass); - if (reloadedRef instanceof BaseGenericIdEntity) { - ((BaseGenericIdEntity) reloadedRef).setId(id); - } - persist(reloadedRef); - } - //noinspection unchecked - return (T) reloadedRef; - } - - protected T internalMerge(T entity) { - try { - CubaUtil.setSoftDeletion(false); - CubaUtil.setOriginalSoftDeletion(false); - - UUID uuid = null; - if (entity.getId() instanceof IdProxy) { - uuid = ((IdProxy) entity.getId()).getUuid(); - } - - T merged = delegate.merge(entity); - - if (entity.getId() instanceof IdProxy - && uuid != null - && !uuid.equals(((IdProxy) merged.getId()).getUuid())) { - ((IdProxy) merged.getId()).setUuid(uuid); - } - - // copy non-persistent attributes to the resulting merged instance - for (MetaProperty property : metadata.getClassNN(entity.getClass()).getProperties()) { - if (metadata.getTools().isNotPersistent(property) && !property.isReadOnly()) { - // copy using reflection to avoid executing getter/setter code - Field field = FieldUtils.getDeclaredField(entity.getClass(), property.getName(), true); - if (field != null) { - try { - Object value = FieldUtils.readField(field, entity); - if (value != null) { - FieldUtils.writeField(field, merged, value); - } - } catch (IllegalAccessException e) { - throw new RuntimeException("Error copying non-persistent attribute value to merged instance", e); - } - } - } - } - - return merged; - } finally { - CubaUtil.setSoftDeletion(softDeletion); - CubaUtil.setOriginalSoftDeletion(softDeletion); - } - } - - protected Object getRealId(Object id) { - return id instanceof IdProxy ? ((IdProxy) id).getNN() : id; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.google.common.collect.Sets; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.listener.EntityListenerManager; +import com.haulmont.cuba.core.sys.listener.EntityListenerType; +import com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.reflect.FieldUtils; +import org.eclipse.persistence.internal.helper.CubaUtil; +import org.eclipse.persistence.sessions.UnitOfWork; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.persistence.EntityNotFoundException; +import java.lang.reflect.Field; +import java.sql.Connection; +import java.util.*; + +public class EntityManagerImpl implements EntityManager { + + protected javax.persistence.EntityManager delegate; + + protected UserSession userSession; + protected Metadata metadata; + protected EntityListenerManager entityListenerMgr; + protected PersistenceImplSupport support; + + protected boolean softDeletion = true; + + private Logger log = LoggerFactory.getLogger(EntityManagerImpl.class); + + protected EntityManagerImpl(javax.persistence.EntityManager jpaEntityManager, UserSession userSession) { + this.delegate = jpaEntityManager; + this.userSession = userSession; + this.metadata = AppBeans.get(Metadata.NAME); + this.entityListenerMgr = AppBeans.get(EntityListenerManager.NAME); + this.support = AppBeans.get(PersistenceImplSupport.NAME); + } + + @Override + public javax.persistence.EntityManager getDelegate() { + return delegate; + } + + @Override + public boolean isSoftDeletion() { + return softDeletion; + } + + @Override + public void setSoftDeletion(boolean softDeletion) { + this.softDeletion = softDeletion; + CubaUtil.setSoftDeletion(softDeletion); + CubaUtil.setOriginalSoftDeletion(softDeletion); + } + + @Override + public void persist(Entity entity) { + delegate.persist(entity); + support.registerInstance(entity, this); + } + + @Override + public T merge(T entity) { + log.debug("merge {}", entity); + + if (PersistenceHelper.isManaged(entity)) + return entity; + + String storeName = support.getStorageName(delegate.unwrap(UnitOfWork.class)); + entityListenerMgr.fireListener(entity, EntityListenerType.BEFORE_ATTACH, storeName); + + if ((PersistenceHelper.isNew(entity) || !PersistenceHelper.isDetached(entity)) && entity.getId() != null) { + // if a new instance is passed to merge(), we suppose it is persistent but "not detached" + Entity destEntity = findOrCreate(entity.getClass(), entity.getId()); + deepCopyIgnoringNulls(entity, destEntity, Sets.newIdentityHashSet()); + //noinspection unchecked + return (T) destEntity; + } + + T merged = internalMerge(entity); + support.registerInstance(merged, this); + return merged; + } + + @Override + @Deprecated + public T merge(T entity, @Nullable View view) { + T managed = merge(entity); + if (view != null) { + metadata.getTools().traverseAttributesByView(view, managed, (e, p) -> { /* do nothing, just fetch */ }); + } + return managed; + } + + @Override + @Deprecated + public T merge(T entity, @Nullable String viewName) { + if (viewName != null) { + return merge(entity, metadata.getViewRepository().getView(entity.getClass(), viewName)); + } else { + return merge(entity); + } + } + + @Override + public void remove(Entity entity) { + log.debug("remove {}", entity); + + if (PersistenceHelper.isDetached(entity)) { + entity = internalMerge(entity); + } + if (entity instanceof SoftDelete && softDeletion) { + TimeSource timeSource = AppBeans.get(TimeSource.NAME); + ((SoftDelete) entity).setDeleteTs(timeSource.currentTimestamp()); + ((SoftDelete) entity).setDeletedBy(userSession != null ? userSession.getUser().getLogin() : ""); + } else { + delegate.remove(entity); + if (entity instanceof BaseGenericIdEntity) { + BaseEntityInternalAccess.setRemoved((BaseGenericIdEntity) entity, true); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public , K> T find(Class entityClass, K id) { + Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); + Preconditions.checkNotNullArgument(id, "id is null"); + + Object realId = getRealId(id); + log.debug("find {} by id={}", entityClass.getSimpleName(), realId); + MetaClass metaClass = metadata.getExtendedEntities().getEffectiveMetaClass(entityClass); + Class javaClass = metaClass.getJavaClass(); + + T entity = delegate.find(javaClass, realId); + if (entity instanceof SoftDelete && ((SoftDelete) entity).isDeleted() && isSoftDeletion()) + return null; // in case of entity cache + else + return entity; + } + + @Nullable + @Override + public , K> T find(Class entityClass, K id, View... views) { + Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); + Preconditions.checkNotNullArgument(id, "id is null"); + + MetaClass metaClass = metadata.getExtendedEntities().getEffectiveMetaClass(entityClass); + return findWithViews(metaClass, id, Arrays.asList(views)); + } + + @Nullable + @Override + public , K> T find(Class entityClass, K id, String... viewNames) { + View[] viewArray = new View[viewNames.length]; + for (int i = 0; i < viewNames.length; i++) { + viewArray[i] = metadata.getViewRepository().getView(entityClass, viewNames[i]); + } + return find(entityClass, id, viewArray); + } + + protected T findWithViews(MetaClass metaClass, Object id, List views) { + Object realId = getRealId(id); + log.debug("find {} by id={}, views={}", metaClass.getJavaClass().getSimpleName(), realId, views); + + String pkName = metadata.getTools().getPrimaryKeyName(metaClass); + if (pkName == null) + throw new IllegalStateException("Cannot determine PK name for entity " + metaClass); + + Query query = createQuery(String.format("select e from %s e where e.%s = ?1", metaClass.getName(), pkName)); + ((QueryImpl) query).setSingleResultExpected(true); + query.setParameter(1, realId); + for (View view : views) { + query.addView(view); + } + //noinspection unchecked + return (T) query.getFirstResult(); + } + + @SuppressWarnings("unchecked") + @Override + public , K> T getReference(Class clazz, K id) { + Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(clazz); + + T reference = delegate.getReference(effectiveClass, getRealId(id)); + BaseEntityInternalAccess.setNew((BaseGenericIdEntity) reference, false); + return reference; + } + + protected TypedQuery createQueryInstance(boolean isNative, Class resultClass) { + return new QueryImpl<>(this, isNative, resultClass); + } + + @Override + public Query createQuery() { + return createQueryInstance(false, null); + } + + @Override + public Query createQuery(String qlStr) { + Query query = createQueryInstance(false, null); + query.setQueryString(qlStr); + return query; + } + + @Override + public TypedQuery createQuery(String qlString, Class resultClass) { + TypedQuery query = createQueryInstance(false, resultClass); + query.setQueryString(qlString); + return query; + } + + @Override + public Query createNativeQuery() { + return createQueryInstance(true, null); + } + + @Override + public Query createNativeQuery(String sql) { + Query query = createQueryInstance(true, null); + query.setQueryString(sql); + return query; + } + + @Override + public TypedQuery createNativeQuery(String sql, Class resultClass) { + TypedQuery query = createQueryInstance(true, resultClass); + query.setQueryString(sql); + return query; + } + + @Override + @Deprecated + public void fetch(Entity entity, View view) { + } + + @Nullable + @Override + public , K> T reload(Class entityClass, K id, String... viewNames) { + Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); + Preconditions.checkNotNullArgument(id, "id is null"); + + if (id instanceof IdProxy && ((IdProxy) id).get() == null) { + return null; + } + + T entity = find(entityClass, id, viewNames); + return entity; + } + + @SuppressWarnings("unchecked") + @Nullable + @Override + public T reload(T entity, String... viewNames) { + Preconditions.checkNotNullArgument(entity, "entity is null"); + + if (entity.getId() instanceof IdProxy && ((IdProxy) entity.getId()).get() == null) { + return null; + } + + Entity resultEntity = find(entity.getClass(), entity.getId(), viewNames); + return (T) resultEntity; + } + + @Override + public T reloadNN(T entity, String... viewNames) { + T reloaded = reload(entity, viewNames); + if (reloaded == null) + throw new EntityNotFoundException("Entity " + entity + " has been deleted"); + return reloaded; + } + + @Override + public void flush() { + log.debug("flush"); + support.fireEntityListeners(this); + delegate.flush(); + } + + @Override + public Connection getConnection() { + return delegate.unwrap(Connection.class); + } + + /** + * Copies all property values from source to dest excluding null values. + */ + protected void deepCopyIgnoringNulls(Entity source, Entity dest, Set visited) { + if (visited.contains(source)) + return; + visited.add(source); + + MetadataTools metadataTools = metadata.getTools(); + for (MetaProperty srcProperty : source.getMetaClass().getProperties()) { + String name = srcProperty.getName(); + + if (!PersistenceHelper.isLoaded(source, name)) { + continue; + } + + if (srcProperty.isReadOnly()) { + continue; + } + + Object value = source.getValue(name); + if (value == null) { + continue; + } + + if (srcProperty.getRange().isClass() && !metadataTools.isEmbedded(srcProperty)) { + if (!metadataTools.isOwningSide(srcProperty)) + continue; + + Class refClass = srcProperty.getRange().asClass().getJavaClass(); + if (!metadataTools.isPersistent(refClass)) + continue; + + if (srcProperty.getRange().getCardinality().isMany()) { + if (!metadataTools.isOwningSide(srcProperty)) + continue; + //noinspection unchecked + Collection srcCollection = (Collection) value; + Collection dstCollection = dest.getValue(name); + if (dstCollection == null) + throw new RuntimeException("Collection is null: " + srcProperty); + boolean equal = srcCollection.size() == dstCollection.size(); + if (equal) { + if (srcProperty.getRange().isOrdered()) { + equal = Arrays.equals(srcCollection.toArray(), dstCollection.toArray()); + } else { + equal = CollectionUtils.isEqualCollection(srcCollection, dstCollection); + } + } + if (!equal) { + dstCollection.clear(); + for (Entity srcRef : srcCollection) { + Entity reloadedRef = findOrCreate(refClass, srcRef.getId()); + dstCollection.add(reloadedRef); + deepCopyIgnoringNulls(srcRef, reloadedRef, visited); + } + } + } else { + Entity srcRef = (Entity) value; + Entity destRef = dest.getValue(name); + if (srcRef.equals(destRef)) { + deepCopyIgnoringNulls(srcRef, destRef, visited); + } else { + Entity reloadedRef = findOrCreate(refClass, srcRef.getId()); + dest.setValue(name, reloadedRef); + deepCopyIgnoringNulls(srcRef, reloadedRef, visited); + } + } + } else if (metadataTools.isEmbedded(srcProperty)) { + Entity srcRef = (Entity) value; + Entity destRef = dest.getValue(name); + if (destRef != null) { + deepCopyIgnoringNulls(srcRef, destRef, visited); + } else { + Entity newRef = (Entity) metadata.create(srcProperty.getRange().asClass().getJavaClass()); + dest.setValue(name, newRef); + deepCopyIgnoringNulls(srcRef, newRef, visited); + } + } else { + dest.setValue(name, value); + } + } + } + + protected T findOrCreate(Class entityClass, Object id) { + Entity reloadedRef = find(entityClass, id); + if (reloadedRef == null) { + reloadedRef = metadata.create(entityClass); + if (reloadedRef instanceof BaseGenericIdEntity) { + ((BaseGenericIdEntity) reloadedRef).setId(id); + } + persist(reloadedRef); + } + //noinspection unchecked + return (T) reloadedRef; + } + + protected T internalMerge(T entity) { + try { + CubaUtil.setSoftDeletion(false); + CubaUtil.setOriginalSoftDeletion(false); + + UUID uuid = null; + if (entity.getId() instanceof IdProxy) { + uuid = ((IdProxy) entity.getId()).getUuid(); + } + + T merged = delegate.merge(entity); + + if (entity.getId() instanceof IdProxy + && uuid != null + && !uuid.equals(((IdProxy) merged.getId()).getUuid())) { + ((IdProxy) merged.getId()).setUuid(uuid); + } + + // copy non-persistent attributes to the resulting merged instance + for (MetaProperty property : metadata.getClassNN(entity.getClass()).getProperties()) { + if (metadata.getTools().isNotPersistent(property) && !property.isReadOnly()) { + // copy using reflection to avoid executing getter/setter code + Field field = FieldUtils.getDeclaredField(entity.getClass(), property.getName(), true); + if (field != null) { + try { + Object value = FieldUtils.readField(field, entity); + if (value != null) { + FieldUtils.writeField(field, merged, value); + } + } catch (IllegalAccessException e) { + throw new RuntimeException("Error copying non-persistent attribute value to merged instance", e); + } + } + } + } + + return merged; + } finally { + CubaUtil.setSoftDeletion(softDeletion); + CubaUtil.setOriginalSoftDeletion(softDeletion); + } + } + + protected Object getRealId(Object id) { + return id instanceof IdProxy ? ((IdProxy) id).getNN() : id; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/MBeanInterceptor.java b/modules/core/src/com/haulmont/cuba/core/sys/MBeanInterceptor.java index 1942d51177..db6effb64f 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/MBeanInterceptor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/MBeanInterceptor.java @@ -1,46 +1,46 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.aspectj.lang.ProceedingJoinPoint; - -/** - * Intercepts invocations of methods defined in {@code *MBean} interfaces. - *
Sets the thread context classloader to the webapp classloader and logs exceptions. - */ -public class MBeanInterceptor { - - private Logger log = LoggerFactory.getLogger(MBeanInterceptor.class); - - @SuppressWarnings("UnusedDeclaration") - private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - - if (log.isTraceEnabled()) - log.trace("Invoking: " + ctx.getSignature()); - - try { - Object res = ctx.proceed(); - return res; - } catch (Throwable e) { - log.error("MBeanInterceptor caught exception: ", e); - throw e; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.aspectj.lang.ProceedingJoinPoint; + +/** + * Intercepts invocations of methods defined in {@code *MBean} interfaces. + *
Sets the thread context classloader to the webapp classloader and logs exceptions. + */ +public class MBeanInterceptor { + + private Logger log = LoggerFactory.getLogger(MBeanInterceptor.class); + + @SuppressWarnings("UnusedDeclaration") + private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + + if (log.isTraceEnabled()) + log.trace("Invoking: " + ctx.getSignature()); + + try { + Object res = ctx.proceed(); + return res; + } catch (Throwable e) { + log.error("MBeanInterceptor caught exception: ", e); + throw e; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/PerformanceLogInterceptor.java b/modules/core/src/com/haulmont/cuba/core/sys/PerformanceLogInterceptor.java index 52348257e0..812d532a47 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/PerformanceLogInterceptor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/PerformanceLogInterceptor.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; - -public class PerformanceLogInterceptor { - @SuppressWarnings("UnusedDeclaration") - private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { - StopWatch stopWatch = new Log4JStopWatch(ctx.getSignature().toShortString()); - try { - stopWatch.start(); - Object res = ctx.proceed(); - return res; - } finally { - stopWatch.stop(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; + +public class PerformanceLogInterceptor { + @SuppressWarnings("UnusedDeclaration") + private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { + StopWatch stopWatch = new Log4JStopWatch(ctx.getSignature().toShortString()); + try { + stopWatch.start(); + Object res = ctx.proceed(); + return res; + } finally { + stopWatch.stop(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/QueryImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/QueryImpl.java index 450e5ae7bb..d014c9b4e6 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/QueryImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/QueryImpl.java @@ -1,676 +1,676 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.contracts.Id; -import com.haulmont.cuba.core.entity.IdProxy; -import com.haulmont.cuba.core.entity.contracts.Ids; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.entitycache.QueryCacheManager; -import com.haulmont.cuba.core.sys.entitycache.QueryKey; -import com.haulmont.cuba.core.sys.persistence.DbmsFeatures; -import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; -import com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport; -import org.eclipse.persistence.config.CascadePolicy; -import org.eclipse.persistence.config.HintValues; -import org.eclipse.persistence.config.QueryHints; -import org.eclipse.persistence.internal.jpa.EJBQueryImpl; -import org.eclipse.persistence.jpa.JpaQuery; -import org.eclipse.persistence.queries.DatabaseQuery; -import org.eclipse.persistence.queries.ObjectLevelReadQuery; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.persistence.*; -import java.util.*; -import java.util.function.Consumer; - -/** - * Implementation of {@link TypedQuery} interface based on EclipseLink. - */ -public class QueryImpl implements TypedQuery { - - private final Logger log = LoggerFactory.getLogger(QueryImpl.class); - - protected Metadata metadata; - protected javax.persistence.EntityManager emDelegate; - protected JpaQuery query; - protected EntityManagerImpl entityManager; - protected PersistenceImplSupport support; - protected boolean isNative; - protected String queryString; - protected String transformedQueryString; - protected Class resultClass; - protected FetchGroupManager fetchGroupMgr; - protected EntityFetcher entityFetcher; - protected QueryCacheManager queryCacheMgr; - protected QueryTransformerFactory queryTransformerFactory; - protected Set params = new HashSet<>(); - protected LockModeType lockMode; - protected List views = new ArrayList<>(); - protected Integer maxResults; - protected Integer firstResult; - protected boolean singleResultExpected; - protected boolean cacheable; - protected FlushModeType flushMode; - - protected Collection macroHandlers; - - public QueryImpl(EntityManagerImpl entityManager, boolean isNative, @Nullable Class resultClass) { - this.entityManager = entityManager; - this.emDelegate = entityManager.getDelegate(); - this.isNative = isNative; - this.macroHandlers = AppBeans.getAll(QueryMacroHandler.class).values(); - //noinspection unchecked - this.resultClass = resultClass; - - this.metadata = AppBeans.get(Metadata.NAME); - this.fetchGroupMgr = AppBeans.get(FetchGroupManager.NAME); - this.entityFetcher = AppBeans.get(EntityFetcher.NAME); - this.support = AppBeans.get(PersistenceImplSupport.NAME); - this.queryCacheMgr = AppBeans.get(QueryCacheManager.NAME); - this.queryTransformerFactory = AppBeans.get(QueryTransformerFactory.NAME); - } - - protected JpaQuery getQuery() { - if (query == null) { - View view = views.isEmpty() ? null : views.get(0); - - if (isNative) { - log.trace("Creating SQL query: {}", queryString); - if (resultClass == null) - query = (JpaQuery) emDelegate.createNativeQuery(queryString); - else { - if (!Entity.class.isAssignableFrom(resultClass)) { - throw new IllegalArgumentException("Non-entity result class for native query is not supported" + - " by EclipseLink: " + resultClass); - } - Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(resultClass); - query = (JpaQuery) emDelegate.createNativeQuery(queryString, effectiveClass); - } - } else { - log.trace("Creating JPQL query: {}", queryString); - transformedQueryString = transformQueryString(); - log.trace("Transformed JPQL query: {}", transformedQueryString); - - Class effectiveClass = getEffectiveResultClass(); - if (effectiveClass != null) { - query = (JpaQuery) emDelegate.createQuery(transformedQueryString, effectiveClass); - } else { - query = (JpaQuery) emDelegate.createQuery(transformedQueryString); - } - if (view != null) { - MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); - if (!metadata.getTools().isCacheable(metaClass) || !singleResultExpected) { - query.setHint(QueryHints.REFRESH, HintValues.TRUE); - query.setHint(QueryHints.REFRESH_CASCADE, CascadePolicy.CascadeByMapping); - } - } - } - - if (flushMode == null) { - if (view != null && !view.loadPartialEntities()) { - query.setFlushMode(FlushModeType.AUTO); - } else { - query.setFlushMode(FlushModeType.COMMIT); - } - } else { - query.setFlushMode(flushMode); - } - - boolean nullParam = false; - for (Param param : params) { - param.apply(query); - if (param.value == null) - nullParam = true; - } - - addMacroParams(query); - - // disable SQL caching to support "is null" generation - if (nullParam) - query.setHint(QueryHints.PREPARE, HintValues.FALSE); - - // Set maxResults and firstResult only if the query is not by ID, otherwise EclipseLink does not select - // nested collections in some cases - if (maxResults != null && !singleResultExpected) - query.setMaxResults(maxResults); - if (firstResult != null && !singleResultExpected) - query.setFirstResult(firstResult); - - if (lockMode != null) - query.setLockMode(lockMode); - - for (int i = 0; i < views.size(); i++) { - if (i == 0) - fetchGroupMgr.setView(query, queryString, views.get(i), singleResultExpected); - else - fetchGroupMgr.addView(query, queryString, views.get(i), singleResultExpected); - } - } - //noinspection unchecked - return query; - } - - @Nullable - protected Class getEffectiveResultClass() { - if (resultClass == null) { - return null; - } - if (Entity.class.isAssignableFrom(resultClass)) { - return metadata.getExtendedEntities().getEffectiveClass(resultClass); - } - return resultClass; - } - - protected void checkState() { - if (query != null) - throw new IllegalStateException("Query delegate has already been created"); - } - - protected String transformQueryString() { - String result = expandMacros(queryString); - - boolean rebuildParser = false; - QueryParser parser = queryTransformerFactory.parser(result); - - String entityName = parser.getEntityName(); - Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(entityName); - String effectiveEntityName = metadata.getClassNN(effectiveClass).getName(); - if (!effectiveEntityName.equals(entityName)) { - QueryTransformer transformer = queryTransformerFactory.transformer(result); - transformer.replaceEntityName(effectiveEntityName); - result = transformer.getResult(); - rebuildParser = true; - } - - result = replaceParams(result, parser); - - if (rebuildParser) { - parser = queryTransformerFactory.parser(result); - } - String nestedEntityName = parser.getEntityNameIfSecondaryReturnedInsteadOfMain(); - String nestedEntityPath = parser.getEntityPathIfSecondaryReturnedInsteadOfMain(); - if (nestedEntityName != null) { - if (parser.isCollectionSecondaryEntitySelect()) { - throw new IllegalStateException(String.format("Collection attributes are not supported in select clause: %s", nestedEntityPath)); - } - QueryTransformer transformer = queryTransformerFactory.transformer(result); - transformer.replaceWithSelectEntityVariable("tempEntityAlias"); - transformer.addFirstSelectionSource(String.format("%s tempEntityAlias", nestedEntityName)); - transformer.addWhereAsIs(String.format("tempEntityAlias.id = %s.id", nestedEntityPath)); - transformer.addEntityInGroupBy("tempEntityAlias"); - result = transformer.getResult(); - } - - return result; - } - - protected String expandMacros(String queryStr) { - String result = queryStr; - if (macroHandlers != null) { - for (QueryMacroHandler handler : macroHandlers) { - result = handler.expandMacro(result); - } - } - return result; - } - - protected String replaceParams(String query, QueryParser parser) { - String result = query; - Set paramNames = Sets.newHashSet(parser.getParamNames()); - for (Iterator iterator = params.iterator(); iterator.hasNext(); ) { - Param param = iterator.next(); - String paramName = param.name.toString(); - if (param.value instanceof String) { - String strValue = (String) param.value; - if (strValue.startsWith("(?i)")) { - result = replaceCaseInsensitiveParam(result, paramName); - param.value = strValue.substring(4).toLowerCase(); - } - } - if (param.isNamedParam()) { - paramNames.remove(paramName); - if (param.value instanceof Collection) { - Collection collectionValue = (Collection) param.value; - if (collectionValue.isEmpty()) { - result = replaceInCollectionParam(result, paramName); - iterator.remove(); - } - } - if (param.value == null) { - if (parser.isParameterInCondition(paramName)) { - result = replaceInCollectionParam(result, paramName); - iterator.remove(); - } - } - } - } - for (String paramName : paramNames) { - result = replaceInCollectionParam(result, paramName); - } - return result; - } - - protected String replaceCaseInsensitiveParam(String query, String paramName) { - QueryTransformer transformer = queryTransformerFactory.transformer(query); - transformer.handleCaseInsensitiveParam(paramName); - return transformer.getResult(); - } - - protected String replaceInCollectionParam(String query, String paramName) { - QueryTransformer transformer = queryTransformerFactory.transformer(query); - transformer.replaceInCondition(paramName); - return transformer.getResult(); - } - - protected void addMacroParams(javax.persistence.TypedQuery jpaQuery) { - if (macroHandlers != null) { - for (QueryMacroHandler handler : macroHandlers) { - - Map namedParams = new HashMap<>(); - for (Param param : params) { - if (param.name instanceof String) - namedParams.put((String) param.name, param.value); - } - handler.setQueryParams(namedParams); - - for (Map.Entry entry : handler.getParams().entrySet()) { - jpaQuery.setParameter(entry.getKey(), entry.getValue()); - } - } - } - } - - @Override - public List getResultList() { - if (log.isDebugEnabled()) - log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); - - singleResultExpected = false; - - JpaQuery query = getQuery(); - preExecute(query); - @SuppressWarnings("unchecked") - List resultList = (List) getResultFromCache(query, false, obj -> { - ((List) obj).stream().filter(item -> item instanceof Entity).forEach(item -> { - for (View view : views) { - entityFetcher.fetch((Entity) item, view); - } - }); - }); - return resultList; - } - - @Override - public T getSingleResult() { - if (log.isDebugEnabled()) - log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); - - singleResultExpected = true; - - JpaQuery jpaQuery = getQuery(); - preExecute(jpaQuery); - @SuppressWarnings("unchecked") - T result = (T) getResultFromCache(jpaQuery, true, obj -> { - if (obj instanceof Entity) { - for (View view : views) { - entityFetcher.fetch((Entity) obj, view); - } - } - }); - return result; - } - - @Override - @Nullable - public T getFirstResult() { - if (log.isDebugEnabled()) - log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); - - Integer saveMaxResults = maxResults; - maxResults = 1; - try { - JpaQuery query = getQuery(); - preExecute(query); - @SuppressWarnings("unchecked") - List resultList = (List) getResultFromCache(query, false, obj -> { - List list = (List) obj; - if (!list.isEmpty()) { - Object item = list.get(0); - if (item instanceof Entity) { - for (View view : views) { - entityFetcher.fetch((Entity) item, view); - } - } - } - }); - if (resultList.isEmpty()) { - return null; - } else { - return resultList.get(0); - } - } finally { - maxResults = saveMaxResults; - } - } - - @Override - public int executeUpdate() { - JpaQuery jpaQuery = getQuery(); - // In some cache configurations (in particular, when shared cache is on, but for some entities cache is set to ISOLATED), - // EclipseLink does not evict updated entities from cache automatically. - Cache cache = jpaQuery.getEntityManager().getEntityManagerFactory().getCache(); - Class referenceClass = jpaQuery.getDatabaseQuery().getReferenceClass(); - if (referenceClass != null) { - cache.evict(referenceClass); - queryCacheMgr.invalidate(referenceClass, true); - } else { - cache.evictAll(); - queryCacheMgr.invalidateAll(true); - } - preExecute(jpaQuery); - return jpaQuery.executeUpdate(); - } - - @Override - public TypedQuery setMaxResults(int maxResults) { - this.maxResults = maxResults; - if (query != null) - query.setMaxResults(maxResults); - return this; - } - - @Override - public TypedQuery setFirstResult(int firstResult) { - this.firstResult = firstResult; - if (query != null) - query.setFirstResult(firstResult); - return this; - } - - @Override - public TypedQuery setParameter(String name, Object value) { - return setParameter(name, value, true); - } - - @Override - public TypedQuery setParameter(String name, Object value, boolean implicitConversions) { - checkState(); - - if (value instanceof IdProxy) { - value = ((IdProxy) value).get(); - } else if (value instanceof Id) { - value = ((Id) value).getValue(); - } else if (value instanceof Ids) { - value = ((Ids)value).getValues(); - } else if (implicitConversions) { - value = handleImplicitConversions(value); - } - params.add(new Param(name, value)); - return this; - } - - protected Object handleImplicitConversions(Object value) { - if (value instanceof Entity) - value = ((Entity) value).getId(); - else if (value instanceof Collection) { - List list = new ArrayList<>(((Collection) value).size()); - for (Object obj : ((Collection) value)) { - list.add(obj instanceof Entity ? ((Entity) obj).getId() : obj); - } - value = list; - } else if (value instanceof EnumClass) { - value = ((EnumClass) value).getId(); - } - return value; - } - - @Override - public TypedQuery setParameter(String name, Date value, TemporalType temporalType) { - checkState(); - params.add(new Param(name, value, temporalType)); - return this; - } - - @Override - public TypedQuery setParameter(int position, Object value) { - return setParameter(position, value, true); - } - - @Override - public TypedQuery setParameter(int position, Object value, boolean implicitConversions) { - checkState(); - DbmsFeatures dbmsFeatures = DbmsSpecificFactory.getDbmsFeatures(); - if (isNative && (value instanceof UUID) && (dbmsFeatures.getUuidTypeClassName() != null)) { - Class c = ReflectionHelper.getClass(dbmsFeatures.getUuidTypeClassName()); - try { - value = ReflectionHelper.newInstance(c, value); - } catch (NoSuchMethodException e) { - throw new RuntimeException("Error setting parameter value", e); - } - } else if (value instanceof IdProxy) { - value = ((IdProxy) value).get(); - } else if (implicitConversions) { - value = handleImplicitConversions(value); - } - - params.add(new Param(position, value)); - return this; - } - - @Override - public TypedQuery setParameter(int position, Date value, TemporalType temporalType) { - checkState(); - params.add(new Param(position, value, temporalType)); - return this; - } - - @Override - public TypedQuery setLockMode(LockModeType lockMode) { - checkState(); - this.lockMode = lockMode; - return this; - } - - @Override - public TypedQuery setView(View view) { - if (isNative) - throw new UnsupportedOperationException("Views are not supported for native queries"); - checkState(); - views.clear(); - views.add(view); - return this; - } - - @Override - public TypedQuery setViewName(String viewName) { - if (resultClass == null) - throw new IllegalStateException("resultClass is null"); - - setView(metadata.getViewRepository().getView(resultClass, viewName)); - return this; - } - - @Override - public TypedQuery setView(Class entityClass, String viewName) { - setView(metadata.getViewRepository().getView(entityClass, viewName)); - return this; - } - - @Override - public TypedQuery addView(View view) { - if (isNative) - throw new UnsupportedOperationException("Views are not supported for native queries"); - checkState(); - views.add(view); - return this; - } - - @Override - public TypedQuery addViewName(String viewName) { - if (resultClass == null) - throw new IllegalStateException("resultClass is null"); - - addView(metadata.getViewRepository().getView(resultClass, viewName)); - return this; - } - - @Override - public TypedQuery addView(Class entityClass, String viewName) { - addView(metadata.getViewRepository().getView(entityClass, viewName)); - return this; - } - - @Override - public javax.persistence.Query getDelegate() { - return getQuery(); - } - - @Override - public String getQueryString() { - return queryString; - } - - @Override - public TypedQuery setQueryString(String queryString) { - checkState(); - this.queryString = queryString; - return this; - } - - @Override - public TypedQuery setCacheable(boolean cacheable) { - this.cacheable = cacheable; - return this; - } - - @Override - public TypedQuery setFlushMode(FlushModeType flushMode) { - this.flushMode = flushMode; - return this; - } - - public void setSingleResultExpected(boolean singleResultExpected) { - this.singleResultExpected = singleResultExpected; - } - - protected void preExecute(JpaQuery jpaQuery) { - // copying behaviour of org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery() - DatabaseQuery elDbQuery = ((EJBQueryImpl) jpaQuery).getDatabaseQueryInternal(); - boolean isObjectLevelReadQuery = elDbQuery.isObjectLevelReadQuery(); - if (jpaQuery.getFlushMode() == FlushModeType.AUTO - && (!isObjectLevelReadQuery || !((ObjectLevelReadQuery) elDbQuery).isReadOnly())) { - // flush is expected - support.fireEntityListeners(entityManager); - } - } - - protected Object getResultFromCache(JpaQuery jpaQuery, boolean singleResult, Consumer fetcher) { - Preconditions.checkNotNull(fetcher); - boolean useQueryCache = cacheable && !isNative && queryCacheMgr.isEnabled() && lockMode == null; - Object result; - if (useQueryCache) { - QueryParser parser = QueryTransformerFactory.createParser(transformedQueryString); - String entityName = parser.getEntityName(); - useQueryCache = parser.isEntitySelect(entityName); - QueryKey queryKey = null; - if (useQueryCache) { - queryKey = QueryKey.create(transformedQueryString, entityManager.isSoftDeletion(), singleResult, jpaQuery); - result = singleResult ? queryCacheMgr.getSingleResultFromCache(queryKey, views) : - queryCacheMgr.getResultListFromCache(queryKey, views); - if (result != null) { - return result; - } - } - try { - result = singleResult ? jpaQuery.getSingleResult() : jpaQuery.getResultList(); - } catch (NoResultException | NonUniqueResultException ex) { - if (useQueryCache && singleResult) { - queryCacheMgr.putResultToCache(queryKey, null, entityName, parser.getAllEntityNames(), ex); - } - throw ex; - } - fetcher.accept(result); - if (useQueryCache) { - queryCacheMgr.putResultToCache(queryKey, - singleResult ? Collections.singletonList(result) : (List) result, - entityName, parser.getAllEntityNames()); - } - } else { - result = singleResult ? jpaQuery.getSingleResult() : jpaQuery.getResultList(); - fetcher.accept(result); - } - return result; - } - - protected static class Param { - protected Object name; - protected Object value; - protected TemporalType temporalType; - - public Param(Object name, Object value) { - this.name = name; - this.value = value; - } - - public Param(Object name, Date value, TemporalType temporalType) { - this.name = name; - this.value = value; - this.temporalType = temporalType; - } - - public void apply(JpaQuery query) { - if (temporalType != null) { - if (name instanceof Integer) - query.setParameter((int) name, (Date) value, temporalType); - else - query.setParameter((String) name, (Date) value, temporalType); - } else { - if (name instanceof Integer) - query.setParameter((int) name, value); - else - query.setParameter((String) name, value); - } - } - - public boolean isNamedParam() { - return name instanceof String; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Param param = (Param) o; - return name.equals(param.name); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.contracts.Id; +import com.haulmont.cuba.core.entity.IdProxy; +import com.haulmont.cuba.core.entity.contracts.Ids; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.entitycache.QueryCacheManager; +import com.haulmont.cuba.core.sys.entitycache.QueryKey; +import com.haulmont.cuba.core.sys.persistence.DbmsFeatures; +import com.haulmont.cuba.core.sys.persistence.DbmsSpecificFactory; +import com.haulmont.cuba.core.sys.persistence.PersistenceImplSupport; +import org.eclipse.persistence.config.CascadePolicy; +import org.eclipse.persistence.config.HintValues; +import org.eclipse.persistence.config.QueryHints; +import org.eclipse.persistence.internal.jpa.EJBQueryImpl; +import org.eclipse.persistence.jpa.JpaQuery; +import org.eclipse.persistence.queries.DatabaseQuery; +import org.eclipse.persistence.queries.ObjectLevelReadQuery; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.persistence.*; +import java.util.*; +import java.util.function.Consumer; + +/** + * Implementation of {@link TypedQuery} interface based on EclipseLink. + */ +public class QueryImpl implements TypedQuery { + + private final Logger log = LoggerFactory.getLogger(QueryImpl.class); + + protected Metadata metadata; + protected javax.persistence.EntityManager emDelegate; + protected JpaQuery query; + protected EntityManagerImpl entityManager; + protected PersistenceImplSupport support; + protected boolean isNative; + protected String queryString; + protected String transformedQueryString; + protected Class resultClass; + protected FetchGroupManager fetchGroupMgr; + protected EntityFetcher entityFetcher; + protected QueryCacheManager queryCacheMgr; + protected QueryTransformerFactory queryTransformerFactory; + protected Set params = new HashSet<>(); + protected LockModeType lockMode; + protected List views = new ArrayList<>(); + protected Integer maxResults; + protected Integer firstResult; + protected boolean singleResultExpected; + protected boolean cacheable; + protected FlushModeType flushMode; + + protected Collection macroHandlers; + + public QueryImpl(EntityManagerImpl entityManager, boolean isNative, @Nullable Class resultClass) { + this.entityManager = entityManager; + this.emDelegate = entityManager.getDelegate(); + this.isNative = isNative; + this.macroHandlers = AppBeans.getAll(QueryMacroHandler.class).values(); + //noinspection unchecked + this.resultClass = resultClass; + + this.metadata = AppBeans.get(Metadata.NAME); + this.fetchGroupMgr = AppBeans.get(FetchGroupManager.NAME); + this.entityFetcher = AppBeans.get(EntityFetcher.NAME); + this.support = AppBeans.get(PersistenceImplSupport.NAME); + this.queryCacheMgr = AppBeans.get(QueryCacheManager.NAME); + this.queryTransformerFactory = AppBeans.get(QueryTransformerFactory.NAME); + } + + protected JpaQuery getQuery() { + if (query == null) { + View view = views.isEmpty() ? null : views.get(0); + + if (isNative) { + log.trace("Creating SQL query: {}", queryString); + if (resultClass == null) + query = (JpaQuery) emDelegate.createNativeQuery(queryString); + else { + if (!Entity.class.isAssignableFrom(resultClass)) { + throw new IllegalArgumentException("Non-entity result class for native query is not supported" + + " by EclipseLink: " + resultClass); + } + Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(resultClass); + query = (JpaQuery) emDelegate.createNativeQuery(queryString, effectiveClass); + } + } else { + log.trace("Creating JPQL query: {}", queryString); + transformedQueryString = transformQueryString(); + log.trace("Transformed JPQL query: {}", transformedQueryString); + + Class effectiveClass = getEffectiveResultClass(); + if (effectiveClass != null) { + query = (JpaQuery) emDelegate.createQuery(transformedQueryString, effectiveClass); + } else { + query = (JpaQuery) emDelegate.createQuery(transformedQueryString); + } + if (view != null) { + MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); + if (!metadata.getTools().isCacheable(metaClass) || !singleResultExpected) { + query.setHint(QueryHints.REFRESH, HintValues.TRUE); + query.setHint(QueryHints.REFRESH_CASCADE, CascadePolicy.CascadeByMapping); + } + } + } + + if (flushMode == null) { + if (view != null && !view.loadPartialEntities()) { + query.setFlushMode(FlushModeType.AUTO); + } else { + query.setFlushMode(FlushModeType.COMMIT); + } + } else { + query.setFlushMode(flushMode); + } + + boolean nullParam = false; + for (Param param : params) { + param.apply(query); + if (param.value == null) + nullParam = true; + } + + addMacroParams(query); + + // disable SQL caching to support "is null" generation + if (nullParam) + query.setHint(QueryHints.PREPARE, HintValues.FALSE); + + // Set maxResults and firstResult only if the query is not by ID, otherwise EclipseLink does not select + // nested collections in some cases + if (maxResults != null && !singleResultExpected) + query.setMaxResults(maxResults); + if (firstResult != null && !singleResultExpected) + query.setFirstResult(firstResult); + + if (lockMode != null) + query.setLockMode(lockMode); + + for (int i = 0; i < views.size(); i++) { + if (i == 0) + fetchGroupMgr.setView(query, queryString, views.get(i), singleResultExpected); + else + fetchGroupMgr.addView(query, queryString, views.get(i), singleResultExpected); + } + } + //noinspection unchecked + return query; + } + + @Nullable + protected Class getEffectiveResultClass() { + if (resultClass == null) { + return null; + } + if (Entity.class.isAssignableFrom(resultClass)) { + return metadata.getExtendedEntities().getEffectiveClass(resultClass); + } + return resultClass; + } + + protected void checkState() { + if (query != null) + throw new IllegalStateException("Query delegate has already been created"); + } + + protected String transformQueryString() { + String result = expandMacros(queryString); + + boolean rebuildParser = false; + QueryParser parser = queryTransformerFactory.parser(result); + + String entityName = parser.getEntityName(); + Class effectiveClass = metadata.getExtendedEntities().getEffectiveClass(entityName); + String effectiveEntityName = metadata.getClassNN(effectiveClass).getName(); + if (!effectiveEntityName.equals(entityName)) { + QueryTransformer transformer = queryTransformerFactory.transformer(result); + transformer.replaceEntityName(effectiveEntityName); + result = transformer.getResult(); + rebuildParser = true; + } + + result = replaceParams(result, parser); + + if (rebuildParser) { + parser = queryTransformerFactory.parser(result); + } + String nestedEntityName = parser.getEntityNameIfSecondaryReturnedInsteadOfMain(); + String nestedEntityPath = parser.getEntityPathIfSecondaryReturnedInsteadOfMain(); + if (nestedEntityName != null) { + if (parser.isCollectionSecondaryEntitySelect()) { + throw new IllegalStateException(String.format("Collection attributes are not supported in select clause: %s", nestedEntityPath)); + } + QueryTransformer transformer = queryTransformerFactory.transformer(result); + transformer.replaceWithSelectEntityVariable("tempEntityAlias"); + transformer.addFirstSelectionSource(String.format("%s tempEntityAlias", nestedEntityName)); + transformer.addWhereAsIs(String.format("tempEntityAlias.id = %s.id", nestedEntityPath)); + transformer.addEntityInGroupBy("tempEntityAlias"); + result = transformer.getResult(); + } + + return result; + } + + protected String expandMacros(String queryStr) { + String result = queryStr; + if (macroHandlers != null) { + for (QueryMacroHandler handler : macroHandlers) { + result = handler.expandMacro(result); + } + } + return result; + } + + protected String replaceParams(String query, QueryParser parser) { + String result = query; + Set paramNames = Sets.newHashSet(parser.getParamNames()); + for (Iterator iterator = params.iterator(); iterator.hasNext(); ) { + Param param = iterator.next(); + String paramName = param.name.toString(); + if (param.value instanceof String) { + String strValue = (String) param.value; + if (strValue.startsWith("(?i)")) { + result = replaceCaseInsensitiveParam(result, paramName); + param.value = strValue.substring(4).toLowerCase(); + } + } + if (param.isNamedParam()) { + paramNames.remove(paramName); + if (param.value instanceof Collection) { + Collection collectionValue = (Collection) param.value; + if (collectionValue.isEmpty()) { + result = replaceInCollectionParam(result, paramName); + iterator.remove(); + } + } + if (param.value == null) { + if (parser.isParameterInCondition(paramName)) { + result = replaceInCollectionParam(result, paramName); + iterator.remove(); + } + } + } + } + for (String paramName : paramNames) { + result = replaceInCollectionParam(result, paramName); + } + return result; + } + + protected String replaceCaseInsensitiveParam(String query, String paramName) { + QueryTransformer transformer = queryTransformerFactory.transformer(query); + transformer.handleCaseInsensitiveParam(paramName); + return transformer.getResult(); + } + + protected String replaceInCollectionParam(String query, String paramName) { + QueryTransformer transformer = queryTransformerFactory.transformer(query); + transformer.replaceInCondition(paramName); + return transformer.getResult(); + } + + protected void addMacroParams(javax.persistence.TypedQuery jpaQuery) { + if (macroHandlers != null) { + for (QueryMacroHandler handler : macroHandlers) { + + Map namedParams = new HashMap<>(); + for (Param param : params) { + if (param.name instanceof String) + namedParams.put((String) param.name, param.value); + } + handler.setQueryParams(namedParams); + + for (Map.Entry entry : handler.getParams().entrySet()) { + jpaQuery.setParameter(entry.getKey(), entry.getValue()); + } + } + } + } + + @Override + public List getResultList() { + if (log.isDebugEnabled()) + log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); + + singleResultExpected = false; + + JpaQuery query = getQuery(); + preExecute(query); + @SuppressWarnings("unchecked") + List resultList = (List) getResultFromCache(query, false, obj -> { + ((List) obj).stream().filter(item -> item instanceof Entity).forEach(item -> { + for (View view : views) { + entityFetcher.fetch((Entity) item, view); + } + }); + }); + return resultList; + } + + @Override + public T getSingleResult() { + if (log.isDebugEnabled()) + log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); + + singleResultExpected = true; + + JpaQuery jpaQuery = getQuery(); + preExecute(jpaQuery); + @SuppressWarnings("unchecked") + T result = (T) getResultFromCache(jpaQuery, true, obj -> { + if (obj instanceof Entity) { + for (View view : views) { + entityFetcher.fetch((Entity) obj, view); + } + } + }); + return result; + } + + @Override + @Nullable + public T getFirstResult() { + if (log.isDebugEnabled()) + log.debug(queryString.replaceAll("[\\t\\n\\x0B\\f\\r]", " ")); + + Integer saveMaxResults = maxResults; + maxResults = 1; + try { + JpaQuery query = getQuery(); + preExecute(query); + @SuppressWarnings("unchecked") + List resultList = (List) getResultFromCache(query, false, obj -> { + List list = (List) obj; + if (!list.isEmpty()) { + Object item = list.get(0); + if (item instanceof Entity) { + for (View view : views) { + entityFetcher.fetch((Entity) item, view); + } + } + } + }); + if (resultList.isEmpty()) { + return null; + } else { + return resultList.get(0); + } + } finally { + maxResults = saveMaxResults; + } + } + + @Override + public int executeUpdate() { + JpaQuery jpaQuery = getQuery(); + // In some cache configurations (in particular, when shared cache is on, but for some entities cache is set to ISOLATED), + // EclipseLink does not evict updated entities from cache automatically. + Cache cache = jpaQuery.getEntityManager().getEntityManagerFactory().getCache(); + Class referenceClass = jpaQuery.getDatabaseQuery().getReferenceClass(); + if (referenceClass != null) { + cache.evict(referenceClass); + queryCacheMgr.invalidate(referenceClass, true); + } else { + cache.evictAll(); + queryCacheMgr.invalidateAll(true); + } + preExecute(jpaQuery); + return jpaQuery.executeUpdate(); + } + + @Override + public TypedQuery setMaxResults(int maxResults) { + this.maxResults = maxResults; + if (query != null) + query.setMaxResults(maxResults); + return this; + } + + @Override + public TypedQuery setFirstResult(int firstResult) { + this.firstResult = firstResult; + if (query != null) + query.setFirstResult(firstResult); + return this; + } + + @Override + public TypedQuery setParameter(String name, Object value) { + return setParameter(name, value, true); + } + + @Override + public TypedQuery setParameter(String name, Object value, boolean implicitConversions) { + checkState(); + + if (value instanceof IdProxy) { + value = ((IdProxy) value).get(); + } else if (value instanceof Id) { + value = ((Id) value).getValue(); + } else if (value instanceof Ids) { + value = ((Ids)value).getValues(); + } else if (implicitConversions) { + value = handleImplicitConversions(value); + } + params.add(new Param(name, value)); + return this; + } + + protected Object handleImplicitConversions(Object value) { + if (value instanceof Entity) + value = ((Entity) value).getId(); + else if (value instanceof Collection) { + List list = new ArrayList<>(((Collection) value).size()); + for (Object obj : ((Collection) value)) { + list.add(obj instanceof Entity ? ((Entity) obj).getId() : obj); + } + value = list; + } else if (value instanceof EnumClass) { + value = ((EnumClass) value).getId(); + } + return value; + } + + @Override + public TypedQuery setParameter(String name, Date value, TemporalType temporalType) { + checkState(); + params.add(new Param(name, value, temporalType)); + return this; + } + + @Override + public TypedQuery setParameter(int position, Object value) { + return setParameter(position, value, true); + } + + @Override + public TypedQuery setParameter(int position, Object value, boolean implicitConversions) { + checkState(); + DbmsFeatures dbmsFeatures = DbmsSpecificFactory.getDbmsFeatures(); + if (isNative && (value instanceof UUID) && (dbmsFeatures.getUuidTypeClassName() != null)) { + Class c = ReflectionHelper.getClass(dbmsFeatures.getUuidTypeClassName()); + try { + value = ReflectionHelper.newInstance(c, value); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Error setting parameter value", e); + } + } else if (value instanceof IdProxy) { + value = ((IdProxy) value).get(); + } else if (implicitConversions) { + value = handleImplicitConversions(value); + } + + params.add(new Param(position, value)); + return this; + } + + @Override + public TypedQuery setParameter(int position, Date value, TemporalType temporalType) { + checkState(); + params.add(new Param(position, value, temporalType)); + return this; + } + + @Override + public TypedQuery setLockMode(LockModeType lockMode) { + checkState(); + this.lockMode = lockMode; + return this; + } + + @Override + public TypedQuery setView(View view) { + if (isNative) + throw new UnsupportedOperationException("Views are not supported for native queries"); + checkState(); + views.clear(); + views.add(view); + return this; + } + + @Override + public TypedQuery setViewName(String viewName) { + if (resultClass == null) + throw new IllegalStateException("resultClass is null"); + + setView(metadata.getViewRepository().getView(resultClass, viewName)); + return this; + } + + @Override + public TypedQuery setView(Class entityClass, String viewName) { + setView(metadata.getViewRepository().getView(entityClass, viewName)); + return this; + } + + @Override + public TypedQuery addView(View view) { + if (isNative) + throw new UnsupportedOperationException("Views are not supported for native queries"); + checkState(); + views.add(view); + return this; + } + + @Override + public TypedQuery addViewName(String viewName) { + if (resultClass == null) + throw new IllegalStateException("resultClass is null"); + + addView(metadata.getViewRepository().getView(resultClass, viewName)); + return this; + } + + @Override + public TypedQuery addView(Class entityClass, String viewName) { + addView(metadata.getViewRepository().getView(entityClass, viewName)); + return this; + } + + @Override + public javax.persistence.Query getDelegate() { + return getQuery(); + } + + @Override + public String getQueryString() { + return queryString; + } + + @Override + public TypedQuery setQueryString(String queryString) { + checkState(); + this.queryString = queryString; + return this; + } + + @Override + public TypedQuery setCacheable(boolean cacheable) { + this.cacheable = cacheable; + return this; + } + + @Override + public TypedQuery setFlushMode(FlushModeType flushMode) { + this.flushMode = flushMode; + return this; + } + + public void setSingleResultExpected(boolean singleResultExpected) { + this.singleResultExpected = singleResultExpected; + } + + protected void preExecute(JpaQuery jpaQuery) { + // copying behaviour of org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery() + DatabaseQuery elDbQuery = ((EJBQueryImpl) jpaQuery).getDatabaseQueryInternal(); + boolean isObjectLevelReadQuery = elDbQuery.isObjectLevelReadQuery(); + if (jpaQuery.getFlushMode() == FlushModeType.AUTO + && (!isObjectLevelReadQuery || !((ObjectLevelReadQuery) elDbQuery).isReadOnly())) { + // flush is expected + support.fireEntityListeners(entityManager); + } + } + + protected Object getResultFromCache(JpaQuery jpaQuery, boolean singleResult, Consumer fetcher) { + Preconditions.checkNotNull(fetcher); + boolean useQueryCache = cacheable && !isNative && queryCacheMgr.isEnabled() && lockMode == null; + Object result; + if (useQueryCache) { + QueryParser parser = QueryTransformerFactory.createParser(transformedQueryString); + String entityName = parser.getEntityName(); + useQueryCache = parser.isEntitySelect(entityName); + QueryKey queryKey = null; + if (useQueryCache) { + queryKey = QueryKey.create(transformedQueryString, entityManager.isSoftDeletion(), singleResult, jpaQuery); + result = singleResult ? queryCacheMgr.getSingleResultFromCache(queryKey, views) : + queryCacheMgr.getResultListFromCache(queryKey, views); + if (result != null) { + return result; + } + } + try { + result = singleResult ? jpaQuery.getSingleResult() : jpaQuery.getResultList(); + } catch (NoResultException | NonUniqueResultException ex) { + if (useQueryCache && singleResult) { + queryCacheMgr.putResultToCache(queryKey, null, entityName, parser.getAllEntityNames(), ex); + } + throw ex; + } + fetcher.accept(result); + if (useQueryCache) { + queryCacheMgr.putResultToCache(queryKey, + singleResult ? Collections.singletonList(result) : (List) result, + entityName, parser.getAllEntityNames()); + } + } else { + result = singleResult ? jpaQuery.getSingleResult() : jpaQuery.getResultList(); + fetcher.accept(result); + } + return result; + } + + protected static class Param { + protected Object name; + protected Object value; + protected TemporalType temporalType; + + public Param(Object name, Object value) { + this.name = name; + this.value = value; + } + + public Param(Object name, Date value, TemporalType temporalType) { + this.name = name; + this.value = value; + this.temporalType = temporalType; + } + + public void apply(JpaQuery query) { + if (temporalType != null) { + if (name instanceof Integer) + query.setParameter((int) name, (Date) value, temporalType); + else + query.setParameter((String) name, (Date) value, temporalType); + } else { + if (name instanceof Integer) + query.setParameter((int) name, value); + else + query.setParameter((String) name, value); + } + } + + public boolean isNamedParam() { + return name instanceof String; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Param param = (Param) o; + return name.equals(param.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/sys/QueryMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/QueryMacroHandler.java index 00edff57d3..3b2ed2d0f2 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/QueryMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/QueryMacroHandler.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import java.util.Map; - -/** - * Interface to be implemented by JPQL macro handlers. - *

The implementation must be a managed bean with "prototype" scope.

- * - */ -public interface QueryMacroHandler { - - /** - * Replaces macro with real JPQL code. If macro is not found, the source query string is returned. - * - * @param queryString source query string - * @return query string with macros replaced - */ - String expandMacro(String queryString); - - /** - * Sets parameters of the expanded query to the macro handler. - * - * @param namedParameters all named parameters of the expanded query - */ - void setQueryParams(Map namedParameters); - - /** - * @return all named parameters of the expanded query augmented with the macro parameters - */ - Map getParams(); - - /** - * Replaces param names in {@code queryString} with its values from the {@code params} parameter. - * If macro is not found, the source query string is returned. - * - * @return modified query string - */ - String replaceQueryParams(String queryString, Map params); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import java.util.Map; + +/** + * Interface to be implemented by JPQL macro handlers. + *

The implementation must be a managed bean with "prototype" scope.

+ * + */ +public interface QueryMacroHandler { + + /** + * Replaces macro with real JPQL code. If macro is not found, the source query string is returned. + * + * @param queryString source query string + * @return query string with macros replaced + */ + String expandMacro(String queryString); + + /** + * Sets parameters of the expanded query to the macro handler. + * + * @param namedParameters all named parameters of the expanded query + */ + void setQueryParams(Map namedParameters); + + /** + * @return all named parameters of the expanded query augmented with the macro parameters + */ + Map getParams(); + + /** + * Replaces param names in {@code queryString} with its values from the {@code params} parameter. + * If macro is not found, the source query string is returned. + * + * @return modified query string + */ + String replaceQueryParams(String queryString, Map params); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/SecurityTokenManager.java b/modules/core/src/com/haulmont/cuba/core/sys/SecurityTokenManager.java index b605d693e0..87a3dfd45a 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/SecurityTokenManager.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/SecurityTokenManager.java @@ -1,212 +1,212 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.UuidProvider; -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.stereotype.Component; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.*; -import static org.apache.commons.lang.StringUtils.rightPad; -import static org.apache.commons.lang.StringUtils.substring; - -@Component(SecurityTokenManager.NAME) -public class SecurityTokenManager { - public static final String NAME = "cuba_SecurityTokenManager"; - - @Inject - protected ServerConfig config; - @Inject - protected Metadata metadata; - - protected static final String READ_ONLY_ATTRIBUTES_KEY = "__readonlyAttributes"; - protected static final String REQUIRED_ATTRIBUTES_KEY = "__requiredAttributes"; - protected static final String HIDDEN_ATTRIBUTES_KEY = "__hiddenAttributes"; - protected static final Set SYSTEM_ATTRIBUTE_KEYS = Sets.newHashSet(READ_ONLY_ATTRIBUTES_KEY, - REQUIRED_ATTRIBUTES_KEY, HIDDEN_ATTRIBUTES_KEY); - /** - * Encrypt filtered data and write the result to the security token - */ - public void writeSecurityToken(Entity entity) { - SecurityState securityState = getOrCreateSecurityState(entity); - if (securityState != null) { - JSONObject jsonObject = new JSONObject(); - Multimap filtered = getFilteredData(securityState); - if (filtered != null) { - Set>> entries = filtered.asMap().entrySet(); - String[] filteredAttributes = new String[entries.size()]; - int i = 0; - for (Map.Entry> entry : entries) { - MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(entry.getKey()); - if (metadata.getTools().isOwningSide(metaProperty)) { - jsonObject.put(entry.getKey(), entry.getValue()); - } - filteredAttributes[i++] = entry.getKey(); - } - setFilteredAttributes(securityState, filteredAttributes); - } - if (!securityState.getReadonlyAttributes().isEmpty()) { - jsonObject.put(READ_ONLY_ATTRIBUTES_KEY, securityState.getReadonlyAttributes()); - } - if (!securityState.getHiddenAttributes().isEmpty()) { - jsonObject.put(HIDDEN_ATTRIBUTES_KEY, securityState.getHiddenAttributes()); - } - if (!securityState.getRequiredAttributes().isEmpty()) { - jsonObject.put(REQUIRED_ATTRIBUTES_KEY, securityState.getRequiredAttributes()); - } - - String json = jsonObject.toString(); - byte[] encrypted; - Cipher cipher = getCipher(Cipher.ENCRYPT_MODE); - try { - encrypted = cipher.doFinal(json.getBytes(StandardCharsets.UTF_8)); - } catch (Exception e) { - throw new RuntimeException("An error occurred while generating security token", e); - } - setSecurityToken(securityState, encrypted); - } - } - - /** - * Decrypt security token and read filtered data - */ - public void readSecurityToken(Entity entity) { - SecurityState securityState = getSecurityState(entity); - if (getSecurityToken(entity) == null) { - return; - } - Multimap filteredData = ArrayListMultimap.create(); - BaseEntityInternalAccess.setFilteredData(securityState, filteredData); - Cipher cipher = getCipher(Cipher.DECRYPT_MODE); - try { - byte[] decrypted = cipher.doFinal(getSecurityToken(securityState)); - String json = new String(decrypted, StandardCharsets.UTF_8); - JSONObject jsonObject = new JSONObject(json); - for (Object key : jsonObject.keySet()) { - if (!SYSTEM_ATTRIBUTE_KEYS.contains(key)) { - String elementName = String.valueOf(key); - JSONArray jsonArray = jsonObject.getJSONArray(elementName); - MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(elementName); - for (int i = 0; i < jsonArray.length(); i++) { - Object id = jsonArray.get(i); - filteredData.put(elementName, convertId(id, metaProperty)); - } - } - } - if (jsonObject.has(READ_ONLY_ATTRIBUTES_KEY)) { - BaseEntityInternalAccess.setReadonlyAttributes(securityState, parseJsonArrayAsStrings( - jsonObject.getJSONArray(READ_ONLY_ATTRIBUTES_KEY))); - } - if (jsonObject.has(HIDDEN_ATTRIBUTES_KEY)) { - BaseEntityInternalAccess.setHiddenAttributes(securityState, parseJsonArrayAsStrings( - jsonObject.getJSONArray(HIDDEN_ATTRIBUTES_KEY))); - } - if (jsonObject.has(REQUIRED_ATTRIBUTES_KEY)) { - BaseEntityInternalAccess.setRequiredAttributes(securityState, parseJsonArrayAsStrings( - jsonObject.getJSONArray(REQUIRED_ATTRIBUTES_KEY))); - } - } catch (Exception e) { - throw new RuntimeException("An error occurred while reading security token", e); - } - } - - protected Cipher getCipher(int mode) { - try { - Cipher cipher = Cipher.getInstance("AES"); - byte[] encryptionKey = rightPad(substring(config.getKeyForSecurityTokenEncryption(), 0, 16), 16) - .getBytes(StandardCharsets.UTF_8); - - SecretKeySpec sKeySpec = new SecretKeySpec(encryptionKey, "AES"); - cipher.init(mode, sKeySpec); - return cipher; - } catch (Exception e) { - throw new RuntimeException("An error occurred while initiating encryption/decryption", e); - } - } - - protected String[] parseJsonArrayAsStrings(JSONArray array) { - List result = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - result.add(array.getString(i)); - } - return result.toArray(new String[result.size()]); - } - - protected Object convertId(Object value, MetaProperty metaProperty) { - MetaClass metaClass = metaProperty.getRange().asClass(); - if (HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { - return UuidProvider.fromString((String) value); - } - MetaProperty primaryKey = metadata.getTools().getPrimaryKeyProperty(metaClass); - - if (primaryKey != null) { - Class type = primaryKey.getJavaType(); - if (UUID.class.equals(type)) { - return UuidProvider.fromString((String) value); - } else if (Long.class.equals(type) || IdProxy.class.equals(type)) { - return ((Integer) value).longValue(); - } else if (Integer.class.equals(type)) { - return value; - } else if (String.class.equals(type)) { - return value; - } else { - throw new IllegalStateException( - String.format("Unsupported primary key type: %s for %s", type.getSimpleName(), metaClass.getName())); - } - } else { - throw new IllegalStateException( - String.format("Primary key not found for %s", metaClass.getName())); - } - } - - /** - * INTERNAL. - */ - public void addFiltered(BaseGenericIdEntity entity, String property, Object id) { - SecurityState securityState = getOrCreateSecurityState(entity); - if (getFilteredData(securityState) == null) { - setFilteredData(securityState, ArrayListMultimap.create()); - } - getFilteredData(securityState).put(property, id); - } - - /** - * INTERNAL. - */ - public void addFiltered(BaseGenericIdEntity entity, String property, Collection ids) { - SecurityState securityState = getOrCreateSecurityState(entity); - if (getFilteredData(securityState) == null) { - setFilteredData(securityState, ArrayListMultimap.create()); - } - getFilteredData(securityState).putAll(property, ids); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.UuidProvider; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.stereotype.Component; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.inject.Inject; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.*; +import static org.apache.commons.lang.StringUtils.rightPad; +import static org.apache.commons.lang.StringUtils.substring; + +@Component(SecurityTokenManager.NAME) +public class SecurityTokenManager { + public static final String NAME = "cuba_SecurityTokenManager"; + + @Inject + protected ServerConfig config; + @Inject + protected Metadata metadata; + + protected static final String READ_ONLY_ATTRIBUTES_KEY = "__readonlyAttributes"; + protected static final String REQUIRED_ATTRIBUTES_KEY = "__requiredAttributes"; + protected static final String HIDDEN_ATTRIBUTES_KEY = "__hiddenAttributes"; + protected static final Set SYSTEM_ATTRIBUTE_KEYS = Sets.newHashSet(READ_ONLY_ATTRIBUTES_KEY, + REQUIRED_ATTRIBUTES_KEY, HIDDEN_ATTRIBUTES_KEY); + /** + * Encrypt filtered data and write the result to the security token + */ + public void writeSecurityToken(Entity entity) { + SecurityState securityState = getOrCreateSecurityState(entity); + if (securityState != null) { + JSONObject jsonObject = new JSONObject(); + Multimap filtered = getFilteredData(securityState); + if (filtered != null) { + Set>> entries = filtered.asMap().entrySet(); + String[] filteredAttributes = new String[entries.size()]; + int i = 0; + for (Map.Entry> entry : entries) { + MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(entry.getKey()); + if (metadata.getTools().isOwningSide(metaProperty)) { + jsonObject.put(entry.getKey(), entry.getValue()); + } + filteredAttributes[i++] = entry.getKey(); + } + setFilteredAttributes(securityState, filteredAttributes); + } + if (!securityState.getReadonlyAttributes().isEmpty()) { + jsonObject.put(READ_ONLY_ATTRIBUTES_KEY, securityState.getReadonlyAttributes()); + } + if (!securityState.getHiddenAttributes().isEmpty()) { + jsonObject.put(HIDDEN_ATTRIBUTES_KEY, securityState.getHiddenAttributes()); + } + if (!securityState.getRequiredAttributes().isEmpty()) { + jsonObject.put(REQUIRED_ATTRIBUTES_KEY, securityState.getRequiredAttributes()); + } + + String json = jsonObject.toString(); + byte[] encrypted; + Cipher cipher = getCipher(Cipher.ENCRYPT_MODE); + try { + encrypted = cipher.doFinal(json.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException("An error occurred while generating security token", e); + } + setSecurityToken(securityState, encrypted); + } + } + + /** + * Decrypt security token and read filtered data + */ + public void readSecurityToken(Entity entity) { + SecurityState securityState = getSecurityState(entity); + if (getSecurityToken(entity) == null) { + return; + } + Multimap filteredData = ArrayListMultimap.create(); + BaseEntityInternalAccess.setFilteredData(securityState, filteredData); + Cipher cipher = getCipher(Cipher.DECRYPT_MODE); + try { + byte[] decrypted = cipher.doFinal(getSecurityToken(securityState)); + String json = new String(decrypted, StandardCharsets.UTF_8); + JSONObject jsonObject = new JSONObject(json); + for (Object key : jsonObject.keySet()) { + if (!SYSTEM_ATTRIBUTE_KEYS.contains(key)) { + String elementName = String.valueOf(key); + JSONArray jsonArray = jsonObject.getJSONArray(elementName); + MetaProperty metaProperty = entity.getMetaClass().getPropertyNN(elementName); + for (int i = 0; i < jsonArray.length(); i++) { + Object id = jsonArray.get(i); + filteredData.put(elementName, convertId(id, metaProperty)); + } + } + } + if (jsonObject.has(READ_ONLY_ATTRIBUTES_KEY)) { + BaseEntityInternalAccess.setReadonlyAttributes(securityState, parseJsonArrayAsStrings( + jsonObject.getJSONArray(READ_ONLY_ATTRIBUTES_KEY))); + } + if (jsonObject.has(HIDDEN_ATTRIBUTES_KEY)) { + BaseEntityInternalAccess.setHiddenAttributes(securityState, parseJsonArrayAsStrings( + jsonObject.getJSONArray(HIDDEN_ATTRIBUTES_KEY))); + } + if (jsonObject.has(REQUIRED_ATTRIBUTES_KEY)) { + BaseEntityInternalAccess.setRequiredAttributes(securityState, parseJsonArrayAsStrings( + jsonObject.getJSONArray(REQUIRED_ATTRIBUTES_KEY))); + } + } catch (Exception e) { + throw new RuntimeException("An error occurred while reading security token", e); + } + } + + protected Cipher getCipher(int mode) { + try { + Cipher cipher = Cipher.getInstance("AES"); + byte[] encryptionKey = rightPad(substring(config.getKeyForSecurityTokenEncryption(), 0, 16), 16) + .getBytes(StandardCharsets.UTF_8); + + SecretKeySpec sKeySpec = new SecretKeySpec(encryptionKey, "AES"); + cipher.init(mode, sKeySpec); + return cipher; + } catch (Exception e) { + throw new RuntimeException("An error occurred while initiating encryption/decryption", e); + } + } + + protected String[] parseJsonArrayAsStrings(JSONArray array) { + List result = new ArrayList<>(); + for (int i = 0; i < array.length(); i++) { + result.add(array.getString(i)); + } + return result.toArray(new String[result.size()]); + } + + protected Object convertId(Object value, MetaProperty metaProperty) { + MetaClass metaClass = metaProperty.getRange().asClass(); + if (HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { + return UuidProvider.fromString((String) value); + } + MetaProperty primaryKey = metadata.getTools().getPrimaryKeyProperty(metaClass); + + if (primaryKey != null) { + Class type = primaryKey.getJavaType(); + if (UUID.class.equals(type)) { + return UuidProvider.fromString((String) value); + } else if (Long.class.equals(type) || IdProxy.class.equals(type)) { + return ((Integer) value).longValue(); + } else if (Integer.class.equals(type)) { + return value; + } else if (String.class.equals(type)) { + return value; + } else { + throw new IllegalStateException( + String.format("Unsupported primary key type: %s for %s", type.getSimpleName(), metaClass.getName())); + } + } else { + throw new IllegalStateException( + String.format("Primary key not found for %s", metaClass.getName())); + } + } + + /** + * INTERNAL. + */ + public void addFiltered(BaseGenericIdEntity entity, String property, Object id) { + SecurityState securityState = getOrCreateSecurityState(entity); + if (getFilteredData(securityState) == null) { + setFilteredData(securityState, ArrayListMultimap.create()); + } + getFilteredData(securityState).put(property, id); + } + + /** + * INTERNAL. + */ + public void addFiltered(BaseGenericIdEntity entity, String property, Collection ids) { + SecurityState securityState = getOrCreateSecurityState(entity); + if (getFilteredData(securityState) == null) { + setFilteredData(securityState, ArrayListMultimap.create()); + } + getFilteredData(securityState).putAll(property, ids); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/ServiceInterceptor.java b/modules/core/src/com/haulmont/cuba/core/sys/ServiceInterceptor.java index 2907104eb9..6fccb53ea2 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/ServiceInterceptor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/ServiceInterceptor.java @@ -1,301 +1,301 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.app.MiddlewareStatisticsAccumulator; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.global.validation.MethodParametersValidationException; -import com.haulmont.cuba.core.global.validation.MethodResultValidationException; -import com.haulmont.cuba.core.global.validation.ServiceMethodConstraintViolation; -import com.haulmont.cuba.core.global.validation.groups.ServiceParametersChecks; -import com.haulmont.cuba.core.global.validation.groups.ServiceResultChecks; -import com.haulmont.cuba.security.app.UserSessionsAPI; -import com.haulmont.cuba.security.global.NoUserSessionException; -import com.haulmont.cuba.security.global.UserSession; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Nullable; -import javax.validation.ConstraintViolation; -import javax.validation.executable.ExecutableValidator; -import javax.validation.groups.Default; -import java.lang.reflect.Method; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Intercepts invocations of the middleware services. - *
Checks {@link UserSession} validity and wraps exceptions into {@link RemoteException}. - */ -public class ServiceInterceptor { - private final Logger log = LoggerFactory.getLogger(ServiceInterceptor.class); - - private UserSessionsAPI userSessions; - - private Persistence persistence; - - private BeanValidation beanValidation; - - private MiddlewareStatisticsAccumulator statisticsAccumulator; - - boolean logInternalServiceInvocation; - - public void setUserSessions(UserSessionsAPI userSessions) { - this.userSessions = userSessions; - } - - public void setPersistence(Persistence persistence) { - this.persistence = persistence; - } - - public void setBeanValidation(BeanValidation beanValidation) { - this.beanValidation = beanValidation; - } - - public void setStatisticsAccumulator(MiddlewareStatisticsAccumulator statisticsAccumulator) { - this.statisticsAccumulator = statisticsAccumulator; - } - - public void setConfiguration(Configuration configuration) { - logInternalServiceInvocation = configuration.getConfig(ServerConfig.class).getLogInternalServiceInvocation(); - } - - private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { - SecurityContext securityContext = AppContext.getSecurityContextNN(); - boolean internalInvocation = securityContext.incServiceInvocation() > 0; - try { - if (internalInvocation) { - if (logInternalServiceInvocation) { - log.warn("Invoking '{}' from another service", ctx.getSignature()); - } - - ValidateServiceMethodContext validatedContext = getValidateServiceMethodContext(ctx); - validateMethodParameters(ctx, validatedContext); - - Object res = ctx.proceed(); - - validateMethodResult(ctx, validatedContext, res); - - return res; - } else { - statisticsAccumulator.incMiddlewareRequestsCount(); - try { - // Using UserSessionsAPI directly to make sure the session's "last used" timestamp is propagated to the cluster - UserSession userSession = userSessions.get(securityContext.getSessionId(), true); - if (userSession == null) { - throw new NoUserSessionException(securityContext.getSessionId()); - } - - ValidateServiceMethodContext validatedContext = getValidateServiceMethodContext(ctx); - validateMethodParameters(ctx, validatedContext); - - boolean checkTransactionOnExit = Stores.getAdditional().isEmpty() && !persistence.isInTransaction(); - - log.trace("Invoking: {}, session={}", ctx.getSignature(), userSession); - - Object res = ctx.proceed(); - - validateMethodResult(ctx, validatedContext, res); - - if (checkTransactionOnExit && persistence.isInTransaction()) { - log.warn("Open transaction left in {}", ctx.getSignature().toShortString()); - } - - return res; - } catch (Throwable e) { - logException(e, ctx); - // Propagate the special exception to avoid serialization errors on remote clients - throw new RemoteException(e); - } - } - } finally { - securityContext.decServiceInvocation(); - } - } - - @Nullable - protected ValidateServiceMethodContext getValidateServiceMethodContext(ProceedingJoinPoint ctx) { - ValidateServiceMethodContext validatedContext = null; - if (ctx instanceof MethodInvocationProceedingJoinPoint) { - MethodInvocationProceedingJoinPoint methodInvocationCtx = (MethodInvocationProceedingJoinPoint) ctx; - - Method method = ((MethodSignature) ctx.getSignature()).getMethod(); - - Validated validated = getValidated(method, ctx.getSignature().getDeclaringType()); - if (validated != null) { - Object[] args = methodInvocationCtx.getArgs(); - ExecutableValidator validator = beanValidation.getValidator().forExecutables(); - - validatedContext = new ValidateServiceMethodContext(validator, ctx.getThis(), - method, args, validated.value()); - } - } - return validatedContext; - } - - protected void validateMethodParameters(ProceedingJoinPoint ctx, - @Nullable ValidateServiceMethodContext validatedContext) { - if (validatedContext != null) { - log.trace("Validating service call params: {}", ctx.getSignature()); - - ExecutableValidator validator = validatedContext.getValidator(); - - Class[] constraintGroups = validatedContext.getGroups(); - if (constraintGroups.length == 0) { - constraintGroups = new Class[]{Default.class, ServiceParametersChecks.class}; - } - - Set> violations = validator.validateParameters( - validatedContext.getTarget(), - validatedContext.getMethod(), - validatedContext.getArgs(), - constraintGroups); - - if (!violations.isEmpty()) { - Class serviceInterface = ctx.getSignature().getDeclaringType(); - Set> resultViolations = violations.stream() - .map(violation -> new ServiceMethodConstraintViolation(serviceInterface, violation)) - .collect(Collectors.toSet()); - - throw new MethodParametersValidationException("Service method parameters validation failed", resultViolations); - } - } - } - - protected void validateMethodResult(ProceedingJoinPoint ctx, ValidateServiceMethodContext validatedContext, - Object methodResult) { - if (validatedContext != null) { - ExecutableValidator validator = validatedContext.getValidator(); - - log.trace("Validating service call result: {}", ctx.getSignature()); - - Class[] constraintGroups = validatedContext.getGroups(); - if (constraintGroups.length == 0) { - constraintGroups = new Class[]{Default.class, ServiceResultChecks.class}; - } - - Set> violations = validator.validateReturnValue( - validatedContext.getTarget(), - validatedContext.getMethod(), - methodResult, - constraintGroups); - - if (!violations.isEmpty()) { - Class serviceInterface = ctx.getSignature().getDeclaringType(); - Set> paramsViolations = violations.stream() - .map(violation -> new ServiceMethodConstraintViolation(serviceInterface, violation)) - .collect(Collectors.toSet()); - - throw new MethodResultValidationException("Service method result validation failed", paramsViolations); - } - } - } - - protected void logException(Throwable e, ProceedingJoinPoint ctx) { - if (e instanceof NoUserSessionException) { - // If you don't want NoUserSessionException in log, set level higher than INFO for ServiceInterceptor logger - log.info("Exception in {}: {}", ctx.getSignature().toShortString(), e.toString()); - } else if (e instanceof MethodParametersValidationException) { - log.info("MethodParametersValidationException in {}: {}, violations:\n{}", ctx.getSignature().toShortString(), e.toString(), - ((MethodParametersValidationException) e).getConstraintViolations()); - } else if (e instanceof MethodResultValidationException) { - log.error("MethodResultValidationException in {}: {}, violations:\n{}", ctx.getSignature().toShortString(), e.toString(), - ((MethodResultValidationException) e).getConstraintViolations()); - } else { - Logging annotation = e.getClass().getAnnotation(Logging.class); - if (annotation == null || annotation.value() == Logging.Type.FULL) { - log.error("Exception: ", e); - } else if (annotation.value() == Logging.Type.BRIEF) { - log.error("Exception in {}: {}", ctx.getSignature().toShortString(), e.toString()); - } - } - } - - protected Validated getValidated(Method method, Class targetClass) { - Validated validatedAnn = AnnotationUtils.findAnnotation(method, Validated.class); - if (validatedAnn == null) { - validatedAnn = AnnotationUtils.findAnnotation(targetClass, Validated.class); - } - return validatedAnn; - } - - protected static class ValidateServiceMethodContext { - protected ExecutableValidator validator; - protected Object target; - protected Method method; - protected Object[] args; - protected Class[] groups; - - public ValidateServiceMethodContext() { - } - - public ValidateServiceMethodContext(ExecutableValidator validator, Object target, Method method, Object[] args, Class[] groups) { - this.validator = validator; - this.target = target; - this.method = method; - this.args = args; - this.groups = groups; - } - - public ExecutableValidator getValidator() { - return validator; - } - - public void setValidator(ExecutableValidator validator) { - this.validator = validator; - } - - public Object getTarget() { - return target; - } - - public void setTarget(Object target) { - this.target = target; - } - - public Method getMethod() { - return method; - } - - public void setMethod(Method method) { - this.method = method; - } - - public Class[] getGroups() { - return groups; - } - - public void setGroups(Class[] groups) { - this.groups = groups; - } - - public Object[] getArgs() { - return args; - } - - public void setArgs(Object[] args) { - this.args = args; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.app.MiddlewareStatisticsAccumulator; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.global.validation.MethodParametersValidationException; +import com.haulmont.cuba.core.global.validation.MethodResultValidationException; +import com.haulmont.cuba.core.global.validation.ServiceMethodConstraintViolation; +import com.haulmont.cuba.core.global.validation.groups.ServiceParametersChecks; +import com.haulmont.cuba.core.global.validation.groups.ServiceResultChecks; +import com.haulmont.cuba.security.app.UserSessionsAPI; +import com.haulmont.cuba.security.global.NoUserSessionException; +import com.haulmont.cuba.security.global.UserSession; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Nullable; +import javax.validation.ConstraintViolation; +import javax.validation.executable.ExecutableValidator; +import javax.validation.groups.Default; +import java.lang.reflect.Method; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Intercepts invocations of the middleware services. + *
Checks {@link UserSession} validity and wraps exceptions into {@link RemoteException}. + */ +public class ServiceInterceptor { + private final Logger log = LoggerFactory.getLogger(ServiceInterceptor.class); + + private UserSessionsAPI userSessions; + + private Persistence persistence; + + private BeanValidation beanValidation; + + private MiddlewareStatisticsAccumulator statisticsAccumulator; + + boolean logInternalServiceInvocation; + + public void setUserSessions(UserSessionsAPI userSessions) { + this.userSessions = userSessions; + } + + public void setPersistence(Persistence persistence) { + this.persistence = persistence; + } + + public void setBeanValidation(BeanValidation beanValidation) { + this.beanValidation = beanValidation; + } + + public void setStatisticsAccumulator(MiddlewareStatisticsAccumulator statisticsAccumulator) { + this.statisticsAccumulator = statisticsAccumulator; + } + + public void setConfiguration(Configuration configuration) { + logInternalServiceInvocation = configuration.getConfig(ServerConfig.class).getLogInternalServiceInvocation(); + } + + private Object aroundInvoke(ProceedingJoinPoint ctx) throws Throwable { + SecurityContext securityContext = AppContext.getSecurityContextNN(); + boolean internalInvocation = securityContext.incServiceInvocation() > 0; + try { + if (internalInvocation) { + if (logInternalServiceInvocation) { + log.warn("Invoking '{}' from another service", ctx.getSignature()); + } + + ValidateServiceMethodContext validatedContext = getValidateServiceMethodContext(ctx); + validateMethodParameters(ctx, validatedContext); + + Object res = ctx.proceed(); + + validateMethodResult(ctx, validatedContext, res); + + return res; + } else { + statisticsAccumulator.incMiddlewareRequestsCount(); + try { + // Using UserSessionsAPI directly to make sure the session's "last used" timestamp is propagated to the cluster + UserSession userSession = userSessions.get(securityContext.getSessionId(), true); + if (userSession == null) { + throw new NoUserSessionException(securityContext.getSessionId()); + } + + ValidateServiceMethodContext validatedContext = getValidateServiceMethodContext(ctx); + validateMethodParameters(ctx, validatedContext); + + boolean checkTransactionOnExit = Stores.getAdditional().isEmpty() && !persistence.isInTransaction(); + + log.trace("Invoking: {}, session={}", ctx.getSignature(), userSession); + + Object res = ctx.proceed(); + + validateMethodResult(ctx, validatedContext, res); + + if (checkTransactionOnExit && persistence.isInTransaction()) { + log.warn("Open transaction left in {}", ctx.getSignature().toShortString()); + } + + return res; + } catch (Throwable e) { + logException(e, ctx); + // Propagate the special exception to avoid serialization errors on remote clients + throw new RemoteException(e); + } + } + } finally { + securityContext.decServiceInvocation(); + } + } + + @Nullable + protected ValidateServiceMethodContext getValidateServiceMethodContext(ProceedingJoinPoint ctx) { + ValidateServiceMethodContext validatedContext = null; + if (ctx instanceof MethodInvocationProceedingJoinPoint) { + MethodInvocationProceedingJoinPoint methodInvocationCtx = (MethodInvocationProceedingJoinPoint) ctx; + + Method method = ((MethodSignature) ctx.getSignature()).getMethod(); + + Validated validated = getValidated(method, ctx.getSignature().getDeclaringType()); + if (validated != null) { + Object[] args = methodInvocationCtx.getArgs(); + ExecutableValidator validator = beanValidation.getValidator().forExecutables(); + + validatedContext = new ValidateServiceMethodContext(validator, ctx.getThis(), + method, args, validated.value()); + } + } + return validatedContext; + } + + protected void validateMethodParameters(ProceedingJoinPoint ctx, + @Nullable ValidateServiceMethodContext validatedContext) { + if (validatedContext != null) { + log.trace("Validating service call params: {}", ctx.getSignature()); + + ExecutableValidator validator = validatedContext.getValidator(); + + Class[] constraintGroups = validatedContext.getGroups(); + if (constraintGroups.length == 0) { + constraintGroups = new Class[]{Default.class, ServiceParametersChecks.class}; + } + + Set> violations = validator.validateParameters( + validatedContext.getTarget(), + validatedContext.getMethod(), + validatedContext.getArgs(), + constraintGroups); + + if (!violations.isEmpty()) { + Class serviceInterface = ctx.getSignature().getDeclaringType(); + Set> resultViolations = violations.stream() + .map(violation -> new ServiceMethodConstraintViolation(serviceInterface, violation)) + .collect(Collectors.toSet()); + + throw new MethodParametersValidationException("Service method parameters validation failed", resultViolations); + } + } + } + + protected void validateMethodResult(ProceedingJoinPoint ctx, ValidateServiceMethodContext validatedContext, + Object methodResult) { + if (validatedContext != null) { + ExecutableValidator validator = validatedContext.getValidator(); + + log.trace("Validating service call result: {}", ctx.getSignature()); + + Class[] constraintGroups = validatedContext.getGroups(); + if (constraintGroups.length == 0) { + constraintGroups = new Class[]{Default.class, ServiceResultChecks.class}; + } + + Set> violations = validator.validateReturnValue( + validatedContext.getTarget(), + validatedContext.getMethod(), + methodResult, + constraintGroups); + + if (!violations.isEmpty()) { + Class serviceInterface = ctx.getSignature().getDeclaringType(); + Set> paramsViolations = violations.stream() + .map(violation -> new ServiceMethodConstraintViolation(serviceInterface, violation)) + .collect(Collectors.toSet()); + + throw new MethodResultValidationException("Service method result validation failed", paramsViolations); + } + } + } + + protected void logException(Throwable e, ProceedingJoinPoint ctx) { + if (e instanceof NoUserSessionException) { + // If you don't want NoUserSessionException in log, set level higher than INFO for ServiceInterceptor logger + log.info("Exception in {}: {}", ctx.getSignature().toShortString(), e.toString()); + } else if (e instanceof MethodParametersValidationException) { + log.info("MethodParametersValidationException in {}: {}, violations:\n{}", ctx.getSignature().toShortString(), e.toString(), + ((MethodParametersValidationException) e).getConstraintViolations()); + } else if (e instanceof MethodResultValidationException) { + log.error("MethodResultValidationException in {}: {}, violations:\n{}", ctx.getSignature().toShortString(), e.toString(), + ((MethodResultValidationException) e).getConstraintViolations()); + } else { + Logging annotation = e.getClass().getAnnotation(Logging.class); + if (annotation == null || annotation.value() == Logging.Type.FULL) { + log.error("Exception: ", e); + } else if (annotation.value() == Logging.Type.BRIEF) { + log.error("Exception in {}: {}", ctx.getSignature().toShortString(), e.toString()); + } + } + } + + protected Validated getValidated(Method method, Class targetClass) { + Validated validatedAnn = AnnotationUtils.findAnnotation(method, Validated.class); + if (validatedAnn == null) { + validatedAnn = AnnotationUtils.findAnnotation(targetClass, Validated.class); + } + return validatedAnn; + } + + protected static class ValidateServiceMethodContext { + protected ExecutableValidator validator; + protected Object target; + protected Method method; + protected Object[] args; + protected Class[] groups; + + public ValidateServiceMethodContext() { + } + + public ValidateServiceMethodContext(ExecutableValidator validator, Object target, Method method, Object[] args, Class[] groups) { + this.validator = validator; + this.target = target; + this.method = method; + this.args = args; + this.groups = groups; + } + + public ExecutableValidator getValidator() { + return validator; + } + + public void setValidator(ExecutableValidator validator) { + this.validator = validator; + } + + public Object getTarget() { + return target; + } + + public void setTarget(Object target) { + this.target = target; + } + + public Method getMethod() { + return method; + } + + public void setMethod(Method method) { + this.method = method; + } + + public Class[] getGroups() { + return groups; + } + + public void setGroups(Class[] groups) { + this.groups = groups; + } + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/TransactionImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/TransactionImpl.java index f1c2ee20a6..8c6b380819 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/TransactionImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/TransactionImpl.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TransactionParams; -import com.haulmont.cuba.core.global.Stores; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; - -import javax.annotation.Nullable; - -public class TransactionImpl implements Transaction { - - private final PlatformTransactionManager tm; - private final PersistenceImpl persistence; - private final String storeName; - private final DefaultTransactionDefinition td; - private TransactionStatus ts; - private boolean committed; - - public TransactionImpl(PlatformTransactionManager transactionManager, PersistenceImpl persistence, boolean join, - @Nullable TransactionParams params, String storeName) { - this.tm = transactionManager; - this.persistence = persistence; - this.storeName = storeName; - - td = new DefaultTransactionDefinition(); - if (join) - td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); - else - td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); - - if (params != null) { - if (params.getTimeout() != 0) - td.setTimeout(params.getTimeout()); - if (params.isReadOnly()) - td.setReadOnly(true); - } - - ts = tm.getTransaction(td); - - persistence.registerSynchronizations(storeName); - } - - @Override - public T execute(Callable callable) { - return execute(Stores.MAIN, callable); - } - - @Override - public T execute(String storeName, Callable callable) { - try { - T result = callable.call(persistence.getEntityManager(storeName)); - commit(); - return result; - } finally { - end(); - } - } - - @Override - public void execute(Runnable runnable) { - execute(Stores.MAIN, runnable); - } - - @Override - public void execute(String storeName, Runnable runnable) { - try { - runnable.run(persistence.getEntityManager(storeName)); - commit(); - } finally { - end(); - } - } - - @Override - public void commit() { - if (committed) - return; - - tm.commit(ts); - committed = true; - } - - @Override - public void commitRetaining() { - if (committed) - return; - - tm.commit(ts); - - ts = tm.getTransaction(td); - persistence.registerSynchronizations(storeName); - } - - @Override - public void end() { - if (committed) - return; - - if (!ts.isCompleted()) - tm.rollback(ts); - } - - @Override - public void close() { - end(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TransactionParams; +import com.haulmont.cuba.core.global.Stores; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.Nullable; + +public class TransactionImpl implements Transaction { + + private final PlatformTransactionManager tm; + private final PersistenceImpl persistence; + private final String storeName; + private final DefaultTransactionDefinition td; + private TransactionStatus ts; + private boolean committed; + + public TransactionImpl(PlatformTransactionManager transactionManager, PersistenceImpl persistence, boolean join, + @Nullable TransactionParams params, String storeName) { + this.tm = transactionManager; + this.persistence = persistence; + this.storeName = storeName; + + td = new DefaultTransactionDefinition(); + if (join) + td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); + else + td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + + if (params != null) { + if (params.getTimeout() != 0) + td.setTimeout(params.getTimeout()); + if (params.isReadOnly()) + td.setReadOnly(true); + } + + ts = tm.getTransaction(td); + + persistence.registerSynchronizations(storeName); + } + + @Override + public T execute(Callable callable) { + return execute(Stores.MAIN, callable); + } + + @Override + public T execute(String storeName, Callable callable) { + try { + T result = callable.call(persistence.getEntityManager(storeName)); + commit(); + return result; + } finally { + end(); + } + } + + @Override + public void execute(Runnable runnable) { + execute(Stores.MAIN, runnable); + } + + @Override + public void execute(String storeName, Runnable runnable) { + try { + runnable.run(persistence.getEntityManager(storeName)); + commit(); + } finally { + end(); + } + } + + @Override + public void commit() { + if (committed) + return; + + tm.commit(ts); + committed = true; + } + + @Override + public void commitRetaining() { + if (committed) + return; + + tm.commit(ts); + + ts = tm.getTransaction(td); + persistence.registerSynchronizations(storeName); + } + + @Override + public void end() { + if (committed) + return; + + if (!ts.isCompleted()) + tm.rollback(ts); + } + + @Override + public void close() { + end(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/ViewHelper.java b/modules/core/src/com/haulmont/cuba/core/sys/ViewHelper.java index b927d22492..6a8a9c6920 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/ViewHelper.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/ViewHelper.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.core.global.ViewProperty; - -import java.util.Collection; - -public final class ViewHelper { - - private ViewHelper() { - } - - public static View intersectViews(View first, View second) { - if (first == null) - throw new IllegalArgumentException("View is null"); - if (second == null) - throw new IllegalArgumentException("View is null"); - - View resultView = new View(first.getEntityClass()); - - Collection firstProps = first.getProperties(); - - for (ViewProperty firstProperty : firstProps) { - if (second.containsProperty(firstProperty.getName())) { - View resultPropView = null; - ViewProperty secondProperty = second.getProperty(firstProperty.getName()); - if ((firstProperty.getView() != null) && (secondProperty.getView() != null)) { - resultPropView = intersectViews(firstProperty.getView(), secondProperty.getView()); - } - resultView.addProperty(firstProperty.getName(), resultPropView); - } - } - - return resultView; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.core.global.ViewProperty; + +import java.util.Collection; + +public final class ViewHelper { + + private ViewHelper() { + } + + public static View intersectViews(View first, View second) { + if (first == null) + throw new IllegalArgumentException("View is null"); + if (second == null) + throw new IllegalArgumentException("View is null"); + + View resultView = new View(first.getEntityClass()); + + Collection firstProps = first.getProperties(); + + for (ViewProperty firstProperty : firstProps) { + if (second.containsProperty(firstProperty.getName())) { + View resultPropView = null; + ViewProperty secondProperty = second.getProperty(firstProperty.getName()); + if ((firstProperty.getView() != null) && (secondProperty.getView() != null)) { + resultPropView = intersectViews(firstProperty.getView(), secondProperty.getView()); + } + resultView.addProperty(firstProperty.getName(), resultPropView); + } + } + + return resultView; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterImpl.java index 7b0f59999a..fa936c7f78 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterImpl.java @@ -1,128 +1,128 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.dbupdate; - -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.ScriptExecutionPolicy; -import com.haulmont.cuba.core.global.Scripting; -import com.haulmont.cuba.core.sys.DbUpdater; -import com.haulmont.cuba.core.sys.PostUpdateScripts; -import com.haulmont.cuba.core.sys.persistence.DbmsType; -import groovy.lang.Binding; -import groovy.lang.Closure; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import javax.sql.DataSource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Component(DbUpdater.NAME) -public class DbUpdaterImpl extends DbUpdaterEngine { - - @Inject - protected Scripting scripting; - - @Inject - protected Persistence persistence; - - protected PostUpdateScripts postUpdate; - - protected Map postUpdateScripts = new HashMap<>(); - - @Inject - public void setConfigProvider(Configuration configuration) { - String dbDirName = configuration.getConfig(ServerConfig.class).getDbDir(); - if (dbDirName != null) - this.dbScriptsDirectory = dbDirName; - - dbmsType = DbmsType.getType(); - dbmsVersion = DbmsType.getVersion(); - } - - @Override - public DataSource getDataSource() { - return persistence.getDataSource(); - } - - @Override - protected boolean executeGroovyScript(final ScriptResource file) { - Binding bind = new Binding(); - bind.setProperty("ds", getDataSource()); - bind.setProperty("log", LoggerFactory.getLogger(String.format("%s$%s", DbUpdaterEngine.class.getName(), - StringUtils.removeEndIgnoreCase(file.getName(), ".groovy")))); - if (!StringUtils.endsWithIgnoreCase(file.getName(), "." + UPGRADE_GROOVY_EXTENSION)) { - bind.setProperty("postUpdate", new PostUpdateScripts() { - @Override - public void add(Closure closure) { - postUpdateScripts.put(closure, file); - - postUpdate.add(closure); - } - - @Override - public List getUpdates() { - return postUpdate.getUpdates(); - } - }); - } - - try { - scripting.evaluateGroovy(file.getContent(), bind, ScriptExecutionPolicy.DO_NOT_USE_COMPILE_CACHE); - } catch (Exception e) { - throw new RuntimeException(ERROR + "Error executing Groovy script " + file.name + "\n" + e.getMessage(), e); - } - return !postUpdateScripts.containsValue(file); - } - - @Override - protected void doUpdate() { - postUpdate = new PostUpdateScripts(); - - try { - super.doUpdate(); - } catch (RuntimeException e) { - postUpdateScripts.clear(); - throw e; - } - - if (!postUpdate.getUpdates().isEmpty()) { - log.info(String.format("Execute '%s' post update actions", postUpdate.getUpdates().size())); - - for (Closure closure : postUpdate.getUpdates()) { - ScriptResource groovyFile = postUpdateScripts.remove(closure); - if (groovyFile != null) { - log.info("Execute post update from " + getScriptName(groovyFile)); - } - - closure.call(); - - if (groovyFile != null && !postUpdateScripts.containsValue(groovyFile)) { - log.info("All post update actions completed for " + getScriptName(groovyFile)); - - markScript(getScriptName(groovyFile), false); - } - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.dbupdate; + +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.ScriptExecutionPolicy; +import com.haulmont.cuba.core.global.Scripting; +import com.haulmont.cuba.core.sys.DbUpdater; +import com.haulmont.cuba.core.sys.PostUpdateScripts; +import com.haulmont.cuba.core.sys.persistence.DbmsType; +import groovy.lang.Binding; +import groovy.lang.Closure; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component(DbUpdater.NAME) +public class DbUpdaterImpl extends DbUpdaterEngine { + + @Inject + protected Scripting scripting; + + @Inject + protected Persistence persistence; + + protected PostUpdateScripts postUpdate; + + protected Map postUpdateScripts = new HashMap<>(); + + @Inject + public void setConfigProvider(Configuration configuration) { + String dbDirName = configuration.getConfig(ServerConfig.class).getDbDir(); + if (dbDirName != null) + this.dbScriptsDirectory = dbDirName; + + dbmsType = DbmsType.getType(); + dbmsVersion = DbmsType.getVersion(); + } + + @Override + public DataSource getDataSource() { + return persistence.getDataSource(); + } + + @Override + protected boolean executeGroovyScript(final ScriptResource file) { + Binding bind = new Binding(); + bind.setProperty("ds", getDataSource()); + bind.setProperty("log", LoggerFactory.getLogger(String.format("%s$%s", DbUpdaterEngine.class.getName(), + StringUtils.removeEndIgnoreCase(file.getName(), ".groovy")))); + if (!StringUtils.endsWithIgnoreCase(file.getName(), "." + UPGRADE_GROOVY_EXTENSION)) { + bind.setProperty("postUpdate", new PostUpdateScripts() { + @Override + public void add(Closure closure) { + postUpdateScripts.put(closure, file); + + postUpdate.add(closure); + } + + @Override + public List getUpdates() { + return postUpdate.getUpdates(); + } + }); + } + + try { + scripting.evaluateGroovy(file.getContent(), bind, ScriptExecutionPolicy.DO_NOT_USE_COMPILE_CACHE); + } catch (Exception e) { + throw new RuntimeException(ERROR + "Error executing Groovy script " + file.name + "\n" + e.getMessage(), e); + } + return !postUpdateScripts.containsValue(file); + } + + @Override + protected void doUpdate() { + postUpdate = new PostUpdateScripts(); + + try { + super.doUpdate(); + } catch (RuntimeException e) { + postUpdateScripts.clear(); + throw e; + } + + if (!postUpdate.getUpdates().isEmpty()) { + log.info(String.format("Execute '%s' post update actions", postUpdate.getUpdates().size())); + + for (Closure closure : postUpdate.getUpdates()) { + ScriptResource groovyFile = postUpdateScripts.remove(closure); + if (groovyFile != null) { + log.info("Execute post update from " + getScriptName(groovyFile)); + } + + closure.call(); + + if (groovyFile != null && !postUpdateScripts.containsValue(groovyFile)) { + log.info("All post update actions completed for " + getScriptName(groovyFile)); + + markScript(getScriptName(groovyFile), false); + } + } + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerManager.java b/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerManager.java index 160208ab56..c9e911e60e 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerManager.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerManager.java @@ -1,401 +1,401 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.listener; - -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.annotation.Listeners; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.listener.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import org.apache.commons.lang.ClassUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * This bean allows to register and fire entity listeners. - *

Usually entity listeners are registered declaratively with {@code @Listeners} annotation on entity class. - * Methods {@link #addListener(Class, Class)} and {@link #addListener(Class, String)} allow to add listeners dynamically, - * e.g. to an entity from a base project. - * - */ -@Component(EntityListenerManager.NAME) -public class EntityListenerManager { - - public static final String NAME = "cuba_EntityListenerManager"; - - protected static class Key { - private final Class entityClass; - private final EntityListenerType type; - - public Key(Class entityClass, EntityListenerType type) { - this.entityClass = entityClass; - this.type = type; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Key key = (Key) o; - - if (!entityClass.equals(key.entityClass)) return false; - if (type != key.type) return false; - - return true; - } - - @Override - public int hashCode() { - int result; - result = entityClass.hashCode(); - result = 31 * result + type.hashCode(); - return result; - } - } - - protected static class ListenerExecution { - private final Entity entity; - private final EntityListenerType type; - - public ListenerExecution(Entity entity, EntityListenerType type) { - this.entity = entity; - this.type = type; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ListenerExecution that = (ListenerExecution) o; - return entity == that.entity && type == that.type; - } - - @Override - public int hashCode() { - return Objects.hash(entity, type); - } - - @Override - public String toString() { - return type + ": " + entity; - } - } - - private Logger log = LoggerFactory.getLogger(EntityListenerManager.class); - - @Inject - protected Persistence persistence; - - protected Map cache = new ConcurrentHashMap<>(); - - protected Map, Set> dynamicListeners = new ConcurrentHashMap<>(); - - protected ReadWriteLock lock = new ReentrantReadWriteLock(); - - protected volatile boolean enabled = true; - - protected ThreadLocal> threadLocalExecutions = new ThreadLocal<>(); - - /** - * Register an entity listener by its class. The listener instance will be instatiated as a plain object. - * - * @param entityClass entity - * @param listenerClass listener class - */ - public void addListener(Class entityClass, Class listenerClass) { - lock.writeLock().lock(); - try { - Set set = dynamicListeners.get(entityClass); - if (set == null) { - set = new HashSet<>(); - dynamicListeners.put(entityClass, set); - } - set.add(listenerClass.getName()); - - cache.clear(); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Unregister an entity listener. - * - * @param entityClass entity - * @param listenerClass listener class - */ - public void removeListener(Class entityClass, Class listenerClass) { - lock.writeLock().lock(); - try { - Set set = dynamicListeners.get(entityClass); - if (set != null) { - set.remove(listenerClass.getName()); - } - - cache.clear(); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Register an entity listener which is a ManagedBean. - * - * @param entityClass entity - * @param listenerBeanName listener bean name - */ - public void addListener(Class entityClass, String listenerBeanName) { - lock.writeLock().lock(); - try { - Set set = dynamicListeners.get(entityClass); - if (set == null) { - set = new HashSet<>(); - dynamicListeners.put(entityClass, set); - } - set.add(listenerBeanName); - - cache.clear(); - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Unregister an entity listener. - * - * @param entityClass entity - * @param listenerBeanName listener bean name - */ - public void removeListener(Class entityClass, String listenerBeanName) { - lock.writeLock().lock(); - try { - Set set = dynamicListeners.get(entityClass); - if (set != null) { - set.remove(listenerBeanName); - } - - cache.clear(); - } finally { - lock.writeLock().unlock(); - } - } - - @SuppressWarnings("unchecked") - public void fireListener(Entity entity, EntityListenerType type, String storeName) { - if (!enabled) - return; - - List listeners = getListener(entity.getClass(), type); - if (listeners.isEmpty()) - return; - - // check if a listener for this instance is already executed - List executions = threadLocalExecutions.get(); - if (executions == null) { - executions = new ArrayList<>(); - threadLocalExecutions.set(executions); - } - ListenerExecution execution = new ListenerExecution(entity, type); - if (executions.contains(execution)) { - return; - } else { - executions.add(execution); - } - - try { - boolean saved = false; - SecurityContext securityContext = AppContext.getSecurityContext(); - if (securityContext != null) { // can be null before login when detaching entities - saved = securityContext.isAuthorizationRequired(); - securityContext.setAuthorizationRequired(false); - } - try { - for (Object listener : listeners) { - switch (type) { - case BEFORE_DETACH: - logExecution(type, entity); - ((BeforeDetachEntityListener) listener).onBeforeDetach(entity, persistence.getEntityManager(storeName)); - break; - case BEFORE_ATTACH: - logExecution(type, entity); - ((BeforeAttachEntityListener) listener).onBeforeAttach(entity); - break; - case BEFORE_INSERT: - logExecution(type, entity); - ((BeforeInsertEntityListener) listener).onBeforeInsert(entity, persistence.getEntityManager(storeName)); - break; - case AFTER_INSERT: - logExecution(type, entity); - ((AfterInsertEntityListener) listener).onAfterInsert(entity, persistence.getEntityManager(storeName).getConnection()); - break; - case BEFORE_UPDATE: - logExecution(type, entity); - ((BeforeUpdateEntityListener) listener).onBeforeUpdate(entity, persistence.getEntityManager(storeName)); - break; - case AFTER_UPDATE: - logExecution(type, entity); - ((AfterUpdateEntityListener) listener).onAfterUpdate(entity, persistence.getEntityManager(storeName).getConnection()); - break; - case BEFORE_DELETE: - logExecution(type, entity); - ((BeforeDeleteEntityListener) listener).onBeforeDelete(entity, persistence.getEntityManager(storeName)); - break; - case AFTER_DELETE: - logExecution(type, entity); - ((AfterDeleteEntityListener) listener).onAfterDelete(entity, persistence.getEntityManager(storeName).getConnection()); - break; - default: - throw new UnsupportedOperationException("Unsupported EntityListenerType: " + type); - } - } - } finally { - SecurityContext sc = AppContext.getSecurityContext(); - if (sc != null) { - sc.setAuthorizationRequired(saved); - } - } - } finally { - executions.remove(execution); - if (executions.isEmpty()) - threadLocalExecutions.remove(); - } - } - - public void enable(boolean enable) { - this.enabled = enable; - } - - protected void logExecution(EntityListenerType type, Entity entity) { - if (log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder(); - sb.append("Executing ").append(type).append(" entity listener for ") - .append(entity.getClass().getName()).append(" id=").append(entity.getId()); - if (type != EntityListenerType.BEFORE_DETACH && type != EntityListenerType.BEFORE_ATTACH) { - Set dirty = persistence.getTools().getDirtyFields(entity); - if (!dirty.isEmpty()) { - sb.append(", changedProperties: "); - for (Iterator it = dirty.iterator(); it.hasNext(); ) { - String field = it.next(); - sb.append(field); - if (it.hasNext()) - sb.append(","); - } - } - } - log.debug(sb.toString()); - } - } - - protected List getListener(Class entityClass, EntityListenerType type) { - Key key = new Key(entityClass, type); - - lock.readLock().lock(); - try { - if (!cache.containsKey(key)) { - List listeners = findListener(entityClass, type); - cache.put(key, listeners); - return listeners; - } else { - return cache.get(key); - } - } finally { - lock.readLock().unlock(); - } - } - - protected List findListener(Class entityClass, EntityListenerType type) { - log.trace("get listener " + type + " for class " + entityClass.getName()); - List names = getDeclaredListeners(entityClass); - if (names.isEmpty()) { - log.trace("no annotations, exiting"); - return Collections.emptyList(); - } - - List result = new ArrayList<>(); - for (String name : names) { - if (AppBeans.containsBean(name)) { - Object bean = AppBeans.get(name); - log.trace("listener bean found: " + bean); - List interfaces = ClassUtils.getAllInterfaces(bean.getClass()); - for (Class intf : interfaces) { - if (intf.equals(type.getListenerInterface())) { - log.trace("listener implements " + type.getListenerInterface()); - result.add(bean); - } - } - } else { - try { - Class aClass = Thread.currentThread().getContextClassLoader().loadClass(name); - log.trace("listener class found: " + aClass); - List interfaces = ClassUtils.getAllInterfaces(aClass); - for (Class intf : interfaces) { - if (intf.equals(type.getListenerInterface())) { - log.trace("listener implements " + type.getListenerInterface()); - result.add(aClass.newInstance()); - } - } - } catch (ClassNotFoundException e) { - throw new RuntimeException("Unable to create entity listener " + name + " for " + entityClass.getName() - + " because there is no bean or class with such name"); - } catch (IllegalAccessException | InstantiationException e) { - throw new RuntimeException("Unable to instantiate an Entity Listener", e); - } - } - } - return result; - } - - protected List getDeclaredListeners(Class entityClass) { - List listeners = new ArrayList<>(); - - List superclasses = ClassUtils.getAllSuperclasses(entityClass); - Collections.reverse(superclasses); - for (Class superclass : superclasses) { - Set set = dynamicListeners.get(superclass); - if (set != null) { - listeners.addAll(set); - } - - Listeners annotation = (Listeners) superclass.getAnnotation(Listeners.class); - if (annotation != null) { - listeners.addAll(Arrays.asList(annotation.value())); - } - } - - Set set = dynamicListeners.get(entityClass); - if (set != null) { - listeners.addAll(set); - } - - Listeners annotation = entityClass.getAnnotation(Listeners.class); - if (annotation != null) { - listeners.addAll(Arrays.asList(annotation.value())); - } - - return listeners; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.listener; + +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.annotation.Listeners; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.listener.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import org.apache.commons.lang.ClassUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * This bean allows to register and fire entity listeners. + *

Usually entity listeners are registered declaratively with {@code @Listeners} annotation on entity class. + * Methods {@link #addListener(Class, Class)} and {@link #addListener(Class, String)} allow to add listeners dynamically, + * e.g. to an entity from a base project. + * + */ +@Component(EntityListenerManager.NAME) +public class EntityListenerManager { + + public static final String NAME = "cuba_EntityListenerManager"; + + protected static class Key { + private final Class entityClass; + private final EntityListenerType type; + + public Key(Class entityClass, EntityListenerType type) { + this.entityClass = entityClass; + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Key key = (Key) o; + + if (!entityClass.equals(key.entityClass)) return false; + if (type != key.type) return false; + + return true; + } + + @Override + public int hashCode() { + int result; + result = entityClass.hashCode(); + result = 31 * result + type.hashCode(); + return result; + } + } + + protected static class ListenerExecution { + private final Entity entity; + private final EntityListenerType type; + + public ListenerExecution(Entity entity, EntityListenerType type) { + this.entity = entity; + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ListenerExecution that = (ListenerExecution) o; + return entity == that.entity && type == that.type; + } + + @Override + public int hashCode() { + return Objects.hash(entity, type); + } + + @Override + public String toString() { + return type + ": " + entity; + } + } + + private Logger log = LoggerFactory.getLogger(EntityListenerManager.class); + + @Inject + protected Persistence persistence; + + protected Map cache = new ConcurrentHashMap<>(); + + protected Map, Set> dynamicListeners = new ConcurrentHashMap<>(); + + protected ReadWriteLock lock = new ReentrantReadWriteLock(); + + protected volatile boolean enabled = true; + + protected ThreadLocal> threadLocalExecutions = new ThreadLocal<>(); + + /** + * Register an entity listener by its class. The listener instance will be instatiated as a plain object. + * + * @param entityClass entity + * @param listenerClass listener class + */ + public void addListener(Class entityClass, Class listenerClass) { + lock.writeLock().lock(); + try { + Set set = dynamicListeners.get(entityClass); + if (set == null) { + set = new HashSet<>(); + dynamicListeners.put(entityClass, set); + } + set.add(listenerClass.getName()); + + cache.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + /** + * Unregister an entity listener. + * + * @param entityClass entity + * @param listenerClass listener class + */ + public void removeListener(Class entityClass, Class listenerClass) { + lock.writeLock().lock(); + try { + Set set = dynamicListeners.get(entityClass); + if (set != null) { + set.remove(listenerClass.getName()); + } + + cache.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + /** + * Register an entity listener which is a ManagedBean. + * + * @param entityClass entity + * @param listenerBeanName listener bean name + */ + public void addListener(Class entityClass, String listenerBeanName) { + lock.writeLock().lock(); + try { + Set set = dynamicListeners.get(entityClass); + if (set == null) { + set = new HashSet<>(); + dynamicListeners.put(entityClass, set); + } + set.add(listenerBeanName); + + cache.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + /** + * Unregister an entity listener. + * + * @param entityClass entity + * @param listenerBeanName listener bean name + */ + public void removeListener(Class entityClass, String listenerBeanName) { + lock.writeLock().lock(); + try { + Set set = dynamicListeners.get(entityClass); + if (set != null) { + set.remove(listenerBeanName); + } + + cache.clear(); + } finally { + lock.writeLock().unlock(); + } + } + + @SuppressWarnings("unchecked") + public void fireListener(Entity entity, EntityListenerType type, String storeName) { + if (!enabled) + return; + + List listeners = getListener(entity.getClass(), type); + if (listeners.isEmpty()) + return; + + // check if a listener for this instance is already executed + List executions = threadLocalExecutions.get(); + if (executions == null) { + executions = new ArrayList<>(); + threadLocalExecutions.set(executions); + } + ListenerExecution execution = new ListenerExecution(entity, type); + if (executions.contains(execution)) { + return; + } else { + executions.add(execution); + } + + try { + boolean saved = false; + SecurityContext securityContext = AppContext.getSecurityContext(); + if (securityContext != null) { // can be null before login when detaching entities + saved = securityContext.isAuthorizationRequired(); + securityContext.setAuthorizationRequired(false); + } + try { + for (Object listener : listeners) { + switch (type) { + case BEFORE_DETACH: + logExecution(type, entity); + ((BeforeDetachEntityListener) listener).onBeforeDetach(entity, persistence.getEntityManager(storeName)); + break; + case BEFORE_ATTACH: + logExecution(type, entity); + ((BeforeAttachEntityListener) listener).onBeforeAttach(entity); + break; + case BEFORE_INSERT: + logExecution(type, entity); + ((BeforeInsertEntityListener) listener).onBeforeInsert(entity, persistence.getEntityManager(storeName)); + break; + case AFTER_INSERT: + logExecution(type, entity); + ((AfterInsertEntityListener) listener).onAfterInsert(entity, persistence.getEntityManager(storeName).getConnection()); + break; + case BEFORE_UPDATE: + logExecution(type, entity); + ((BeforeUpdateEntityListener) listener).onBeforeUpdate(entity, persistence.getEntityManager(storeName)); + break; + case AFTER_UPDATE: + logExecution(type, entity); + ((AfterUpdateEntityListener) listener).onAfterUpdate(entity, persistence.getEntityManager(storeName).getConnection()); + break; + case BEFORE_DELETE: + logExecution(type, entity); + ((BeforeDeleteEntityListener) listener).onBeforeDelete(entity, persistence.getEntityManager(storeName)); + break; + case AFTER_DELETE: + logExecution(type, entity); + ((AfterDeleteEntityListener) listener).onAfterDelete(entity, persistence.getEntityManager(storeName).getConnection()); + break; + default: + throw new UnsupportedOperationException("Unsupported EntityListenerType: " + type); + } + } + } finally { + SecurityContext sc = AppContext.getSecurityContext(); + if (sc != null) { + sc.setAuthorizationRequired(saved); + } + } + } finally { + executions.remove(execution); + if (executions.isEmpty()) + threadLocalExecutions.remove(); + } + } + + public void enable(boolean enable) { + this.enabled = enable; + } + + protected void logExecution(EntityListenerType type, Entity entity) { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Executing ").append(type).append(" entity listener for ") + .append(entity.getClass().getName()).append(" id=").append(entity.getId()); + if (type != EntityListenerType.BEFORE_DETACH && type != EntityListenerType.BEFORE_ATTACH) { + Set dirty = persistence.getTools().getDirtyFields(entity); + if (!dirty.isEmpty()) { + sb.append(", changedProperties: "); + for (Iterator it = dirty.iterator(); it.hasNext(); ) { + String field = it.next(); + sb.append(field); + if (it.hasNext()) + sb.append(","); + } + } + } + log.debug(sb.toString()); + } + } + + protected List getListener(Class entityClass, EntityListenerType type) { + Key key = new Key(entityClass, type); + + lock.readLock().lock(); + try { + if (!cache.containsKey(key)) { + List listeners = findListener(entityClass, type); + cache.put(key, listeners); + return listeners; + } else { + return cache.get(key); + } + } finally { + lock.readLock().unlock(); + } + } + + protected List findListener(Class entityClass, EntityListenerType type) { + log.trace("get listener " + type + " for class " + entityClass.getName()); + List names = getDeclaredListeners(entityClass); + if (names.isEmpty()) { + log.trace("no annotations, exiting"); + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + for (String name : names) { + if (AppBeans.containsBean(name)) { + Object bean = AppBeans.get(name); + log.trace("listener bean found: " + bean); + List interfaces = ClassUtils.getAllInterfaces(bean.getClass()); + for (Class intf : interfaces) { + if (intf.equals(type.getListenerInterface())) { + log.trace("listener implements " + type.getListenerInterface()); + result.add(bean); + } + } + } else { + try { + Class aClass = Thread.currentThread().getContextClassLoader().loadClass(name); + log.trace("listener class found: " + aClass); + List interfaces = ClassUtils.getAllInterfaces(aClass); + for (Class intf : interfaces) { + if (intf.equals(type.getListenerInterface())) { + log.trace("listener implements " + type.getListenerInterface()); + result.add(aClass.newInstance()); + } + } + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unable to create entity listener " + name + " for " + entityClass.getName() + + " because there is no bean or class with such name"); + } catch (IllegalAccessException | InstantiationException e) { + throw new RuntimeException("Unable to instantiate an Entity Listener", e); + } + } + } + return result; + } + + protected List getDeclaredListeners(Class entityClass) { + List listeners = new ArrayList<>(); + + List superclasses = ClassUtils.getAllSuperclasses(entityClass); + Collections.reverse(superclasses); + for (Class superclass : superclasses) { + Set set = dynamicListeners.get(superclass); + if (set != null) { + listeners.addAll(set); + } + + Listeners annotation = (Listeners) superclass.getAnnotation(Listeners.class); + if (annotation != null) { + listeners.addAll(Arrays.asList(annotation.value())); + } + } + + Set set = dynamicListeners.get(entityClass); + if (set != null) { + listeners.addAll(set); + } + + Listeners annotation = entityClass.getAnnotation(Listeners.class); + if (annotation != null) { + listeners.addAll(Arrays.asList(annotation.value())); + } + + return listeners; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerType.java b/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerType.java index 910d7bc104..e36aae78ce 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerType.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/listener/EntityListenerType.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.listener; - -import com.haulmont.cuba.core.listener.*; - -public enum EntityListenerType { - - BEFORE_DETACH(BeforeDetachEntityListener.class), - BEFORE_ATTACH(BeforeAttachEntityListener.class), - BEFORE_INSERT(BeforeInsertEntityListener.class), - AFTER_INSERT(AfterInsertEntityListener.class), - BEFORE_UPDATE(BeforeUpdateEntityListener.class), - AFTER_UPDATE(AfterUpdateEntityListener.class), - AFTER_DELETE(AfterDeleteEntityListener.class), - BEFORE_DELETE(BeforeDeleteEntityListener.class); - - private final Class listenerInterface; - - private EntityListenerType(Class listenerInterface) { - this.listenerInterface = listenerInterface; - } - - public Class getListenerInterface() { - return listenerInterface; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.listener; + +import com.haulmont.cuba.core.listener.*; + +public enum EntityListenerType { + + BEFORE_DETACH(BeforeDetachEntityListener.class), + BEFORE_ATTACH(BeforeAttachEntityListener.class), + BEFORE_INSERT(BeforeInsertEntityListener.class), + AFTER_INSERT(AfterInsertEntityListener.class), + BEFORE_UPDATE(BeforeUpdateEntityListener.class), + AFTER_UPDATE(AfterUpdateEntityListener.class), + AFTER_DELETE(AfterDeleteEntityListener.class), + BEFORE_DELETE(BeforeDeleteEntityListener.class); + + private final Class listenerInterface; + + private EntityListenerType(Class listenerInterface) { + this.listenerInterface = listenerInterface; + } + + public Class getListenerInterface() { + return listenerInterface; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/mybatis/UUIDTypeHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/mybatis/UUIDTypeHandler.java index fa1f45fc5f..915b939d29 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/mybatis/UUIDTypeHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/mybatis/UUIDTypeHandler.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.mybatis; - -import com.haulmont.cuba.core.global.UuidProvider; -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.TypeHandler; - -import java.sql.*; - -public class UUIDTypeHandler implements TypeHandler { - - @Override - public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { - ps.setObject(i, parameter, Types.OTHER); - } - - @Override - public Object getResult(ResultSet rs, String columnName) throws SQLException { - String val = rs.getString(columnName); - if (val != null) { - return UuidProvider.fromString(val); - } else { - return null; - } - } - - @Override - public Object getResult(ResultSet rs, int columnIndex) throws SQLException { - String val = rs.getString(columnIndex); - if (val != null) { - return UuidProvider.fromString(val); - } else { - return null; - } - } - - @Override - public Object getResult(CallableStatement cs, int columnIndex) throws SQLException { - String val = cs.getString(columnIndex); - if (val != null) { - return UuidProvider.fromString(val); - } else { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.mybatis; + +import com.haulmont.cuba.core.global.UuidProvider; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; + +import java.sql.*; + +public class UUIDTypeHandler implements TypeHandler { + + @Override + public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { + ps.setObject(i, parameter, Types.OTHER); + } + + @Override + public Object getResult(ResultSet rs, String columnName) throws SQLException { + String val = rs.getString(columnName); + if (val != null) { + return UuidProvider.fromString(val); + } else { + return null; + } + } + + @Override + public Object getResult(ResultSet rs, int columnIndex) throws SQLException { + String val = rs.getString(columnIndex); + if (val != null) { + return UuidProvider.fromString(val); + } else { + return null; + } + } + + @Override + public Object getResult(CallableStatement cs, int columnIndex) throws SQLException { + String val = cs.getString(columnIndex); + if (val != null) { + return UuidProvider.fromString(val); + } else { + return null; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/CubaOraclePlatform.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/CubaOraclePlatform.java index def291b367..a5f2929649 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/CubaOraclePlatform.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/CubaOraclePlatform.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import org.eclipse.persistence.exceptions.ConversionException; -import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; - -import java.util.UUID; - -public class CubaOraclePlatform extends Oracle10Platform { - - @Override - public Object convertObject(Object sourceObject, Class javaClass) throws ConversionException { - if (sourceObject instanceof UUID && javaClass == String.class) { - return sourceObject.toString().replace("-", ""); - } - return super.convertObject(sourceObject, javaClass); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import org.eclipse.persistence.exceptions.ConversionException; +import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; + +import java.util.UUID; + +public class CubaOraclePlatform extends Oracle10Platform { + + @Override + public Object convertObject(Object sourceObject, Class javaClass) throws ConversionException { + if (sourceObject instanceof UUID && javaClass == String.class) { + return sourceObject.toString().replace("-", ""); + } + return super.convertObject(sourceObject, javaClass); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/DbTypeConverter.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/DbTypeConverter.java index eab1ee0d40..20a62a5bf0 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/DbTypeConverter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/DbTypeConverter.java @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import java.sql.ResultSet; - -/** - * Interface defining methods to convert data between Java objects and JDBC params and results depending on the current - * DBMS type. - *
The main goal is to convert dates and UUID. - */ -public interface DbTypeConverter { - - /** - * Convert a JDBC ResultSet column value to a value appropriate for an entity attribute. - * - * @param resultSet JDBC ResultSet - * @param column ResultSet column number, starting from 1 - * @return corresponding value for an entity attribute - */ - Object getJavaObject(ResultSet resultSet, int column); - - /** - * Convert an entity attribute value to a value appropriate for a JDBC parameter. - * - * @param value an entity attribute value - * @return corresponding value for a JDBC parameter - */ - Object getSqlObject(Object value); - - /** - * Get a JDBC type corresponding to an entity attribute type. - * - * @param javaClass entity attribute type - * @return corresponding JDBC type - * @see java.sql.Types - */ - int getSqlType(Class javaClass); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import java.sql.ResultSet; + +/** + * Interface defining methods to convert data between Java objects and JDBC params and results depending on the current + * DBMS type. + *
The main goal is to convert dates and UUID. + */ +public interface DbTypeConverter { + + /** + * Convert a JDBC ResultSet column value to a value appropriate for an entity attribute. + * + * @param resultSet JDBC ResultSet + * @param column ResultSet column number, starting from 1 + * @return corresponding value for an entity attribute + */ + Object getJavaObject(ResultSet resultSet, int column); + + /** + * Convert an entity attribute value to a value appropriate for a JDBC parameter. + * + * @param value an entity attribute value + * @return corresponding value for a JDBC parameter + */ + Object getSqlObject(Object value); + + /** + * Get a JDBC type corresponding to an entity attribute type. + * + * @param javaClass entity attribute type + * @return corresponding JDBC type + * @see java.sql.Types + */ + int getSqlType(Class javaClass); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/DeletePolicyProcessor.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/DeletePolicyProcessor.java index 795d8a9666..5ded8389ba 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/DeletePolicyProcessor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/DeletePolicyProcessor.java @@ -1,380 +1,380 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.SoftDelete; -import com.haulmont.cuba.core.entity.annotation.OnDelete; -import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.PersistenceImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.sql.SQLException; -import java.util.*; - -@Component(DeletePolicyProcessor.NAME) -@Scope("prototype") -public class DeletePolicyProcessor { - - public static final String NAME = "cuba_DeletePolicyProcessor"; - - private final Logger log = LoggerFactory.getLogger(DeletePolicyProcessor.class); - - protected Entity entity; - protected MetaClass metaClass; - protected String primaryKeyName; - - protected EntityManager entityManager; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - public Entity getEntity() { - return entity; - } - - public void setEntity(Entity entity) { - this.entity = entity; - this.metaClass = metadata.getSession().getClass(entity.getClass()); - primaryKeyName = metadata.getTools().getPrimaryKeyName(metaClass); - - String storeName = metadata.getTools().getStoreName(metaClass); - entityManager = persistence.getEntityManager(storeName == null ? Stores.MAIN : storeName); - } - - public void process() { - List properties = new ArrayList(); - - fillProperties(properties, OnDeleteInverse.class.getName()); - if (!properties.isEmpty()) - processOnDeleteInverse(properties); - - fillProperties(properties, OnDelete.class.getName()); - if (!properties.isEmpty()) - processOnDelete(properties); - } - - protected void fillProperties(List properties, String annotationName) { - properties.clear(); - MetaProperty[] metaProperties = (MetaProperty[]) metaClass.getAnnotations().get(annotationName); - if (metaProperties != null) - properties.addAll(Arrays.asList(metaProperties)); - for (MetaClass aClass : metaClass.getAncestors()) { - metaProperties = (MetaProperty[]) aClass.getAnnotations().get(annotationName); - if (metaProperties != null) - properties.addAll(Arrays.asList(metaProperties)); - } - } - - protected void processOnDeleteInverse(List properties) { - for (MetaProperty property : properties) { - MetaClass metaClass = property.getDomain(); - - List persistentEntities = new ArrayList<>(); - if (isPersistent(metaClass)) - persistentEntities.add(metaClass); - for (MetaClass descendant : metaClass.getDescendants()) { - if (isPersistent(descendant)) - persistentEntities.add(descendant); - } - - for (MetaClass persistentEntity : persistentEntities) { - OnDeleteInverse annotation = property.getAnnotatedElement().getAnnotation(OnDeleteInverse.class); - DeletePolicy deletePolicy = annotation.value(); - switch (deletePolicy) { - case DENY: - if (referenceExists(persistentEntity.getName(), property)) - throw new DeletePolicyException(this.metaClass.getName(), persistentEntity.getName()); - break; - case CASCADE: - cascade(persistentEntity.getName(), property); - break; - case UNLINK: - unlink(persistentEntity.getName(), property); - break; - } - } - - } - } - - protected void processOnDelete(List properties) { - for (MetaProperty property : properties) { - MetaClass metaClass = property.getRange().asClass(); - OnDelete annotation = property.getAnnotatedElement().getAnnotation(OnDelete.class); - DeletePolicy deletePolicy = annotation.value(); - switch (deletePolicy) { - case DENY: - if (property.getRange().getCardinality().isMany()) { - if (!isCollectionEmpty(property)) - throw new DeletePolicyException(this.metaClass.getName(), metaClass.getName()); - } else { - Object value = getReference(entity, property); - if (value != null) - throw new DeletePolicyException(this.metaClass.getName(), metaClass.getName()); - } - break; - case CASCADE: - if (property.getRange().getCardinality().isMany()) { - Collection value = getCollection(property); - if (value != null && !value.isEmpty()) { - for (Entity e : value) { - entityManager.remove(e); - } - } - } else { - Entity value = getReference(entity, property); - if (value != null && checkIfEntityBelongsToMaster(property, value)) { - if (!(value instanceof SoftDelete)) { - if (PersistenceHelper.isLoaded(entity, property.getName())) { - entity.setValue(property.getName(), null); - entityManager.remove(value); - } else { - hardDeleteNotLoadedReference(entity, property, value); - } - } else { - entityManager.remove(value); - } - } - } - break; - case UNLINK: - if (property.getRange().getCardinality().isMany()) { - throw new UnsupportedOperationException("Unable to unlink nested collection items"); - } else { - setReferenceNull(entity, property); - } - break; - } - } - } - - protected void hardDeleteNotLoadedReference(Entity entity, MetaProperty property, Entity reference) { - List list = persistence.getEntityManagerContext().getAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR); - if (list == null) { - list = new ArrayList<>(); - persistence.getEntityManagerContext().setAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR, list); - } - list.add(() -> { - MetadataTools metadataTools = metadata.getTools(); - QueryRunner queryRunner = new QueryRunner(); - try { - String column = metadataTools.getDatabaseColumn(property); - if (column != null) { // is null for mapped-by property - String updateMasterSql = "update " + metadataTools.getDatabaseTable(metaClass) - + " set " + column + " = null where " - + metadataTools.getPrimaryKeyName(metaClass) + " = ?"; - log.debug("Hard delete unfetched reference: " + updateMasterSql + ", bind: [" + entity.getId() + "]"); - queryRunner.update(entityManager.getConnection(), updateMasterSql, persistence.getDbTypeConverter().getSqlObject(entity.getId())); - } - - MetaClass refMetaClass = property.getRange().asClass(); - String deleteRefSql = "delete from " + metadataTools.getDatabaseTable(refMetaClass) + " where " - + metadataTools.getPrimaryKeyName(refMetaClass) + " = ?"; - log.debug("Hard delete unfetched reference: " + deleteRefSql + ", bind: [" + reference.getId() + "]"); - queryRunner.update(entityManager.getConnection(), deleteRefSql, persistence.getDbTypeConverter().getSqlObject(reference.getId())); - } catch (SQLException e) { - throw new RuntimeException("Error processing deletion of " + entity, e); - } - }); - } - - protected void setReferenceNull(Entity entity, MetaProperty property) { - if (PersistenceHelper.isLoaded(entity, property.getName())) { - entity.setValue(property.getName(), null); - } else { - List list = persistence.getEntityManagerContext().getAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR); - if (list == null) { - list = new ArrayList<>(); - persistence.getEntityManagerContext().setAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR, list); - } - list.add(() -> { - MetadataTools metadataTools = metadata.getTools(); - MetaClass entityMetaClass = metadata.getClassNN(entity.getClass()); - while (!entityMetaClass.equals(property.getDomain())) { - MetaClass ancestor = entityMetaClass.getAncestor(); - if (ancestor == null) - throw new IllegalStateException("Cannot determine a persistent entity for property " + property); - if (metadataTools.isPersistent(ancestor)) { - entityMetaClass = ancestor; - } else { - break; - } - } - String sql = "update " + metadataTools.getDatabaseTable(entityMetaClass) - + " set " + metadataTools.getDatabaseColumn(property) + " = null where " - + metadataTools.getPrimaryKeyName(entityMetaClass) + " = ?"; - QueryRunner queryRunner = new QueryRunner(); - try { - log.debug("Set reference to null: " + sql + ", bind: [" + entity.getId() + "]"); - queryRunner.update(entityManager.getConnection(), sql, persistence.getDbTypeConverter().getSqlObject(entity.getId())); - } catch (SQLException e) { - throw new RuntimeException("Error processing deletion of " + entity, e); - } - }); - } - } - - protected Entity getReference(Entity entity, MetaProperty property) { - if (PersistenceHelper.isLoaded(entity, property.getName())) - return entity.getValue(property.getName()); - else { - Query query = entityManager.createQuery( - "select e." + property.getName() + " from " + entity.getMetaClass().getName() + " e where e." + primaryKeyName + " = ?1"); - query.setParameter(1, entity.getId()); - Object refEntity = query.getFirstResult(); - return (Entity) refEntity; - } - } - - protected boolean checkIfEntityBelongsToMaster(MetaProperty property, Entity entityToRemove) { - MetaProperty inverseProperty = property.getInverse(); - if (inverseProperty != null && !inverseProperty.getRange().getCardinality().isMany()) { - Entity master = entityToRemove.getValue(inverseProperty.getName()); - return entity.equals(master); - } else { - return true; - } - } - - protected boolean isCollectionEmpty(MetaProperty property) { - MetaProperty inverseProperty = property.getInverse(); - if (inverseProperty == null) { - log.warn("Inverse property not found for property " + property); - Collection value = entity.getValue(property.getName()); - return value == null || value.isEmpty(); - } - - String invPropName = inverseProperty.getName(); - String collectionPkName = metadata.getTools().getPrimaryKeyName(property.getRange().asClass()); - - String qlStr = "select e." + collectionPkName + " from " + property.getRange().asClass().getName() + - " e where e." + invPropName + "." + primaryKeyName + " = ?1"; - - Query query = entityManager.createQuery(qlStr); - query.setParameter(1, entity.getId()); - query.setMaxResults(1); - List list = query.getResultList(); - - return list.isEmpty(); - } - - protected Collection getCollection(MetaProperty property) { - MetaProperty inverseProperty = property.getInverse(); - if (inverseProperty == null) { - log.warn("Inverse property not found for property " + property); - Collection value = entity.getValue(property.getName()); - return value == null ? Collections.EMPTY_LIST : value; - } - - String invPropName = inverseProperty.getName(); - String qlStr = "select e from " + property.getRange().asClass().getName() + " e where e." + invPropName + "." + - primaryKeyName + " = ?1"; - - Query query = entityManager.createQuery(qlStr); - query.setParameter(1, entity.getId()); - List list = query.getResultList(); - - // If the property is not loaded, it means it was not modified and further check is not needed - if (!PersistenceHelper.isLoaded(entity, property.getName())) { - return list; - } - // Check whether the collection items still belong to the master entity, because they could be changed in the - // current transaction that did not affect the database yet - List result = new ArrayList<>(list.size()); - for (Entity item : list) { - Entity master = item.getValue(invPropName); - if (entity.equals(master)) - result.add(item); - } - return result; - } - - protected boolean referenceExists(String entityName, MetaProperty property) { - String template = property.getRange().getCardinality().isMany() ? - "select count(e) from %s e join e.%s c where c." + primaryKeyName + "= ?1" : - "select count(e) from %s e where e.%s." + primaryKeyName + " = ?1"; - String qstr = String.format(template, entityName, property.getName()); - Query query = entityManager.createQuery(qstr); - query.setParameter(1, entity.getId()); - query.setMaxResults(1); - Long count = (Long) query.getSingleResult(); - return count > 0; - } - - protected boolean isPersistent(MetaClass metaClass) { - return metaClass.getJavaClass().isAnnotationPresent(javax.persistence.Entity.class); - } - - protected void cascade(String entityName, MetaProperty property) { - String template = property.getRange().getCardinality().isMany() ? - "select e from %s e join e.%s c where c." + primaryKeyName + " = ?1" : - "select e from %s e where e.%s." + primaryKeyName + " = ?1"; - String qstr = String.format(template, entityName, property.getName()); - Query query = entityManager.createQuery(qstr); - query.setParameter(1, entity.getId()); - List list = query.getResultList(); - for (Entity e : list) { - entityManager.remove(e); - } - } - - protected void unlink(String entityName, MetaProperty property) { - if (metadata.getTools().isOwningSide(property)) { - String template = property.getRange().getCardinality().isMany() ? - "select e from %s e join e.%s c where c." + primaryKeyName + " = ?1" : - "select e from %s e where e.%s." + primaryKeyName + " = ?1"; - String qstr = String.format(template, entityName, property.getName()); - Query query = entityManager.createQuery(qstr); - query.setParameter(1, entity.getId()); - List list = query.getResultList(); - for (Entity e : list) { - if (property.getRange().getCardinality().isMany()) { - Collection collection = e.getValue(property.getName()); - if (collection != null) { - for (Iterator it = collection.iterator(); it.hasNext(); ) { - if (entity.equals(it.next())) { - it.remove(); - } - } - } - } else { - setReferenceNull(e, property); - } - } - } else { - MetaProperty inverseProp = property.getInverse(); - if (inverseProp != null && inverseProp.getDomain().equals(metaClass)) { - setReferenceNull(entity, inverseProp); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.SoftDelete; +import com.haulmont.cuba.core.entity.annotation.OnDelete; +import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.PersistenceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.sql.SQLException; +import java.util.*; + +@Component(DeletePolicyProcessor.NAME) +@Scope("prototype") +public class DeletePolicyProcessor { + + public static final String NAME = "cuba_DeletePolicyProcessor"; + + private final Logger log = LoggerFactory.getLogger(DeletePolicyProcessor.class); + + protected Entity entity; + protected MetaClass metaClass; + protected String primaryKeyName; + + protected EntityManager entityManager; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + this.metaClass = metadata.getSession().getClass(entity.getClass()); + primaryKeyName = metadata.getTools().getPrimaryKeyName(metaClass); + + String storeName = metadata.getTools().getStoreName(metaClass); + entityManager = persistence.getEntityManager(storeName == null ? Stores.MAIN : storeName); + } + + public void process() { + List properties = new ArrayList(); + + fillProperties(properties, OnDeleteInverse.class.getName()); + if (!properties.isEmpty()) + processOnDeleteInverse(properties); + + fillProperties(properties, OnDelete.class.getName()); + if (!properties.isEmpty()) + processOnDelete(properties); + } + + protected void fillProperties(List properties, String annotationName) { + properties.clear(); + MetaProperty[] metaProperties = (MetaProperty[]) metaClass.getAnnotations().get(annotationName); + if (metaProperties != null) + properties.addAll(Arrays.asList(metaProperties)); + for (MetaClass aClass : metaClass.getAncestors()) { + metaProperties = (MetaProperty[]) aClass.getAnnotations().get(annotationName); + if (metaProperties != null) + properties.addAll(Arrays.asList(metaProperties)); + } + } + + protected void processOnDeleteInverse(List properties) { + for (MetaProperty property : properties) { + MetaClass metaClass = property.getDomain(); + + List persistentEntities = new ArrayList<>(); + if (isPersistent(metaClass)) + persistentEntities.add(metaClass); + for (MetaClass descendant : metaClass.getDescendants()) { + if (isPersistent(descendant)) + persistentEntities.add(descendant); + } + + for (MetaClass persistentEntity : persistentEntities) { + OnDeleteInverse annotation = property.getAnnotatedElement().getAnnotation(OnDeleteInverse.class); + DeletePolicy deletePolicy = annotation.value(); + switch (deletePolicy) { + case DENY: + if (referenceExists(persistentEntity.getName(), property)) + throw new DeletePolicyException(this.metaClass.getName(), persistentEntity.getName()); + break; + case CASCADE: + cascade(persistentEntity.getName(), property); + break; + case UNLINK: + unlink(persistentEntity.getName(), property); + break; + } + } + + } + } + + protected void processOnDelete(List properties) { + for (MetaProperty property : properties) { + MetaClass metaClass = property.getRange().asClass(); + OnDelete annotation = property.getAnnotatedElement().getAnnotation(OnDelete.class); + DeletePolicy deletePolicy = annotation.value(); + switch (deletePolicy) { + case DENY: + if (property.getRange().getCardinality().isMany()) { + if (!isCollectionEmpty(property)) + throw new DeletePolicyException(this.metaClass.getName(), metaClass.getName()); + } else { + Object value = getReference(entity, property); + if (value != null) + throw new DeletePolicyException(this.metaClass.getName(), metaClass.getName()); + } + break; + case CASCADE: + if (property.getRange().getCardinality().isMany()) { + Collection value = getCollection(property); + if (value != null && !value.isEmpty()) { + for (Entity e : value) { + entityManager.remove(e); + } + } + } else { + Entity value = getReference(entity, property); + if (value != null && checkIfEntityBelongsToMaster(property, value)) { + if (!(value instanceof SoftDelete)) { + if (PersistenceHelper.isLoaded(entity, property.getName())) { + entity.setValue(property.getName(), null); + entityManager.remove(value); + } else { + hardDeleteNotLoadedReference(entity, property, value); + } + } else { + entityManager.remove(value); + } + } + } + break; + case UNLINK: + if (property.getRange().getCardinality().isMany()) { + throw new UnsupportedOperationException("Unable to unlink nested collection items"); + } else { + setReferenceNull(entity, property); + } + break; + } + } + } + + protected void hardDeleteNotLoadedReference(Entity entity, MetaProperty property, Entity reference) { + List list = persistence.getEntityManagerContext().getAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR); + if (list == null) { + list = new ArrayList<>(); + persistence.getEntityManagerContext().setAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR, list); + } + list.add(() -> { + MetadataTools metadataTools = metadata.getTools(); + QueryRunner queryRunner = new QueryRunner(); + try { + String column = metadataTools.getDatabaseColumn(property); + if (column != null) { // is null for mapped-by property + String updateMasterSql = "update " + metadataTools.getDatabaseTable(metaClass) + + " set " + column + " = null where " + + metadataTools.getPrimaryKeyName(metaClass) + " = ?"; + log.debug("Hard delete unfetched reference: " + updateMasterSql + ", bind: [" + entity.getId() + "]"); + queryRunner.update(entityManager.getConnection(), updateMasterSql, persistence.getDbTypeConverter().getSqlObject(entity.getId())); + } + + MetaClass refMetaClass = property.getRange().asClass(); + String deleteRefSql = "delete from " + metadataTools.getDatabaseTable(refMetaClass) + " where " + + metadataTools.getPrimaryKeyName(refMetaClass) + " = ?"; + log.debug("Hard delete unfetched reference: " + deleteRefSql + ", bind: [" + reference.getId() + "]"); + queryRunner.update(entityManager.getConnection(), deleteRefSql, persistence.getDbTypeConverter().getSqlObject(reference.getId())); + } catch (SQLException e) { + throw new RuntimeException("Error processing deletion of " + entity, e); + } + }); + } + + protected void setReferenceNull(Entity entity, MetaProperty property) { + if (PersistenceHelper.isLoaded(entity, property.getName())) { + entity.setValue(property.getName(), null); + } else { + List list = persistence.getEntityManagerContext().getAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR); + if (list == null) { + list = new ArrayList<>(); + persistence.getEntityManagerContext().setAttribute(PersistenceImpl.RUN_BEFORE_COMMIT_ATTR, list); + } + list.add(() -> { + MetadataTools metadataTools = metadata.getTools(); + MetaClass entityMetaClass = metadata.getClassNN(entity.getClass()); + while (!entityMetaClass.equals(property.getDomain())) { + MetaClass ancestor = entityMetaClass.getAncestor(); + if (ancestor == null) + throw new IllegalStateException("Cannot determine a persistent entity for property " + property); + if (metadataTools.isPersistent(ancestor)) { + entityMetaClass = ancestor; + } else { + break; + } + } + String sql = "update " + metadataTools.getDatabaseTable(entityMetaClass) + + " set " + metadataTools.getDatabaseColumn(property) + " = null where " + + metadataTools.getPrimaryKeyName(entityMetaClass) + " = ?"; + QueryRunner queryRunner = new QueryRunner(); + try { + log.debug("Set reference to null: " + sql + ", bind: [" + entity.getId() + "]"); + queryRunner.update(entityManager.getConnection(), sql, persistence.getDbTypeConverter().getSqlObject(entity.getId())); + } catch (SQLException e) { + throw new RuntimeException("Error processing deletion of " + entity, e); + } + }); + } + } + + protected Entity getReference(Entity entity, MetaProperty property) { + if (PersistenceHelper.isLoaded(entity, property.getName())) + return entity.getValue(property.getName()); + else { + Query query = entityManager.createQuery( + "select e." + property.getName() + " from " + entity.getMetaClass().getName() + " e where e." + primaryKeyName + " = ?1"); + query.setParameter(1, entity.getId()); + Object refEntity = query.getFirstResult(); + return (Entity) refEntity; + } + } + + protected boolean checkIfEntityBelongsToMaster(MetaProperty property, Entity entityToRemove) { + MetaProperty inverseProperty = property.getInverse(); + if (inverseProperty != null && !inverseProperty.getRange().getCardinality().isMany()) { + Entity master = entityToRemove.getValue(inverseProperty.getName()); + return entity.equals(master); + } else { + return true; + } + } + + protected boolean isCollectionEmpty(MetaProperty property) { + MetaProperty inverseProperty = property.getInverse(); + if (inverseProperty == null) { + log.warn("Inverse property not found for property " + property); + Collection value = entity.getValue(property.getName()); + return value == null || value.isEmpty(); + } + + String invPropName = inverseProperty.getName(); + String collectionPkName = metadata.getTools().getPrimaryKeyName(property.getRange().asClass()); + + String qlStr = "select e." + collectionPkName + " from " + property.getRange().asClass().getName() + + " e where e." + invPropName + "." + primaryKeyName + " = ?1"; + + Query query = entityManager.createQuery(qlStr); + query.setParameter(1, entity.getId()); + query.setMaxResults(1); + List list = query.getResultList(); + + return list.isEmpty(); + } + + protected Collection getCollection(MetaProperty property) { + MetaProperty inverseProperty = property.getInverse(); + if (inverseProperty == null) { + log.warn("Inverse property not found for property " + property); + Collection value = entity.getValue(property.getName()); + return value == null ? Collections.EMPTY_LIST : value; + } + + String invPropName = inverseProperty.getName(); + String qlStr = "select e from " + property.getRange().asClass().getName() + " e where e." + invPropName + "." + + primaryKeyName + " = ?1"; + + Query query = entityManager.createQuery(qlStr); + query.setParameter(1, entity.getId()); + List list = query.getResultList(); + + // If the property is not loaded, it means it was not modified and further check is not needed + if (!PersistenceHelper.isLoaded(entity, property.getName())) { + return list; + } + // Check whether the collection items still belong to the master entity, because they could be changed in the + // current transaction that did not affect the database yet + List result = new ArrayList<>(list.size()); + for (Entity item : list) { + Entity master = item.getValue(invPropName); + if (entity.equals(master)) + result.add(item); + } + return result; + } + + protected boolean referenceExists(String entityName, MetaProperty property) { + String template = property.getRange().getCardinality().isMany() ? + "select count(e) from %s e join e.%s c where c." + primaryKeyName + "= ?1" : + "select count(e) from %s e where e.%s." + primaryKeyName + " = ?1"; + String qstr = String.format(template, entityName, property.getName()); + Query query = entityManager.createQuery(qstr); + query.setParameter(1, entity.getId()); + query.setMaxResults(1); + Long count = (Long) query.getSingleResult(); + return count > 0; + } + + protected boolean isPersistent(MetaClass metaClass) { + return metaClass.getJavaClass().isAnnotationPresent(javax.persistence.Entity.class); + } + + protected void cascade(String entityName, MetaProperty property) { + String template = property.getRange().getCardinality().isMany() ? + "select e from %s e join e.%s c where c." + primaryKeyName + " = ?1" : + "select e from %s e where e.%s." + primaryKeyName + " = ?1"; + String qstr = String.format(template, entityName, property.getName()); + Query query = entityManager.createQuery(qstr); + query.setParameter(1, entity.getId()); + List list = query.getResultList(); + for (Entity e : list) { + entityManager.remove(e); + } + } + + protected void unlink(String entityName, MetaProperty property) { + if (metadata.getTools().isOwningSide(property)) { + String template = property.getRange().getCardinality().isMany() ? + "select e from %s e join e.%s c where c." + primaryKeyName + " = ?1" : + "select e from %s e where e.%s." + primaryKeyName + " = ?1"; + String qstr = String.format(template, entityName, property.getName()); + Query query = entityManager.createQuery(qstr); + query.setParameter(1, entity.getId()); + List list = query.getResultList(); + for (Entity e : list) { + if (property.getRange().getCardinality().isMany()) { + Collection collection = e.getValue(property.getName()); + if (collection != null) { + for (Iterator it = collection.iterator(); it.hasNext(); ) { + if (entity.equals(it.next())) { + it.remove(); + } + } + } + } else { + setReferenceNull(e, property); + } + } + } else { + MetaProperty inverseProp = property.getInverse(); + if (inverseProp != null && inverseProp.getDomain().equals(metaClass)) { + setReferenceNull(entity, inverseProp); + } + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlDbTypeConverter.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlDbTypeConverter.java index 2ad846ea4c..67dfa89b87 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlDbTypeConverter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlDbTypeConverter.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import java.sql.*; -import java.util.Date; -import java.util.UUID; - -public class HsqlDbTypeConverter implements DbTypeConverter { - - @Override - public Object getJavaObject(ResultSet resultSet, int columnIndex) { - Object value; - - try { - ResultSetMetaData metaData = resultSet.getMetaData(); - - if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) - throw new IndexOutOfBoundsException("Column index out of bound"); - - value = resultSet.getObject(columnIndex); - - return value; - } catch (SQLException e) { - throw new RuntimeException("Error converting database value", e); - } - } - - @Override - public Object getSqlObject(Object value) { - if (value instanceof Date) - return new Timestamp(((Date) value).getTime()); - if (value instanceof UUID) - return value.toString(); - return value; - } - - @Override - public int getSqlType(Class javaClass) { - if (javaClass == Date.class) - return Types.TIMESTAMP; - else if (javaClass == UUID.class) - return Types.VARCHAR; - return Types.OTHER; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import java.sql.*; +import java.util.Date; +import java.util.UUID; + +public class HsqlDbTypeConverter implements DbTypeConverter { + + @Override + public Object getJavaObject(ResultSet resultSet, int columnIndex) { + Object value; + + try { + ResultSetMetaData metaData = resultSet.getMetaData(); + + if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) + throw new IndexOutOfBoundsException("Column index out of bound"); + + value = resultSet.getObject(columnIndex); + + return value; + } catch (SQLException e) { + throw new RuntimeException("Error converting database value", e); + } + } + + @Override + public Object getSqlObject(Object value) { + if (value instanceof Date) + return new Timestamp(((Date) value).getTime()); + if (value instanceof UUID) + return value.toString(); + return value; + } + + @Override + public int getSqlType(Class javaClass) { + if (javaClass == Date.class) + return Types.TIMESTAMP; + else if (javaClass == UUID.class) + return Types.VARCHAR; + return Types.OTHER; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlSequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlSequenceSupport.java index e26ccbd2b7..3046889a25 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlSequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/HsqlSequenceSupport.java @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -public class HsqlSequenceSupport implements SequenceSupport { - - @Override - public String sequenceExistsSql(String sequenceName) { - return "select top 1 SEQUENCE_NAME from INFORMATION_SCHEMA.SYSTEM_SEQUENCES where SEQUENCE_NAME = '" - + sequenceName.toUpperCase() + "'"; - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - return "create sequence " + sequenceName - + " as bigint start with " + startValue + " increment by " + increment; - } - - @Override - public String modifySequenceSql(String sequenceName, long startWith) { - return "alter sequence " + sequenceName + " restart with " + startWith; - } - - @Override - public String deleteSequenceSql(String sequenceName) { - return "drop sequence " + (sequenceName != null ? sequenceName.toUpperCase() : null); - } - - @Override - public String getNextValueSql(String sequenceName) { - return "select next value for " + sequenceName + " from dual"; - } - - @Override - public String getCurrentValueSql(String sequenceName) { - return "select START_WITH from INFORMATION_SCHEMA.SYSTEM_SEQUENCES where SEQUENCE_NAME = '" - + sequenceName.toUpperCase() + "'"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +public class HsqlSequenceSupport implements SequenceSupport { + + @Override + public String sequenceExistsSql(String sequenceName) { + return "select top 1 SEQUENCE_NAME from INFORMATION_SCHEMA.SYSTEM_SEQUENCES where SEQUENCE_NAME = '" + + sequenceName.toUpperCase() + "'"; + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + return "create sequence " + sequenceName + + " as bigint start with " + startValue + " increment by " + increment; + } + + @Override + public String modifySequenceSql(String sequenceName, long startWith) { + return "alter sequence " + sequenceName + " restart with " + startWith; + } + + @Override + public String deleteSequenceSql(String sequenceName) { + return "drop sequence " + (sequenceName != null ? sequenceName.toUpperCase() : null); + } + + @Override + public String getNextValueSql(String sequenceName) { + return "select next value for " + sequenceName + " from dual"; + } + + @Override + public String getCurrentValueSql(String sequenceName) { + return "select START_WITH from INFORMATION_SCHEMA.SYSTEM_SEQUENCES where SEQUENCE_NAME = '" + + sequenceName.toUpperCase() + "'"; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/Mssql2012SequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/Mssql2012SequenceSupport.java index 9dfeb08a4d..fe542fcbe7 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/Mssql2012SequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/Mssql2012SequenceSupport.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.bali.util.Preconditions; - -@SuppressWarnings("UnusedDeclaration") -public class Mssql2012SequenceSupport implements SequenceSupport { - - @Override - public String sequenceExistsSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select NAME from SYS.SEQUENCES where NAME = '" + sequenceName.toUpperCase() + "'"; - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "create sequence " + sequenceName.toUpperCase() - + " as bigint increment by " + increment + " start with " + startValue + " minvalue 0"; - } - - @Override - public String modifySequenceSql(String sequenceName, long startWith) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "alter sequence " + sequenceName.toUpperCase() - + " restart with " + startWith; - } - - @Override - public String deleteSequenceSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "drop sequence " + sequenceName.toUpperCase(); - } - - @Override - public String getNextValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select next value for " + sequenceName.toUpperCase(); - } - - @Override - public String getCurrentValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select cast(CURRENT_VALUE as bigint) from SYS.SEQUENCES where NAME = '" + sequenceName.toUpperCase() + "'"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.bali.util.Preconditions; + +@SuppressWarnings("UnusedDeclaration") +public class Mssql2012SequenceSupport implements SequenceSupport { + + @Override + public String sequenceExistsSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select NAME from SYS.SEQUENCES where NAME = '" + sequenceName.toUpperCase() + "'"; + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "create sequence " + sequenceName.toUpperCase() + + " as bigint increment by " + increment + " start with " + startValue + " minvalue 0"; + } + + @Override + public String modifySequenceSql(String sequenceName, long startWith) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "alter sequence " + sequenceName.toUpperCase() + + " restart with " + startWith; + } + + @Override + public String deleteSequenceSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "drop sequence " + sequenceName.toUpperCase(); + } + + @Override + public String getNextValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select next value for " + sequenceName.toUpperCase(); + } + + @Override + public String getCurrentValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select cast(CURRENT_VALUE as bigint) from SYS.SEQUENCES where NAME = '" + sequenceName.toUpperCase() + "'"; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlDbTypeConverter.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlDbTypeConverter.java index ea1b2fdc53..a78092fd70 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlDbTypeConverter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlDbTypeConverter.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.cuba.core.global.UuidProvider; - -import java.sql.*; -import java.util.Date; -import java.util.UUID; - -public class MssqlDbTypeConverter implements DbTypeConverter { - - @Override - public Object getJavaObject(ResultSet resultSet, int columnIndex) { - Object value; - - try { - ResultSetMetaData metaData = resultSet.getMetaData(); - - if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) - throw new IndexOutOfBoundsException("Column index out of bound"); - - int sqlType = metaData.getColumnType(columnIndex); - String typeName = metaData.getColumnTypeName(columnIndex); - - switch (sqlType) { - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - case Types.CLOB: - if ("uniqueidentifier".equals(typeName)) { - String stringValue = resultSet.getString(columnIndex); - value = stringValue != null ? UuidProvider.fromString(stringValue) : null; - } else { - value = resultSet.getObject(columnIndex); - } - break; - - default: - value = resultSet.getObject(columnIndex); - break; - } - - return value; - } catch (SQLException e) { - throw new RuntimeException("Error converting database value", e); - } - } - - @Override - public Object getSqlObject(Object value) { - if (value instanceof Date) - return new Timestamp(((Date) value).getTime()); - if (value instanceof UUID) - return value.toString(); - if (value instanceof Boolean) - return ((Boolean) value) ? 1 : 0; - return value; - } - - @Override - public int getSqlType(Class javaClass) { - if (javaClass == Date.class) - return Types.TIMESTAMP; - else if (javaClass == UUID.class) - return Types.VARCHAR; - else if (javaClass == Boolean.class) - return Types.BIT; - else if (javaClass == String.class) - return Types.VARCHAR; - else if (javaClass == Integer.class) - return Types.INTEGER; - else if (javaClass == Long.class) - return Types.BIGINT; - return Types.OTHER; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.cuba.core.global.UuidProvider; + +import java.sql.*; +import java.util.Date; +import java.util.UUID; + +public class MssqlDbTypeConverter implements DbTypeConverter { + + @Override + public Object getJavaObject(ResultSet resultSet, int columnIndex) { + Object value; + + try { + ResultSetMetaData metaData = resultSet.getMetaData(); + + if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) + throw new IndexOutOfBoundsException("Column index out of bound"); + + int sqlType = metaData.getColumnType(columnIndex); + String typeName = metaData.getColumnTypeName(columnIndex); + + switch (sqlType) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.CLOB: + if ("uniqueidentifier".equals(typeName)) { + String stringValue = resultSet.getString(columnIndex); + value = stringValue != null ? UuidProvider.fromString(stringValue) : null; + } else { + value = resultSet.getObject(columnIndex); + } + break; + + default: + value = resultSet.getObject(columnIndex); + break; + } + + return value; + } catch (SQLException e) { + throw new RuntimeException("Error converting database value", e); + } + } + + @Override + public Object getSqlObject(Object value) { + if (value instanceof Date) + return new Timestamp(((Date) value).getTime()); + if (value instanceof UUID) + return value.toString(); + if (value instanceof Boolean) + return ((Boolean) value) ? 1 : 0; + return value; + } + + @Override + public int getSqlType(Class javaClass) { + if (javaClass == Date.class) + return Types.TIMESTAMP; + else if (javaClass == UUID.class) + return Types.VARCHAR; + else if (javaClass == Boolean.class) + return Types.BIT; + else if (javaClass == String.class) + return Types.VARCHAR; + else if (javaClass == Integer.class) + return Types.INTEGER; + else if (javaClass == Long.class) + return Types.BIGINT; + return Types.OTHER; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlSequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlSequenceSupport.java index 2d97227470..6c62d2fee2 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlSequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MssqlSequenceSupport.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.TimeSource; - -import java.text.SimpleDateFormat; - -public class MssqlSequenceSupport implements SequenceSupport { - - @Override - public String sequenceExistsSql(String sequenceName) { - return String.format("select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME = '%s'", - sequenceName.toUpperCase()); - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - return String.format("create table %s (ID bigint identity(%d,%d), CREATE_TS datetime)", - sequenceName.toUpperCase(), startValue, increment); - } - - @Override - public String modifySequenceSql(String sequenceName, long startWith) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - return String.format("drop table %1$s ^ " + - "create table %1$s (ID bigint identity(%2$d,1), CREATE_TS datetime) ^ " + - "insert into %1$s (CREATE_TS) values ({ts '%3$s'})", - sequenceName.toUpperCase(), startWith, dateFormat.format(AppBeans.get(TimeSource.class).currentTimestamp())); - } - - @Override - public String deleteSequenceSql(String sequenceName) { - return "drop table " + (sequenceName != null ? sequenceName.toUpperCase() : null); - } - - @Override - public String getNextValueSql(String sequenceName) { - return String.format("insert into %s(CREATE_TS) output inserted.id values(CURRENT_TIMESTAMP);", sequenceName.toUpperCase()); - } - - @Override - public String getCurrentValueSql(String sequenceName) { - return String.format("select ident_current('%s') as CURR_VALUE", sequenceName.toUpperCase()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.TimeSource; + +import java.text.SimpleDateFormat; + +public class MssqlSequenceSupport implements SequenceSupport { + + @Override + public String sequenceExistsSql(String sequenceName) { + return String.format("select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME = '%s'", + sequenceName.toUpperCase()); + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + return String.format("create table %s (ID bigint identity(%d,%d), CREATE_TS datetime)", + sequenceName.toUpperCase(), startValue, increment); + } + + @Override + public String modifySequenceSql(String sequenceName, long startWith) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + return String.format("drop table %1$s ^ " + + "create table %1$s (ID bigint identity(%2$d,1), CREATE_TS datetime) ^ " + + "insert into %1$s (CREATE_TS) values ({ts '%3$s'})", + sequenceName.toUpperCase(), startWith, dateFormat.format(AppBeans.get(TimeSource.class).currentTimestamp())); + } + + @Override + public String deleteSequenceSql(String sequenceName) { + return "drop table " + (sequenceName != null ? sequenceName.toUpperCase() : null); + } + + @Override + public String getNextValueSql(String sequenceName) { + return String.format("insert into %s(CREATE_TS) output inserted.id values(CURRENT_TIMESTAMP);", sequenceName.toUpperCase()); + } + + @Override + public String getCurrentValueSql(String sequenceName) { + return String.format("select ident_current('%s') as CURR_VALUE", sequenceName.toUpperCase()); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbTypeConverter.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbTypeConverter.java index acc4bbfdaf..a86aa70c02 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbTypeConverter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbTypeConverter.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import java.sql.*; -import java.util.Date; -import java.util.UUID; - -public class MysqlDbTypeConverter implements DbTypeConverter { - - @Override - public Object getJavaObject(ResultSet resultSet, int columnIndex) { - Object value; - - try { - ResultSetMetaData metaData = resultSet.getMetaData(); - - if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) - throw new IndexOutOfBoundsException("Column index out of bound"); - - value = resultSet.getObject(columnIndex); - - return value; - } catch (SQLException e) { - throw new RuntimeException("Error converting database value", e); - } - } - - @Override - public Object getSqlObject(Object value) { - if (value instanceof Date) - return new Timestamp(((Date) value).getTime()); - if (value instanceof UUID) - return value.toString().replace("-", ""); - return value; - } - - @Override - public int getSqlType(Class javaClass) { - if (javaClass == Date.class) - return Types.TIMESTAMP; - else if (javaClass == UUID.class) - return Types.VARCHAR; - else if (javaClass == Boolean.class) - return Types.BIT; - else if (javaClass == String.class) - return Types.VARCHAR; - else if (javaClass == Integer.class) - return Types.INTEGER; - else if (javaClass == Long.class) - return Types.BIGINT; - return Types.OTHER; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import java.sql.*; +import java.util.Date; +import java.util.UUID; + +public class MysqlDbTypeConverter implements DbTypeConverter { + + @Override + public Object getJavaObject(ResultSet resultSet, int columnIndex) { + Object value; + + try { + ResultSetMetaData metaData = resultSet.getMetaData(); + + if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) + throw new IndexOutOfBoundsException("Column index out of bound"); + + value = resultSet.getObject(columnIndex); + + return value; + } catch (SQLException e) { + throw new RuntimeException("Error converting database value", e); + } + } + + @Override + public Object getSqlObject(Object value) { + if (value instanceof Date) + return new Timestamp(((Date) value).getTime()); + if (value instanceof UUID) + return value.toString().replace("-", ""); + return value; + } + + @Override + public int getSqlType(Class javaClass) { + if (javaClass == Date.class) + return Types.TIMESTAMP; + else if (javaClass == UUID.class) + return Types.VARCHAR; + else if (javaClass == Boolean.class) + return Types.BIT; + else if (javaClass == String.class) + return Types.VARCHAR; + else if (javaClass == Integer.class) + return Types.INTEGER; + else if (javaClass == Long.class) + return Types.BIGINT; + return Types.OTHER; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbmsFeatures.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbmsFeatures.java index 3b427946f0..512eba4cd4 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbmsFeatures.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlDbmsFeatures.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; - -public class MysqlDbmsFeatures implements DbmsFeatures { - - @Override - public Map getJpaParameters() { - HashMap params = new HashMap<>(); - params.put("eclipselink.target-database", "com.haulmont.cuba.core.sys.persistence.CubaMySQLPlatform"); - return params; - } - - @Override - public String getIdColumn() { - return "ID"; - } - - @Override - public String getDeleteTsColumn() { - return "DELETE_TS"; - } - - @Override - public String getTimeStampType() { - return "DATETIME"; - } - - @Nullable - @Override - public String getUuidTypeClassName() { - return null; - } - - @Nullable - @Override - public String getTransactionTimeoutStatement() { - return null; - } - - @Override - public String getUniqueConstraintViolationPattern() { - return "Duplicate entry '(.+)' for key '(.+)'"; - } - - @Override - public boolean isNullsLastSorting() { - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +public class MysqlDbmsFeatures implements DbmsFeatures { + + @Override + public Map getJpaParameters() { + HashMap params = new HashMap<>(); + params.put("eclipselink.target-database", "com.haulmont.cuba.core.sys.persistence.CubaMySQLPlatform"); + return params; + } + + @Override + public String getIdColumn() { + return "ID"; + } + + @Override + public String getDeleteTsColumn() { + return "DELETE_TS"; + } + + @Override + public String getTimeStampType() { + return "DATETIME"; + } + + @Nullable + @Override + public String getUuidTypeClassName() { + return null; + } + + @Nullable + @Override + public String getTransactionTimeoutStatement() { + return null; + } + + @Override + public String getUniqueConstraintViolationPattern() { + return "Duplicate entry '(.+)' for key '(.+)'"; + } + + @Override + public boolean isNullsLastSorting() { + return false; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlSequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlSequenceSupport.java index a8a542fbbf..6409428f18 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlSequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/MysqlSequenceSupport.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.bali.util.Preconditions; - -public class MysqlSequenceSupport implements SequenceSupport { - @Override - public String sequenceExistsSql(String sequenceName) { - return "select NAME from SYS_SEQUENCE where NAME = '" + sequenceName + "'"; - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - return "insert into SYS_SEQUENCE (NAME, CURR_VALUE, INCREMENT) values ('" + sequenceName + "', " + startValue - + ", " + increment + ")"; - } - - @Override - public String modifySequenceSql(String sequenceName, long startWith) { - return "update SYS_SEQUENCE set CURR_VALUE = " + startWith + " where " + - "NAME = '" + sequenceName + "'"; - } - - @Override - public String deleteSequenceSql(String sequenceName) { - return "delete from SYS_SEQUENCE where name = '" + sequenceName + "'"; - } - - @Override - public String getNextValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "update SYS_SEQUENCE set CURR_VALUE = last_insert_id(CURR_VALUE + INCREMENT) where NAME = '" + sequenceName + "' ^ select last_insert_id() - INCREMENT from SYS_SEQUENCE where NAME = '" + sequenceName +"'"; - } - - @Override - public String getCurrentValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select CURR_VALUE from SYS_SEQUENCE where NAME = '" + sequenceName.toLowerCase() + "'"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.bali.util.Preconditions; + +public class MysqlSequenceSupport implements SequenceSupport { + @Override + public String sequenceExistsSql(String sequenceName) { + return "select NAME from SYS_SEQUENCE where NAME = '" + sequenceName + "'"; + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + return "insert into SYS_SEQUENCE (NAME, CURR_VALUE, INCREMENT) values ('" + sequenceName + "', " + startValue + + ", " + increment + ")"; + } + + @Override + public String modifySequenceSql(String sequenceName, long startWith) { + return "update SYS_SEQUENCE set CURR_VALUE = " + startWith + " where " + + "NAME = '" + sequenceName + "'"; + } + + @Override + public String deleteSequenceSql(String sequenceName) { + return "delete from SYS_SEQUENCE where name = '" + sequenceName + "'"; + } + + @Override + public String getNextValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "update SYS_SEQUENCE set CURR_VALUE = last_insert_id(CURR_VALUE + INCREMENT) where NAME = '" + sequenceName + "' ^ select last_insert_id() - INCREMENT from SYS_SEQUENCE where NAME = '" + sequenceName +"'"; + } + + @Override + public String getCurrentValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select CURR_VALUE from SYS_SEQUENCE where NAME = '" + sequenceName.toLowerCase() + "'"; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/OracleSequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/OracleSequenceSupport.java index 4eb1117f22..2d0e006a64 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/OracleSequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/OracleSequenceSupport.java @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -public class OracleSequenceSupport implements SequenceSupport { - - @Override - public String sequenceExistsSql(String sequenceName) { - return "select SEQUENCE_NAME from USER_SEQUENCES where SEQUENCE_NAME = '" + sequenceName.toUpperCase() + "'"; - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - return "create sequence " + sequenceName + " increment by " + increment + " start with " + startValue + " nocache minvalue 0"; - } - - @Override - public String modifySequenceSql(String sequenceName, long newVal) { - return "{call SET_SEQ_VAL('" + sequenceName + "', " + newVal + ")}"; - } - - @Override - public String deleteSequenceSql(String sequenceName) { - return "drop sequence " + (sequenceName != null ? sequenceName.toUpperCase() : null); - } - - @Override - public String getNextValueSql(String sequenceName) { - return "select " + sequenceName + ".NEXTVAL from DUAL"; - } - - @Override - public String getCurrentValueSql(String sequenceName) { - return "select GET_SEQ_VAL('" + sequenceName.toUpperCase() + "') from DUAL"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +public class OracleSequenceSupport implements SequenceSupport { + + @Override + public String sequenceExistsSql(String sequenceName) { + return "select SEQUENCE_NAME from USER_SEQUENCES where SEQUENCE_NAME = '" + sequenceName.toUpperCase() + "'"; + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + return "create sequence " + sequenceName + " increment by " + increment + " start with " + startValue + " nocache minvalue 0"; + } + + @Override + public String modifySequenceSql(String sequenceName, long newVal) { + return "{call SET_SEQ_VAL('" + sequenceName + "', " + newVal + ")}"; + } + + @Override + public String deleteSequenceSql(String sequenceName) { + return "drop sequence " + (sequenceName != null ? sequenceName.toUpperCase() : null); + } + + @Override + public String getNextValueSql(String sequenceName) { + return "select " + sequenceName + ".NEXTVAL from DUAL"; + } + + @Override + public String getCurrentValueSql(String sequenceName) { + return "select GET_SEQ_VAL('" + sequenceName.toUpperCase() + "') from DUAL"; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PersistenceConfigProcessor.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PersistenceConfigProcessor.java index 5e1bf95530..2f440acb70 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PersistenceConfigProcessor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PersistenceConfigProcessor.java @@ -1,225 +1,225 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.cuba.core.global.Stores; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.ConfigurationResourceLoader; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Document; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; - -import javax.persistence.Entity; -import java.io.*; -import java.util.*; - -/** - * Generates a working persistence.xml file combining classes and properties from a set of given persistence.xml files, - * defined in cuba.persistenceConfig app property. - * - */ -public class PersistenceConfigProcessor { - - private String baseDir; - private List sourceFileNames; - private String outFileName; - private String storeName; - - private Logger log = LoggerFactory.getLogger(PersistenceConfigProcessor.class); - - public void setBaseDir(String baseDir) { - this.baseDir = baseDir; - } - - public void setSourceFiles(List files) { - sourceFileNames = files; - } - - public void setOutputFile(String file) { - outFileName = file; - } - - public void setStorageName(String storeName) { - this.storeName = storeName; - } - - public void create() { - if (sourceFileNames == null || sourceFileNames.isEmpty()) - throw new IllegalStateException("Source file list not set"); - if (StringUtils.isBlank(outFileName)) - throw new IllegalStateException("Output file not set"); - - Map classes = new LinkedHashMap<>(); - Map properties = new HashMap<>(); - - properties.putAll(DbmsSpecificFactory.getDbmsFeatures(storeName).getJpaParameters()); - - for (String fileName : sourceFileNames) { - Document doc = getDocument(fileName); - Element puElem = findPersistenceUnitElement(doc.getRootElement()); - if (puElem == null) - throw new IllegalStateException("No persistence unit named 'cuba' found among multiple units inside " + fileName); - addClasses(puElem, classes); - addProperties(puElem, properties); - } - - for (String name : AppContext.getPropertyNames()) { - if (name.startsWith("eclipselink.")) { - properties.put(name, AppContext.getProperty(name)); - } - } - - if (!Stores.isMain(storeName)) - properties.put(PersistenceImplSupport.PROP_NAME, storeName); - - File outFile; - try { - outFile = new File(outFileName).getCanonicalFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } - outFile.getParentFile().mkdirs(); - - boolean ormXmlCreated = true; - String disableOrmGenProp = AppContext.getProperty("cuba.disableOrmXmlGeneration"); - if (!Boolean.parseBoolean(disableOrmGenProp)) { - MappingFileCreator mappingFileCreator = new MappingFileCreator(classes.values(), properties, outFile.getParentFile()); - ormXmlCreated = mappingFileCreator.create(); - } - - String fileName = sourceFileNames.get(sourceFileNames.size() - 1); - Document doc = getDocument(fileName); - Element rootElem = doc.getRootElement(); - - Element puElem = findPersistenceUnitElement(rootElem); - if (puElem == null) - throw new IllegalStateException("No persistence unit named 'cuba' found among multiple units inside " + fileName); - - String puName = AppContext.getProperty("cuba.persistenceUnitName"); - if (!StringUtils.isEmpty(puName)) { - if (!Stores.isMain(storeName)) - puName = puName + "_" + storeName; - puElem.addAttribute("name", puName); - } - - for (Element element : new ArrayList<>(Dom4j.elements(puElem, "class"))) { - puElem.remove(element); - } - - puElem.addElement("provider").setText("org.eclipse.persistence.jpa.PersistenceProvider"); - - if (ormXmlCreated) { - puElem.addElement("mapping-file").setText("orm.xml"); - } - - for (String className : classes.values()) { - puElem.addElement("class").setText(className); - } - - puElem.addElement("exclude-unlisted-classes"); - - Element propertiesEl = puElem.element("properties"); - if (propertiesEl != null) - puElem.remove(propertiesEl); - - propertiesEl = puElem.addElement("properties"); - for (Map.Entry entry : properties.entrySet()) { - Element element = propertiesEl.addElement("property"); - element.addAttribute("name", entry.getKey()); - element.addAttribute("value", entry.getValue()); - } - - log.info("Creating file " + outFile); - OutputStream os = null; - try { - os = new FileOutputStream(outFileName); - Dom4j.writeDocument(doc, true, os); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(os); - } - } - - private void addClasses(Element puElem, Map classes) { - for (Element element : Dom4j.elements(puElem, "class")) { - String className = element.getText(); - Class cls = ReflectionHelper.getClass(className); - Entity annotation = cls.getAnnotation(Entity.class); - if (annotation != null) { - classes.put(annotation.name(), className); - } else { - classes.put(className, className); - } - } - } - - private void addProperties(Element puElem, Map properties) { - Element propertiesEl = puElem.element("properties"); - if (propertiesEl != null) { - for (Element element : Dom4j.elements(propertiesEl, "property")) { - properties.put(element.attributeValue("name"), element.attributeValue("value")); - } - } - } - - private Element findPersistenceUnitElement(Element rootElem) { - List puList = Dom4j.elements(rootElem, "persistence-unit"); - if (puList.size() == 1) { - return puList.get(0); - } else { - for (Element element : puList) { - if ("cuba".equals(element.attributeValue("name"))) { - return element; - } - } - } - return null; - } - - private Document getDocument(String fileName) { - Document doc; - if (baseDir == null) { - Resource resource = new ConfigurationResourceLoader().getResource(fileName); - InputStream stream = null; - try { - stream = resource.getInputStream(); - doc = Dom4j.readDocument(stream); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(stream); - } - } else { - if (!fileName.startsWith("/")) - fileName = "/" + fileName; - File file = new File(baseDir, fileName); - if (!file.exists()) - throw new IllegalArgumentException("File not found: " + file.getAbsolutePath()); - - doc = Dom4j.readDocument(file); - } - return doc; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.cuba.core.global.Stores; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.ConfigurationResourceLoader; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Document; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; + +import javax.persistence.Entity; +import java.io.*; +import java.util.*; + +/** + * Generates a working persistence.xml file combining classes and properties from a set of given persistence.xml files, + * defined in cuba.persistenceConfig app property. + * + */ +public class PersistenceConfigProcessor { + + private String baseDir; + private List sourceFileNames; + private String outFileName; + private String storeName; + + private Logger log = LoggerFactory.getLogger(PersistenceConfigProcessor.class); + + public void setBaseDir(String baseDir) { + this.baseDir = baseDir; + } + + public void setSourceFiles(List files) { + sourceFileNames = files; + } + + public void setOutputFile(String file) { + outFileName = file; + } + + public void setStorageName(String storeName) { + this.storeName = storeName; + } + + public void create() { + if (sourceFileNames == null || sourceFileNames.isEmpty()) + throw new IllegalStateException("Source file list not set"); + if (StringUtils.isBlank(outFileName)) + throw new IllegalStateException("Output file not set"); + + Map classes = new LinkedHashMap<>(); + Map properties = new HashMap<>(); + + properties.putAll(DbmsSpecificFactory.getDbmsFeatures(storeName).getJpaParameters()); + + for (String fileName : sourceFileNames) { + Document doc = getDocument(fileName); + Element puElem = findPersistenceUnitElement(doc.getRootElement()); + if (puElem == null) + throw new IllegalStateException("No persistence unit named 'cuba' found among multiple units inside " + fileName); + addClasses(puElem, classes); + addProperties(puElem, properties); + } + + for (String name : AppContext.getPropertyNames()) { + if (name.startsWith("eclipselink.")) { + properties.put(name, AppContext.getProperty(name)); + } + } + + if (!Stores.isMain(storeName)) + properties.put(PersistenceImplSupport.PROP_NAME, storeName); + + File outFile; + try { + outFile = new File(outFileName).getCanonicalFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + outFile.getParentFile().mkdirs(); + + boolean ormXmlCreated = true; + String disableOrmGenProp = AppContext.getProperty("cuba.disableOrmXmlGeneration"); + if (!Boolean.parseBoolean(disableOrmGenProp)) { + MappingFileCreator mappingFileCreator = new MappingFileCreator(classes.values(), properties, outFile.getParentFile()); + ormXmlCreated = mappingFileCreator.create(); + } + + String fileName = sourceFileNames.get(sourceFileNames.size() - 1); + Document doc = getDocument(fileName); + Element rootElem = doc.getRootElement(); + + Element puElem = findPersistenceUnitElement(rootElem); + if (puElem == null) + throw new IllegalStateException("No persistence unit named 'cuba' found among multiple units inside " + fileName); + + String puName = AppContext.getProperty("cuba.persistenceUnitName"); + if (!StringUtils.isEmpty(puName)) { + if (!Stores.isMain(storeName)) + puName = puName + "_" + storeName; + puElem.addAttribute("name", puName); + } + + for (Element element : new ArrayList<>(Dom4j.elements(puElem, "class"))) { + puElem.remove(element); + } + + puElem.addElement("provider").setText("org.eclipse.persistence.jpa.PersistenceProvider"); + + if (ormXmlCreated) { + puElem.addElement("mapping-file").setText("orm.xml"); + } + + for (String className : classes.values()) { + puElem.addElement("class").setText(className); + } + + puElem.addElement("exclude-unlisted-classes"); + + Element propertiesEl = puElem.element("properties"); + if (propertiesEl != null) + puElem.remove(propertiesEl); + + propertiesEl = puElem.addElement("properties"); + for (Map.Entry entry : properties.entrySet()) { + Element element = propertiesEl.addElement("property"); + element.addAttribute("name", entry.getKey()); + element.addAttribute("value", entry.getValue()); + } + + log.info("Creating file " + outFile); + OutputStream os = null; + try { + os = new FileOutputStream(outFileName); + Dom4j.writeDocument(doc, true, os); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(os); + } + } + + private void addClasses(Element puElem, Map classes) { + for (Element element : Dom4j.elements(puElem, "class")) { + String className = element.getText(); + Class cls = ReflectionHelper.getClass(className); + Entity annotation = cls.getAnnotation(Entity.class); + if (annotation != null) { + classes.put(annotation.name(), className); + } else { + classes.put(className, className); + } + } + } + + private void addProperties(Element puElem, Map properties) { + Element propertiesEl = puElem.element("properties"); + if (propertiesEl != null) { + for (Element element : Dom4j.elements(propertiesEl, "property")) { + properties.put(element.attributeValue("name"), element.attributeValue("value")); + } + } + } + + private Element findPersistenceUnitElement(Element rootElem) { + List puList = Dom4j.elements(rootElem, "persistence-unit"); + if (puList.size() == 1) { + return puList.get(0); + } else { + for (Element element : puList) { + if ("cuba".equals(element.attributeValue("name"))) { + return element; + } + } + } + return null; + } + + private Document getDocument(String fileName) { + Document doc; + if (baseDir == null) { + Resource resource = new ConfigurationResourceLoader().getResource(fileName); + InputStream stream = null; + try { + stream = resource.getInputStream(); + doc = Dom4j.readDocument(stream); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } else { + if (!fileName.startsWith("/")) + fileName = "/" + fileName; + File file = new File(baseDir, fileName); + if (!file.exists()) + throw new IllegalArgumentException("File not found: " + file.getAbsolutePath()); + + doc = Dom4j.readDocument(file); + } + return doc; + } +} diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresDbTypeConverter.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresDbTypeConverter.java index 6d660ab777..7549839a2d 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresDbTypeConverter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresDbTypeConverter.java @@ -1,83 +1,83 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.cuba.core.global.UuidProvider; - -import java.sql.*; -import java.util.Date; -import java.util.UUID; - -public class PostgresDbTypeConverter implements DbTypeConverter { - - @Override - public Object getJavaObject(ResultSet resultSet, int columnIndex) { - Object value; - - try { - ResultSetMetaData metaData = resultSet.getMetaData(); - - if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) - throw new IndexOutOfBoundsException("Column index out of bound"); - - int sqlType = metaData.getColumnType(columnIndex); - String typeName = metaData.getColumnTypeName(columnIndex); - - switch (sqlType) { - case Types.OTHER: - if (resultSet.getObject(columnIndex) instanceof UUID) { - value = resultSet.getObject(columnIndex); - } else if ("uuid".equals(typeName)) { - String stringValue = resultSet.getString(columnIndex); - value = stringValue != null ? UuidProvider.fromString(stringValue) : null; - } else { - value = resultSet.getObject(columnIndex); - } - break; - - default: - value = resultSet.getObject(columnIndex); - break; - } - - return value; - } catch (SQLException e) { - throw new RuntimeException("Error converting database value", e); - } - } - - @Override - public Object getSqlObject(Object value) { - try { - if (value instanceof Date) - return new Timestamp(((Date) value).getTime()); - if (value instanceof UUID) - return new PostgresUUID((UUID) value); - return value; - } catch (SQLException e) { - throw new RuntimeException("Error converting application value", e); - } - } - - @Override - public int getSqlType(Class javaClass) { - if (javaClass == Date.class) - return Types.TIMESTAMP; - return Types.OTHER; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.cuba.core.global.UuidProvider; + +import java.sql.*; +import java.util.Date; +import java.util.UUID; + +public class PostgresDbTypeConverter implements DbTypeConverter { + + @Override + public Object getJavaObject(ResultSet resultSet, int columnIndex) { + Object value; + + try { + ResultSetMetaData metaData = resultSet.getMetaData(); + + if ((columnIndex > metaData.getColumnCount()) || (columnIndex <= 0)) + throw new IndexOutOfBoundsException("Column index out of bound"); + + int sqlType = metaData.getColumnType(columnIndex); + String typeName = metaData.getColumnTypeName(columnIndex); + + switch (sqlType) { + case Types.OTHER: + if (resultSet.getObject(columnIndex) instanceof UUID) { + value = resultSet.getObject(columnIndex); + } else if ("uuid".equals(typeName)) { + String stringValue = resultSet.getString(columnIndex); + value = stringValue != null ? UuidProvider.fromString(stringValue) : null; + } else { + value = resultSet.getObject(columnIndex); + } + break; + + default: + value = resultSet.getObject(columnIndex); + break; + } + + return value; + } catch (SQLException e) { + throw new RuntimeException("Error converting database value", e); + } + } + + @Override + public Object getSqlObject(Object value) { + try { + if (value instanceof Date) + return new Timestamp(((Date) value).getTime()); + if (value instanceof UUID) + return new PostgresUUID((UUID) value); + return value; + } catch (SQLException e) { + throw new RuntimeException("Error converting application value", e); + } + } + + @Override + public int getSqlType(Class javaClass) { + if (javaClass == Date.class) + return Types.TIMESTAMP; + return Types.OTHER; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresSequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresSequenceSupport.java index 7666e147c7..73616f8abc 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresSequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/PostgresSequenceSupport.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import com.haulmont.bali.util.Preconditions; - -public class PostgresSequenceSupport implements SequenceSupport { - - @Override - public String sequenceExistsSql(String sequenceName) { - return "select relname from pg_class where relkind = 'S' and relname = '" - + sequenceName.toLowerCase() + "'"; - } - - @Override - public String createSequenceSql(String sequenceName, long startValue, long increment) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "create sequence " + sequenceName.toLowerCase() - + " increment by " + increment + " start with " + startValue + " minvalue 0"; - } - - @Override - public String modifySequenceSql(String sequenceName, long startWith) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select setval('" + sequenceName.toLowerCase() + "', " + startWith + ")"; - } - - @Override - public String deleteSequenceSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "drop sequence " + sequenceName.toLowerCase(); - } - - @Override - public String getNextValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select nextval('" + sequenceName.toLowerCase() + "')"; - } - - @Override - public String getCurrentValueSql(String sequenceName) { - Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); - return "select last_value from " + sequenceName.toLowerCase(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import com.haulmont.bali.util.Preconditions; + +public class PostgresSequenceSupport implements SequenceSupport { + + @Override + public String sequenceExistsSql(String sequenceName) { + return "select relname from pg_class where relkind = 'S' and relname = '" + + sequenceName.toLowerCase() + "'"; + } + + @Override + public String createSequenceSql(String sequenceName, long startValue, long increment) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "create sequence " + sequenceName.toLowerCase() + + " increment by " + increment + " start with " + startValue + " minvalue 0"; + } + + @Override + public String modifySequenceSql(String sequenceName, long startWith) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select setval('" + sequenceName.toLowerCase() + "', " + startWith + ")"; + } + + @Override + public String deleteSequenceSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "drop sequence " + sequenceName.toLowerCase(); + } + + @Override + public String getNextValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select nextval('" + sequenceName.toLowerCase() + "')"; + } + + @Override + public String getCurrentValueSql(String sequenceName) { + Preconditions.checkNotNullArgument(sequenceName, "sequenceName is null"); + return "select last_value from " + sequenceName.toLowerCase(); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/persistence/SequenceSupport.java b/modules/core/src/com/haulmont/cuba/core/sys/persistence/SequenceSupport.java index b0632249b1..e392a61d5d 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/persistence/SequenceSupport.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/persistence/SequenceSupport.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * 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. - * - */ - -/* - * Author: Konstantin Krivopustov - * Created: 15.05.2009 22:25:05 - * - */ -package com.haulmont.cuba.core.sys.persistence; - -/** - * Interface defining methods for managing database sequences. - * - */ -public interface SequenceSupport { - - String SQL_DELIMITER = "^"; - - String sequenceExistsSql(String sequenceName); - - String createSequenceSql(String sequenceName, long startValue, long increment); - - String modifySequenceSql(String sequenceName, long startWith); - - String deleteSequenceSql(String sequenceName); - - String getNextValueSql(String sequenceName); - - String getCurrentValueSql(String sequenceName); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * 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. + * + */ + +/* + * Author: Konstantin Krivopustov + * Created: 15.05.2009 22:25:05 + * + */ +package com.haulmont.cuba.core.sys.persistence; + +/** + * Interface defining methods for managing database sequences. + * + */ +public interface SequenceSupport { + + String SQL_DELIMITER = "^"; + + String sequenceExistsSql(String sequenceName); + + String createSequenceSql(String sequenceName, long startValue, long increment); + + String modifySequenceSql(String sequenceName, long startWith); + + String deleteSequenceSql(String sequenceName); + + String getNextValueSql(String sequenceName); + + String getCurrentValueSql(String sequenceName); +} diff --git a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateAfterMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateAfterMacroHandler.java index a074b04885..e1330ca64f 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateAfterMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateAfterMacroHandler.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import org.apache.commons.lang.time.DateUtils; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.regex.Pattern; - -@Component("cuba_DateAfterQueryMacroHandler") -@Scope("prototype") -public class DateAfterMacroHandler extends AbstractQueryMacroHandler { - - protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateAfter\\s*\\(([^)]+)\\)"); - - protected Map namedParameters; - protected List paramNames = new ArrayList<>(); - - public DateAfterMacroHandler() { - super(MACRO_PATTERN); - } - - @Override - protected String doExpand(String macro) { - count++; - String[] args = macro.split(","); - if (args.length != 2) - throw new RuntimeException("Invalid macro: " + macro); - - String field = args[0].trim(); - String param = args[1].trim().substring(1); - paramNames.add(param); - - return String.format("(%s >= :%s)", field, param); - } - - @Override - public void setQueryParams(Map namedParameters) { - this.namedParameters = namedParameters; - } - - @Override - public Map getParams() { - Map params = new HashMap<>(); - for (String paramName : paramNames) { - Date date = (Date) namedParameters.get(paramName); - if (date == null) - throw new RuntimeException("Parameter " + paramName + " not found for macro"); - - Date d = DateUtils.truncate(date, Calendar.DAY_OF_MONTH); - params.put(paramName, d); - } - return params; - } - - @Override - public String replaceQueryParams(String queryString, Map params) { - return queryString; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import org.apache.commons.lang.time.DateUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.regex.Pattern; + +@Component("cuba_DateAfterQueryMacroHandler") +@Scope("prototype") +public class DateAfterMacroHandler extends AbstractQueryMacroHandler { + + protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateAfter\\s*\\(([^)]+)\\)"); + + protected Map namedParameters; + protected List paramNames = new ArrayList<>(); + + public DateAfterMacroHandler() { + super(MACRO_PATTERN); + } + + @Override + protected String doExpand(String macro) { + count++; + String[] args = macro.split(","); + if (args.length != 2) + throw new RuntimeException("Invalid macro: " + macro); + + String field = args[0].trim(); + String param = args[1].trim().substring(1); + paramNames.add(param); + + return String.format("(%s >= :%s)", field, param); + } + + @Override + public void setQueryParams(Map namedParameters) { + this.namedParameters = namedParameters; + } + + @Override + public Map getParams() { + Map params = new HashMap<>(); + for (String paramName : paramNames) { + Date date = (Date) namedParameters.get(paramName); + if (date == null) + throw new RuntimeException("Parameter " + paramName + " not found for macro"); + + Date d = DateUtils.truncate(date, Calendar.DAY_OF_MONTH); + params.put(paramName, d); + } + return params; + } + + @Override + public String replaceQueryParams(String queryString, Map params) { + return queryString; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateBeforeMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateBeforeMacroHandler.java index 6362830df4..153df9ba78 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateBeforeMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateBeforeMacroHandler.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import org.apache.commons.lang.time.DateUtils; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.regex.Pattern; - -@Component("cuba_DateBeforeQueryMacroHandler") -@Scope("prototype") -public class DateBeforeMacroHandler extends AbstractQueryMacroHandler { - - protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateBefore\\s*\\(([^)]+)\\)"); - - protected Map namedParameters; - protected List paramNames = new ArrayList<>(); - - public DateBeforeMacroHandler() { - super(MACRO_PATTERN); - } - - @Override - protected String doExpand(String macro) { - count++; - String[] args = macro.split(","); - if (args.length != 2) - throw new RuntimeException("Invalid macro: " + macro); - - String field = args[0].trim(); - String param = args[1].trim().substring(1); - paramNames.add(param); - - return String.format("(%s < :%s)", field, param); - } - - @Override - public void setQueryParams(Map namedParameters) { - this.namedParameters = namedParameters; - } - - @Override - public Map getParams() { - Map params = new HashMap<>(); - for (String paramName : paramNames) { - Date date = (Date) namedParameters.get(paramName); - if (date == null) - throw new RuntimeException("Parameter " + paramName + " not found for macro"); - - Date d = DateUtils.truncate(date, Calendar.DAY_OF_MONTH); - params.put(paramName, d); - } - return params; - } - - @Override - public String replaceQueryParams(String queryString, Map params) { - return queryString; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import org.apache.commons.lang.time.DateUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.regex.Pattern; + +@Component("cuba_DateBeforeQueryMacroHandler") +@Scope("prototype") +public class DateBeforeMacroHandler extends AbstractQueryMacroHandler { + + protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateBefore\\s*\\(([^)]+)\\)"); + + protected Map namedParameters; + protected List paramNames = new ArrayList<>(); + + public DateBeforeMacroHandler() { + super(MACRO_PATTERN); + } + + @Override + protected String doExpand(String macro) { + count++; + String[] args = macro.split(","); + if (args.length != 2) + throw new RuntimeException("Invalid macro: " + macro); + + String field = args[0].trim(); + String param = args[1].trim().substring(1); + paramNames.add(param); + + return String.format("(%s < :%s)", field, param); + } + + @Override + public void setQueryParams(Map namedParameters) { + this.namedParameters = namedParameters; + } + + @Override + public Map getParams() { + Map params = new HashMap<>(); + for (String paramName : paramNames) { + Date date = (Date) namedParameters.get(paramName); + if (date == null) + throw new RuntimeException("Parameter " + paramName + " not found for macro"); + + Date d = DateUtils.truncate(date, Calendar.DAY_OF_MONTH); + params.put(paramName, d); + } + return params; + } + + @Override + public String replaceQueryParams(String queryString, Map params) { + return queryString; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandler.java index 676361d6f0..d4858e9bde 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandler.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import com.haulmont.bali.datastruct.Pair; -import org.apache.commons.lang.time.DateUtils; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.regex.Pattern; - -@Component("cuba_DateEqualsQueryMacroHandler") -@Scope("prototype") -public class DateEqualsMacroHandler extends AbstractQueryMacroHandler { - - protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateEquals\\s*\\(([^)]+)\\)"); - - protected Map namedParameters; - protected List> paramNames = new ArrayList<>(); - - public DateEqualsMacroHandler() { - super(MACRO_PATTERN); - } - - @Override - public void setQueryParams(Map namedParameters) { - this.namedParameters = namedParameters; - } - - @Override - protected String doExpand(String macro) { - count++; - String[] args = macro.split(","); - if (args.length != 2) - throw new RuntimeException("Invalid macro: " + macro); - - String field = args[0].trim(); - String param1 = args[1].trim().substring(1); - String param2 = field.replace(".", "_") + "_" + count; - paramNames.add(new Pair<>(param1, param2)); - - return String.format("(%s >= :%s and %s < :%s)", field, param1, field, param2); - } - - @Override - public Map getParams() { - Map params = new HashMap<>(); - for (Pair pair : paramNames) { - Date date1 = (Date) namedParameters.get(pair.getFirst()); - if (date1 == null) - throw new RuntimeException("Parameter " + pair.getFirst() + " not found for macro"); - date1 = DateUtils.truncate(date1, Calendar.DAY_OF_MONTH); - Date date2 = DateUtils.addDays(date1, 1); - - params.put(pair.getFirst(), date1); - params.put(pair.getSecond(), date2); - } - return params; - } - - @Override - public String replaceQueryParams(String queryString, Map params) { - return queryString; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import com.haulmont.bali.datastruct.Pair; +import org.apache.commons.lang.time.DateUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.regex.Pattern; + +@Component("cuba_DateEqualsQueryMacroHandler") +@Scope("prototype") +public class DateEqualsMacroHandler extends AbstractQueryMacroHandler { + + protected static final Pattern MACRO_PATTERN = Pattern.compile("@dateEquals\\s*\\(([^)]+)\\)"); + + protected Map namedParameters; + protected List> paramNames = new ArrayList<>(); + + public DateEqualsMacroHandler() { + super(MACRO_PATTERN); + } + + @Override + public void setQueryParams(Map namedParameters) { + this.namedParameters = namedParameters; + } + + @Override + protected String doExpand(String macro) { + count++; + String[] args = macro.split(","); + if (args.length != 2) + throw new RuntimeException("Invalid macro: " + macro); + + String field = args[0].trim(); + String param1 = args[1].trim().substring(1); + String param2 = field.replace(".", "_") + "_" + count; + paramNames.add(new Pair<>(param1, param2)); + + return String.format("(%s >= :%s and %s < :%s)", field, param1, field, param2); + } + + @Override + public Map getParams() { + Map params = new HashMap<>(); + for (Pair pair : paramNames) { + Date date1 = (Date) namedParameters.get(pair.getFirst()); + if (date1 == null) + throw new RuntimeException("Parameter " + pair.getFirst() + " not found for macro"); + date1 = DateUtils.truncate(date1, Calendar.DAY_OF_MONTH); + Date date2 = DateUtils.addDays(date1, 1); + + params.put(pair.getFirst(), date1); + params.put(pair.getSecond(), date2); + } + return params; + } + + @Override + public String replaceQueryParams(String queryString, Map params) { + return queryString; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandler.java index 74411f1864..509b5eb401 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandler.java @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import com.google.common.base.Strings; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Scripting; -import com.haulmont.cuba.core.global.TimeSource; -import groovy.lang.Binding; -import org.apache.commons.lang.time.DateUtils; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Component("cuba_TimeBetweenQueryMacroHandler") -@Scope("prototype") -public class TimeBetweenQueryMacroHandler extends AbstractQueryMacroHandler { - - protected static final Pattern MACRO_PATTERN = Pattern.compile("@between\\s*\\(([^)]+)\\)"); - protected static final Pattern PARAM_PATTERN = Pattern.compile("(now)\\s*([\\d\\s+-]*)"); - protected static final Pattern QUERY_PARAM_PATTERN = Pattern.compile(":(\\w+)"); - - protected static final Map units = new HashMap<>(); - - static { - units.put("year", Calendar.YEAR); - units.put("month", Calendar.MONTH); - units.put("day", Calendar.DAY_OF_MONTH); - units.put("hour", Calendar.HOUR_OF_DAY); - units.put("minute", Calendar.MINUTE); - units.put("second", Calendar.SECOND); - } - - protected Map params = new HashMap<>(); - - public TimeBetweenQueryMacroHandler() { - super(MACRO_PATTERN); - } - - @Override - public void setQueryParams(Map namedParameters) { - } - - @Override - public Map getParams() { - return params; - } - - @Override - public String replaceQueryParams(String queryString, Map params) { - Matcher matcher = MACRO_PATTERN.matcher(queryString); - StringBuffer sb = new StringBuffer(); - while (matcher.find()) { - String macros = matcher.group(0); - macros = replaceParamsInMacros(macros, params); - matcher.appendReplacement(sb, macros); - } - matcher.appendTail(sb); - return sb.toString(); - } - - protected String replaceParamsInMacros(String macros, Map params) { - Matcher matcher = QUERY_PARAM_PATTERN.matcher(macros); - StringBuffer sb = new StringBuffer(); - while (matcher.find()) { - String paramName = matcher.group(1); - if (params.containsKey(paramName)) { - matcher.appendReplacement(sb, params.get(paramName).toString()); - params.remove(paramName); - } - } - matcher.appendTail(sb); - return sb.toString(); - } - - @Override - protected String doExpand(String macro) { - count++; - String[] args = macro.split(","); - if (args.length != 4) - throw new RuntimeException("Invalid macro: " + macro); - - String field = args[0]; - String param1 = getParam(args, 1); - String param2 = getParam(args, 2); - - return String.format("(%s >= :%s and %s < :%s)", field, param1, field, param2); - } - - protected String getParam(String[] args, int idx) { - String arg = args[idx].trim(); - String unit = args[3].trim(); - - Matcher matcher = PARAM_PATTERN.matcher(arg); - if (!matcher.find()) - throw new RuntimeException("Invalid macro argument: " + arg); - - int num = 0; - try { - String expr = matcher.group(2); - if (!Strings.isNullOrEmpty(expr)) { - Scripting scripting = AppBeans.get(Scripting.class); - num = scripting.evaluateGroovy(expr, new Binding()); - } - } catch (NumberFormatException e) { - throw new RuntimeException("Invalid macro argument: " + arg, e); - } - - Date date = computeDate(num, unit); - - String paramName = args[0].trim().replace(".", "_") + "_" + count + "_" + idx; - params.put(paramName, date); - - return paramName; - } - - protected Date computeDate(int num, String unit) { - Calendar cal = Calendar.getInstance(); - cal.setTime(AppBeans.get(TimeSource.class).currentTimestamp()); - int calField = getCalendarField(unit); - if (num != 0) { - cal.add(calField, num); - } - return DateUtils.truncate(cal.getTime(), calField); - } - - protected int getCalendarField(String unit) { - Integer calField = (Integer) units.get(unit.toLowerCase()); - if (calField == null) - throw new RuntimeException("Invalid macro argument: " + unit); - return calField; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import com.google.common.base.Strings; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Scripting; +import com.haulmont.cuba.core.global.TimeSource; +import groovy.lang.Binding; +import org.apache.commons.lang.time.DateUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Component("cuba_TimeBetweenQueryMacroHandler") +@Scope("prototype") +public class TimeBetweenQueryMacroHandler extends AbstractQueryMacroHandler { + + protected static final Pattern MACRO_PATTERN = Pattern.compile("@between\\s*\\(([^)]+)\\)"); + protected static final Pattern PARAM_PATTERN = Pattern.compile("(now)\\s*([\\d\\s+-]*)"); + protected static final Pattern QUERY_PARAM_PATTERN = Pattern.compile(":(\\w+)"); + + protected static final Map units = new HashMap<>(); + + static { + units.put("year", Calendar.YEAR); + units.put("month", Calendar.MONTH); + units.put("day", Calendar.DAY_OF_MONTH); + units.put("hour", Calendar.HOUR_OF_DAY); + units.put("minute", Calendar.MINUTE); + units.put("second", Calendar.SECOND); + } + + protected Map params = new HashMap<>(); + + public TimeBetweenQueryMacroHandler() { + super(MACRO_PATTERN); + } + + @Override + public void setQueryParams(Map namedParameters) { + } + + @Override + public Map getParams() { + return params; + } + + @Override + public String replaceQueryParams(String queryString, Map params) { + Matcher matcher = MACRO_PATTERN.matcher(queryString); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String macros = matcher.group(0); + macros = replaceParamsInMacros(macros, params); + matcher.appendReplacement(sb, macros); + } + matcher.appendTail(sb); + return sb.toString(); + } + + protected String replaceParamsInMacros(String macros, Map params) { + Matcher matcher = QUERY_PARAM_PATTERN.matcher(macros); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String paramName = matcher.group(1); + if (params.containsKey(paramName)) { + matcher.appendReplacement(sb, params.get(paramName).toString()); + params.remove(paramName); + } + } + matcher.appendTail(sb); + return sb.toString(); + } + + @Override + protected String doExpand(String macro) { + count++; + String[] args = macro.split(","); + if (args.length != 4) + throw new RuntimeException("Invalid macro: " + macro); + + String field = args[0]; + String param1 = getParam(args, 1); + String param2 = getParam(args, 2); + + return String.format("(%s >= :%s and %s < :%s)", field, param1, field, param2); + } + + protected String getParam(String[] args, int idx) { + String arg = args[idx].trim(); + String unit = args[3].trim(); + + Matcher matcher = PARAM_PATTERN.matcher(arg); + if (!matcher.find()) + throw new RuntimeException("Invalid macro argument: " + arg); + + int num = 0; + try { + String expr = matcher.group(2); + if (!Strings.isNullOrEmpty(expr)) { + Scripting scripting = AppBeans.get(Scripting.class); + num = scripting.evaluateGroovy(expr, new Binding()); + } + } catch (NumberFormatException e) { + throw new RuntimeException("Invalid macro argument: " + arg, e); + } + + Date date = computeDate(num, unit); + + String paramName = args[0].trim().replace(".", "_") + "_" + count + "_" + idx; + params.put(paramName, date); + + return paramName; + } + + protected Date computeDate(int num, String unit) { + Calendar cal = Calendar.getInstance(); + cal.setTime(AppBeans.get(TimeSource.class).currentTimestamp()); + int calField = getCalendarField(unit); + if (num != 0) { + cal.add(calField, num); + } + return DateUtils.truncate(cal.getTime(), calField); + } + + protected int getCalendarField(String unit) { + Integer calField = (Integer) units.get(unit.toLowerCase()); + if (calField == null) + throw new RuntimeException("Invalid macro argument: " + unit); + return calField; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandler.java b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandler.java index 9b766589a9..93273ce8f8 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandler.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandler.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.TimeSource; -import org.apache.commons.lang.time.DateUtils; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -@Component("cuba_TimeTodayQueryMacroHandler") -@Scope("prototype") -public class TimeTodayQueryMacroHandler extends AbstractQueryMacroHandler { - - private static final Pattern MACRO_PATTERN = Pattern.compile("@today\\s*\\(([^\\)]+)\\)"); - - private int count; - private Map params = new HashMap<>(); - - public TimeTodayQueryMacroHandler() { - super(MACRO_PATTERN); - } - - @Override - public void setQueryParams(Map namedParameters) { - } - - @Override - public Map getParams() { - return params; - } - - @Override - public String replaceQueryParams(String queryString, Map params) { - return queryString; - } - - @Override - protected String doExpand(String macro) { - count++; - String param1 = macro.replace(".", "_") + "_" + count + "_1"; - String param2 = macro.replace(".", "_") + "_" + count + "_2"; - - Calendar cal = Calendar.getInstance(); - cal.setTime(AppBeans.get(TimeSource.class).currentTimestamp()); -// cal.setTime(new Date()); - params.put(param1, DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH)); - - cal.add(Calendar.DAY_OF_MONTH, 1); - params.put(param2, DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH)); - - return String.format("(%s >= :%s and %s < :%s)", macro, param1, macro, param2); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.TimeSource; +import org.apache.commons.lang.time.DateUtils; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +@Component("cuba_TimeTodayQueryMacroHandler") +@Scope("prototype") +public class TimeTodayQueryMacroHandler extends AbstractQueryMacroHandler { + + private static final Pattern MACRO_PATTERN = Pattern.compile("@today\\s*\\(([^\\)]+)\\)"); + + private int count; + private Map params = new HashMap<>(); + + public TimeTodayQueryMacroHandler() { + super(MACRO_PATTERN); + } + + @Override + public void setQueryParams(Map namedParameters) { + } + + @Override + public Map getParams() { + return params; + } + + @Override + public String replaceQueryParams(String queryString, Map params) { + return queryString; + } + + @Override + protected String doExpand(String macro) { + count++; + String param1 = macro.replace(".", "_") + "_" + count + "_1"; + String param2 = macro.replace(".", "_") + "_" + count + "_2"; + + Calendar cal = Calendar.getInstance(); + cal.setTime(AppBeans.get(TimeSource.class).currentTimestamp()); +// cal.setTime(new Date()); + params.put(param1, DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH)); + + cal.add(Calendar.DAY_OF_MONTH, 1); + params.put(param2, DateUtils.truncate(cal.getTime(), Calendar.DAY_OF_MONTH)); + + return String.format("(%s >= :%s and %s < :%s)", macro, param1, macro, param2); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationExecutor.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationExecutor.java index f0154c3cb2..d11a9f569a 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationExecutor.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationExecutor.java @@ -1,132 +1,132 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.core.sys.UserInvocationContext; -import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; -import com.haulmont.cuba.core.sys.remoting.discovery.StaticServerSelector; -import com.haulmont.cuba.security.app.TrustedClientService; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.UserSessionManager; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.remoting.support.RemoteInvocation; -import org.springframework.remoting.support.RemoteInvocationExecutor; - -import java.lang.reflect.InvocationTargetException; -import java.util.Locale; -import java.util.UUID; - -/** - * Executes {@link CubaRemoteInvocation} on middleware, setting and clearing a {@link SecurityContext} in the request - * handling thread. - */ -public class CubaRemoteInvocationExecutor implements RemoteInvocationExecutor { - - private final Logger log = LoggerFactory.getLogger(CubaRemoteInvocationExecutor.class); - - protected volatile ServerSelector serverSelector; - - protected UserSessionManager userSessionManager; - protected Configuration configuration; - protected GlobalConfig globalConfig; - - public CubaRemoteInvocationExecutor() { - userSessionManager = AppBeans.get(UserSessionManager.NAME); - configuration = AppBeans.get(Configuration.NAME); - globalConfig = configuration.getConfig(GlobalConfig.class); - } - - @Override - public Object invoke(RemoteInvocation invocation, Object targetObject) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (invocation instanceof CubaRemoteInvocation) { - CubaRemoteInvocation cubaInvocation = (CubaRemoteInvocation) invocation; - - UUID sessionId = cubaInvocation.getSessionId(); - if (sessionId != null) { - UserSession session = userSessionManager.findSession(sessionId); - if (session == null) { - ServerConfig serverConfig = configuration.getConfig(ServerConfig.class); - String sessionProviderUrl = serverConfig.getUserSessionProviderUrl(); - if (StringUtils.isNotBlank(sessionProviderUrl)) { - log.debug("User session {} not found, trying to get it from {}", sessionId, sessionProviderUrl); - try { - HttpServiceProxy proxyFactory = new HttpServiceProxy(getServerSelector(sessionProviderUrl)); - proxyFactory.setServiceUrl("cuba_TrustedClientService"); - proxyFactory.setServiceInterface(TrustedClientService.class); - proxyFactory.afterPropertiesSet(); - TrustedClientService trustedClientService = (TrustedClientService) proxyFactory.getObject(); - if (trustedClientService != null) { - UserSession userSession = trustedClientService.findSession(serverConfig.getTrustedClientPassword(), sessionId); - if (userSession != null) { - userSessionManager.storeSession(userSession); - } else { - log.debug("User session {} not found on {}", sessionId, sessionProviderUrl); - } - } - } catch (Exception e) { - log.error("Error getting user session from {}", sessionProviderUrl, e); - } - } - } - AppContext.setSecurityContext(new SecurityContext(sessionId)); - } - - if (cubaInvocation.getLocale() != null) { - Locale requestLocale = Locale.forLanguageTag(cubaInvocation.getLocale()); - if (!globalConfig.getAvailableLocales().containsValue(requestLocale)) { - requestLocale = null; - } - - UserInvocationContext.setRequestScopeInfo(sessionId, requestLocale, cubaInvocation.getTimeZone(), - cubaInvocation.getAddress(), cubaInvocation.getClientInfo()); - } - } - - Object result; - try { - result = invocation.invoke(targetObject); - } finally { - AppContext.setSecurityContext(null); - UserInvocationContext.clearRequestScopeInfo(); - } - - return result; - } - - protected ServerSelector getServerSelector(String sessionProviderUrl) { - if (serverSelector == null) { - synchronized (this) { - if (serverSelector == null) { - StaticServerSelector result = new StaticServerSelector(); - result.setBaseUrl(sessionProviderUrl); - result.init(); - serverSelector = result; - } - } - } - return serverSelector; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.core.sys.UserInvocationContext; +import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; +import com.haulmont.cuba.core.sys.remoting.discovery.StaticServerSelector; +import com.haulmont.cuba.security.app.TrustedClientService; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.UserSessionManager; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.remoting.support.RemoteInvocation; +import org.springframework.remoting.support.RemoteInvocationExecutor; + +import java.lang.reflect.InvocationTargetException; +import java.util.Locale; +import java.util.UUID; + +/** + * Executes {@link CubaRemoteInvocation} on middleware, setting and clearing a {@link SecurityContext} in the request + * handling thread. + */ +public class CubaRemoteInvocationExecutor implements RemoteInvocationExecutor { + + private final Logger log = LoggerFactory.getLogger(CubaRemoteInvocationExecutor.class); + + protected volatile ServerSelector serverSelector; + + protected UserSessionManager userSessionManager; + protected Configuration configuration; + protected GlobalConfig globalConfig; + + public CubaRemoteInvocationExecutor() { + userSessionManager = AppBeans.get(UserSessionManager.NAME); + configuration = AppBeans.get(Configuration.NAME); + globalConfig = configuration.getConfig(GlobalConfig.class); + } + + @Override + public Object invoke(RemoteInvocation invocation, Object targetObject) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + if (invocation instanceof CubaRemoteInvocation) { + CubaRemoteInvocation cubaInvocation = (CubaRemoteInvocation) invocation; + + UUID sessionId = cubaInvocation.getSessionId(); + if (sessionId != null) { + UserSession session = userSessionManager.findSession(sessionId); + if (session == null) { + ServerConfig serverConfig = configuration.getConfig(ServerConfig.class); + String sessionProviderUrl = serverConfig.getUserSessionProviderUrl(); + if (StringUtils.isNotBlank(sessionProviderUrl)) { + log.debug("User session {} not found, trying to get it from {}", sessionId, sessionProviderUrl); + try { + HttpServiceProxy proxyFactory = new HttpServiceProxy(getServerSelector(sessionProviderUrl)); + proxyFactory.setServiceUrl("cuba_TrustedClientService"); + proxyFactory.setServiceInterface(TrustedClientService.class); + proxyFactory.afterPropertiesSet(); + TrustedClientService trustedClientService = (TrustedClientService) proxyFactory.getObject(); + if (trustedClientService != null) { + UserSession userSession = trustedClientService.findSession(serverConfig.getTrustedClientPassword(), sessionId); + if (userSession != null) { + userSessionManager.storeSession(userSession); + } else { + log.debug("User session {} not found on {}", sessionId, sessionProviderUrl); + } + } + } catch (Exception e) { + log.error("Error getting user session from {}", sessionProviderUrl, e); + } + } + } + AppContext.setSecurityContext(new SecurityContext(sessionId)); + } + + if (cubaInvocation.getLocale() != null) { + Locale requestLocale = Locale.forLanguageTag(cubaInvocation.getLocale()); + if (!globalConfig.getAvailableLocales().containsValue(requestLocale)) { + requestLocale = null; + } + + UserInvocationContext.setRequestScopeInfo(sessionId, requestLocale, cubaInvocation.getTimeZone(), + cubaInvocation.getAddress(), cubaInvocation.getClientInfo()); + } + } + + Object result; + try { + result = invocation.invoke(targetObject); + } finally { + AppContext.setSecurityContext(null); + UserInvocationContext.clearRequestScopeInfo(); + } + + return result; + } + + protected ServerSelector getServerSelector(String sessionProviderUrl) { + if (serverSelector == null) { + synchronized (this) { + if (serverSelector == null) { + StaticServerSelector result = new StaticServerSelector(); + result.setBaseUrl(sessionProviderUrl); + result.init(); + serverSelector = result; + } + } + } + return serverSelector; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/HttpServiceExporter.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/HttpServiceExporter.java index b41c87ac6d..3f0df775c7 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/HttpServiceExporter.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/HttpServiceExporter.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.serialization.SerializationSupport; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; -import org.springframework.remoting.support.RemoteInvocation; -import org.springframework.remoting.support.RemoteInvocationResult; -import org.springframework.web.util.NestedServletException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OptionalDataException; - -/** - * Exports a middleware service bean as an HTTP invoker service endpoint. - * - */ -public class HttpServiceExporter extends HttpInvokerServiceExporter implements BeanNameAware { - - public HttpServiceExporter() { - super(); - setRegisterTraceInterceptor(false); - setRemoteInvocationExecutor(new CubaRemoteInvocationExecutor()); - } - - @Override - public void setService(Object service) { - super.setService(service); - } - - @Override - public void setBeanName(String name) { - Object service = getService(); - if (service == null) - throw new IllegalStateException("Target service is null"); - - String entryName = AppContext.getProperty("cuba.webContextName") + name; - - LocalServiceInvoker invoker = new LocalServiceInvokerImpl(service); - LocalServiceDirectory.registerInvoker(entryName, invoker); - } - - /* - * In base implementation, exceptions which are thrown during reading remote invocation request, are not handled. - * Client gets useless HTTP status 500 in this case. - * - * This implementation passes some known exceptions to client. - */ - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - try { - RemoteInvocationResult result; - try { - RemoteInvocation invocation = readRemoteInvocation(request); - result = invokeAndCreateResult(invocation, getProxy()); - } catch (OptionalDataException | ClassCastException e) { // typical binary incompatibility exceptions - logger.error("Failed to read remote invocation request", e); - result = new RemoteInvocationResult(e); - } - - writeRemoteInvocationResult(request, response, result); - } catch (ClassNotFoundException ex) { - throw new NestedServletException("Class not found during deserialization", ex); - } - } - - @Override - protected void doWriteRemoteInvocationResult(RemoteInvocationResult result, ObjectOutputStream oos) throws IOException { - SerializationSupport.serialize(result, oos); - } - - @Override - protected RemoteInvocation doReadRemoteInvocation(ObjectInputStream ois) throws IOException, ClassNotFoundException { - return (RemoteInvocation) SerializationSupport.deserialize(ois); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.serialization.SerializationSupport; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; +import org.springframework.remoting.support.RemoteInvocation; +import org.springframework.remoting.support.RemoteInvocationResult; +import org.springframework.web.util.NestedServletException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OptionalDataException; + +/** + * Exports a middleware service bean as an HTTP invoker service endpoint. + * + */ +public class HttpServiceExporter extends HttpInvokerServiceExporter implements BeanNameAware { + + public HttpServiceExporter() { + super(); + setRegisterTraceInterceptor(false); + setRemoteInvocationExecutor(new CubaRemoteInvocationExecutor()); + } + + @Override + public void setService(Object service) { + super.setService(service); + } + + @Override + public void setBeanName(String name) { + Object service = getService(); + if (service == null) + throw new IllegalStateException("Target service is null"); + + String entryName = AppContext.getProperty("cuba.webContextName") + name; + + LocalServiceInvoker invoker = new LocalServiceInvokerImpl(service); + LocalServiceDirectory.registerInvoker(entryName, invoker); + } + + /* + * In base implementation, exceptions which are thrown during reading remote invocation request, are not handled. + * Client gets useless HTTP status 500 in this case. + * + * This implementation passes some known exceptions to client. + */ + @Override + public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + try { + RemoteInvocationResult result; + try { + RemoteInvocation invocation = readRemoteInvocation(request); + result = invokeAndCreateResult(invocation, getProxy()); + } catch (OptionalDataException | ClassCastException e) { // typical binary incompatibility exceptions + logger.error("Failed to read remote invocation request", e); + result = new RemoteInvocationResult(e); + } + + writeRemoteInvocationResult(request, response, result); + } catch (ClassNotFoundException ex) { + throw new NestedServletException("Class not found during deserialization", ex); + } + } + + @Override + protected void doWriteRemoteInvocationResult(RemoteInvocationResult result, ObjectOutputStream oos) throws IOException { + SerializationSupport.serialize(result, oos); + } + + @Override + protected RemoteInvocation doReadRemoteInvocation(ObjectInputStream ois) throws IOException, ClassNotFoundException { + return (RemoteInvocation) SerializationSupport.deserialize(ois); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeServiceBean.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeServiceBean.java index a886384c9e..0e0eeb7298 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeServiceBean.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.app.FileStorageAPI; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; -import org.springframework.stereotype.Service; - -import javax.inject.Inject; -import java.io.InputStream; - -@Service(LocalFileExchangeService.NAME) -public class LocalFileExchangeServiceBean implements LocalFileExchangeService { - @Inject - protected FileStorageAPI fileStorage; - - @Override - public void uploadFile(InputStream inputStream, FileDescriptor fileDescriptor) throws FileStorageException { - fileStorage.saveStream(fileDescriptor, inputStream); - } - - @Override - public InputStream downloadFile(FileDescriptor fileDescriptor) throws FileStorageException { - return fileStorage.openStream(fileDescriptor); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.app.FileStorageAPI; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.io.InputStream; + +@Service(LocalFileExchangeService.NAME) +public class LocalFileExchangeServiceBean implements LocalFileExchangeService { + @Inject + protected FileStorageAPI fileStorage; + + @Override + public void uploadFile(InputStream inputStream, FileDescriptor fileDescriptor) throws FileStorageException { + fileStorage.saveStream(fileDescriptor, inputStream); + } + + @Override + public InputStream downloadFile(FileDescriptor fileDescriptor) throws FileStorageException { + return fileStorage.openStream(fileDescriptor); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalServiceInvokerImpl.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalServiceInvokerImpl.java index 4906d2345a..6fe74421e9 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalServiceInvokerImpl.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/LocalServiceInvokerImpl.java @@ -1,113 +1,113 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.core.sys.UserInvocationContext; -import com.haulmont.cuba.core.sys.serialization.SerializationSupport; -import org.apache.commons.lang.ClassUtils; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Locale; - -public class LocalServiceInvokerImpl implements LocalServiceInvoker { - - private Object target; - - public LocalServiceInvokerImpl(Object target) { - if (target == null) { - throw new IllegalArgumentException("Target object is null"); - } - - this.target = target; - } - - @Override - public LocalServiceInvocationResult invoke(LocalServiceInvocation invocation) { - if (invocation == null) { - throw new IllegalArgumentException("Invocation is null"); - } - - LocalServiceInvocationResult result = new LocalServiceInvocationResult(); - ClassLoader clientClassLoader = Thread.currentThread().getContextClassLoader(); - try { - ClassLoader classLoader = target.getClass().getClassLoader(); - Thread.currentThread().setContextClassLoader(classLoader); - - String[] parameterTypeNames = invocation.getParameterTypeNames(); - Class[] parameterTypes = new Class[parameterTypeNames.length]; - for (int i = 0; i < parameterTypeNames.length; i++) { - Class paramClass = ClassUtils.getClass(classLoader, parameterTypeNames[i]); - parameterTypes[i] = paramClass; - } - - byte[][] argumentsData = invocation.getArgumentsData(); - Object[] notSerializableArguments = invocation.getNotSerializableArguments(); - Object[] arguments; - if (argumentsData == null) { - arguments = null; - } else { - arguments = new Object[argumentsData.length]; - for (int i = 0; i < argumentsData.length; i++) { - if (argumentsData[i] == null) { - if (notSerializableArguments[i] == null) { - arguments[i] = null; - } else { - arguments[i] = notSerializableArguments[i]; - } - } else { - arguments[i] = SerializationSupport.deserialize(argumentsData[i]); - } - } - } - - SecurityContext targetSecurityContext = null; - if (invocation.getSessionId() != null) { - targetSecurityContext = new SecurityContext(invocation.getSessionId()); - } - AppContext.setSecurityContext(targetSecurityContext); - - if (invocation.getLocale() != null) { - Locale locale = Locale.forLanguageTag(invocation.getLocale()); - UserInvocationContext.setRequestScopeInfo(invocation.getSessionId(), locale, invocation.getTimeZone(), - invocation.getAddress(), invocation.getClientInfo()); - } - - Method method = target.getClass().getMethod(invocation.getMethodName(), parameterTypes); - Object data = method.invoke(target, arguments); - - if (invocation.canResultBypassSerialization()) { - result.setNotSerializableData(data); - } else { - result.setData(SerializationSupport.serialize(data)); - } - return result; - } catch (Throwable t) { - if (t instanceof InvocationTargetException) - t = ((InvocationTargetException) t).getTargetException(); - result.setException(SerializationSupport.serialize(t)); - return result; - } finally { - Thread.currentThread().setContextClassLoader(clientClassLoader); - AppContext.setSecurityContext(null); - UserInvocationContext.clearRequestScopeInfo(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.core.sys.UserInvocationContext; +import com.haulmont.cuba.core.sys.serialization.SerializationSupport; +import org.apache.commons.lang.ClassUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Locale; + +public class LocalServiceInvokerImpl implements LocalServiceInvoker { + + private Object target; + + public LocalServiceInvokerImpl(Object target) { + if (target == null) { + throw new IllegalArgumentException("Target object is null"); + } + + this.target = target; + } + + @Override + public LocalServiceInvocationResult invoke(LocalServiceInvocation invocation) { + if (invocation == null) { + throw new IllegalArgumentException("Invocation is null"); + } + + LocalServiceInvocationResult result = new LocalServiceInvocationResult(); + ClassLoader clientClassLoader = Thread.currentThread().getContextClassLoader(); + try { + ClassLoader classLoader = target.getClass().getClassLoader(); + Thread.currentThread().setContextClassLoader(classLoader); + + String[] parameterTypeNames = invocation.getParameterTypeNames(); + Class[] parameterTypes = new Class[parameterTypeNames.length]; + for (int i = 0; i < parameterTypeNames.length; i++) { + Class paramClass = ClassUtils.getClass(classLoader, parameterTypeNames[i]); + parameterTypes[i] = paramClass; + } + + byte[][] argumentsData = invocation.getArgumentsData(); + Object[] notSerializableArguments = invocation.getNotSerializableArguments(); + Object[] arguments; + if (argumentsData == null) { + arguments = null; + } else { + arguments = new Object[argumentsData.length]; + for (int i = 0; i < argumentsData.length; i++) { + if (argumentsData[i] == null) { + if (notSerializableArguments[i] == null) { + arguments[i] = null; + } else { + arguments[i] = notSerializableArguments[i]; + } + } else { + arguments[i] = SerializationSupport.deserialize(argumentsData[i]); + } + } + } + + SecurityContext targetSecurityContext = null; + if (invocation.getSessionId() != null) { + targetSecurityContext = new SecurityContext(invocation.getSessionId()); + } + AppContext.setSecurityContext(targetSecurityContext); + + if (invocation.getLocale() != null) { + Locale locale = Locale.forLanguageTag(invocation.getLocale()); + UserInvocationContext.setRequestScopeInfo(invocation.getSessionId(), locale, invocation.getTimeZone(), + invocation.getAddress(), invocation.getClientInfo()); + } + + Method method = target.getClass().getMethod(invocation.getMethodName(), parameterTypes); + Object data = method.invoke(target, arguments); + + if (invocation.canResultBypassSerialization()) { + result.setNotSerializableData(data); + } else { + result.setData(SerializationSupport.serialize(data)); + } + return result; + } catch (Throwable t) { + if (t instanceof InvocationTargetException) + t = ((InvocationTargetException) t).getTargetException(); + result.setException(SerializationSupport.serialize(t)); + return result; + } finally { + Thread.currentThread().setContextClassLoader(clientClassLoader); + AppContext.setSecurityContext(null); + UserInvocationContext.clearRequestScopeInfo(); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteClientInfo.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteClientInfo.java index b309ce0450..551a040c6b 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteClientInfo.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteClientInfo.java @@ -1,67 +1,67 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -/** - * Information about remote invocation client. - * - */ -public class RemoteClientInfo { - - private String host; - private Integer port; - private String address; - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - private static final ThreadLocal clientInfo = new ThreadLocal<>(); - - public static RemoteClientInfo get() { - return clientInfo.get(); - } - - public static void set(RemoteClientInfo info) { - clientInfo.set(info); - } - - public static void clear() { - clientInfo.set(null); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +/** + * Information about remote invocation client. + * + */ +public class RemoteClientInfo { + + private String host; + private Integer port; + private String address; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + private static final ThreadLocal clientInfo = new ThreadLocal<>(); + + public static RemoteClientInfo get() { + return clientInfo.get(); + } + + public static void set(RemoteClientInfo info) { + clientInfo.set(info); + } + + public static void clear() { + clientInfo.set(null); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteServicesBeanCreator.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteServicesBeanCreator.java index 3f23b0ac8d..2078e9434a 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteServicesBeanCreator.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemoteServicesBeanCreator.java @@ -1,103 +1,103 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import org.apache.commons.lang.ClassUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class RemoteServicesBeanCreator implements BeanFactoryPostProcessor, ApplicationContextAware { - - private Logger log = LoggerFactory.getLogger(RemoteServicesBeanCreator.class); - - private ApplicationContext context; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.context = applicationContext; - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - log.info("Configuring remote services"); - - BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; - - ApplicationContext coreContext = context.getParent(); - Map services = coreContext.getBeansWithAnnotation(Service.class); - for (Map.Entry entry : services.entrySet()) { - String serviceName = entry.getKey(); - Object service = entry.getValue(); - - List serviceInterfaces = new ArrayList<>(); - List interfaces = ClassUtils.getAllInterfaces(service.getClass()); - for (Class intf : interfaces) { - if (intf.getName().endsWith("Service")) - serviceInterfaces.add(intf); - } - String intfName = null; - if (serviceInterfaces.size() == 0) { - log.error("Bean " + serviceName + " has @Service annotation but no interfaces named '*Service'. Ignoring it."); - } else if (serviceInterfaces.size() > 1) { - intfName = findLowestSubclassName(serviceInterfaces); - if (intfName == null) - log.error("Bean " + serviceName + " has @Service annotation and more than one interface named '*Service', " + - "but these interfaces are not from the same hierarchy. Ignoring it."); - } else { - intfName = serviceInterfaces.get(0).getName(); - } - if (intfName != null) { - BeanDefinition definition = new RootBeanDefinition(HttpServiceExporter.class); - MutablePropertyValues propertyValues = definition.getPropertyValues(); - propertyValues.add("service", service); - propertyValues.add("serviceInterface", intfName); - registry.registerBeanDefinition("/" + serviceName, definition); - log.debug("Bean " + serviceName + " configured for export via HTTP"); - } - } - } - - @Nullable - protected String findLowestSubclassName(List interfaces) { - outer: - for (Class intf : interfaces) { - for (Class other : interfaces) { - if (intf != other && !other.isAssignableFrom(intf)) { - continue outer; - } - } - return intf.getName(); - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import org.apache.commons.lang.ClassUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class RemoteServicesBeanCreator implements BeanFactoryPostProcessor, ApplicationContextAware { + + private Logger log = LoggerFactory.getLogger(RemoteServicesBeanCreator.class); + + private ApplicationContext context; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.context = applicationContext; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + log.info("Configuring remote services"); + + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + + ApplicationContext coreContext = context.getParent(); + Map services = coreContext.getBeansWithAnnotation(Service.class); + for (Map.Entry entry : services.entrySet()) { + String serviceName = entry.getKey(); + Object service = entry.getValue(); + + List serviceInterfaces = new ArrayList<>(); + List interfaces = ClassUtils.getAllInterfaces(service.getClass()); + for (Class intf : interfaces) { + if (intf.getName().endsWith("Service")) + serviceInterfaces.add(intf); + } + String intfName = null; + if (serviceInterfaces.size() == 0) { + log.error("Bean " + serviceName + " has @Service annotation but no interfaces named '*Service'. Ignoring it."); + } else if (serviceInterfaces.size() > 1) { + intfName = findLowestSubclassName(serviceInterfaces); + if (intfName == null) + log.error("Bean " + serviceName + " has @Service annotation and more than one interface named '*Service', " + + "but these interfaces are not from the same hierarchy. Ignoring it."); + } else { + intfName = serviceInterfaces.get(0).getName(); + } + if (intfName != null) { + BeanDefinition definition = new RootBeanDefinition(HttpServiceExporter.class); + MutablePropertyValues propertyValues = definition.getPropertyValues(); + propertyValues.add("service", service); + propertyValues.add("serviceInterface", intfName); + registry.registerBeanDefinition("/" + serviceName, definition); + log.debug("Bean " + serviceName + " configured for export via HTTP"); + } + } + } + + @Nullable + protected String findLowestSubclassName(List interfaces) { + outer: + for (Class intf : interfaces) { + for (Class other : interfaces) { + if (intf != other && !other.isAssignableFrom(intf)) { + continue outer; + } + } + return intf.getName(); + } + return null; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemotingServlet.java b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemotingServlet.java index 91d0cc986e..671cf6815a 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemotingServlet.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/remoting/RemotingServlet.java @@ -1,177 +1,177 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.CubaXmlWebApplicationContext; -import com.haulmont.cuba.core.sys.RemotingContextHolder; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.util.ResourceUtils; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; - -public class RemotingServlet extends DispatcherServlet { - - private static final long serialVersionUID = 4142366570614871805L; - - public static final String SPRING_CONTEXT_CONFIG = "cuba.remotingSpringContextConfig"; - - private static final Logger log = LoggerFactory.getLogger(RemotingServlet.class); - - private volatile boolean checkCompleted; - - /* - The field is used to prevent double initialization of the servlet. - Double initialization might occur during single WAR deployment when we call the method from initializer. - */ - protected volatile boolean initialized = false; - - @Override - public String getContextConfigLocation() { - String configProperty = AppContext.getProperty(SPRING_CONTEXT_CONFIG); - if (StringUtils.isBlank(configProperty)) { - throw new IllegalStateException("Missing " + SPRING_CONTEXT_CONFIG + " application property"); - } - File baseDir = new File(AppContext.getProperty("cuba.confDir")); - - StrTokenizer tokenizer = new StrTokenizer(configProperty); - String[] tokenArray = tokenizer.getTokenArray(); - StringBuilder locations = new StringBuilder(); - for (String token : tokenArray) { - String location; - if (ResourceUtils.isUrl(token)) { - location = token; - } else { - if (token.startsWith("/")) - token = token.substring(1); - File file = new File(baseDir, token); - if (file.exists()) { - location = file.toURI().toString(); - } else { - location = "classpath:" + token; - } - } - locations.append(location).append(" "); - } - return locations.toString(); - } - - @Override - protected WebApplicationContext initWebApplicationContext() { - WebApplicationContext wac = findWebApplicationContext(); - if (wac == null) { - ApplicationContext parent = AppContext.getApplicationContext(); - wac = createWebApplicationContext(parent); - } - - onRefresh(wac); - - // Publish the context as a servlet context attribute. - String attrName = getServletContextAttributeName(); - getServletContext().setAttribute(attrName, wac); - if (this.logger.isDebugEnabled()) { - this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + - "' as ServletContext attribute with name [" + attrName + "]"); - } - - RemotingContextHolder.setRemotingApplicationContext(wac); - - LocalServiceDirectory.start(); - - return wac; - } - - @Override - protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { - if (!checkCompleted) { - // Check correctness of some configuration parameters and log the warning if necesary - Configuration configuration = AppBeans.get(Configuration.NAME); - GlobalConfig config = configuration.getConfig(GlobalConfig.class); - StringBuilder sb = new StringBuilder(); - if (!request.getServerName().equals(config.getWebHostName())) { - sb.append("***** cuba.webHostName=").append(config.getWebHostName()) - .append(", actual=").append(request.getServerName()).append("\n"); - } - if (request.getServerPort() != Integer.parseInt(config.getWebPort())) { - sb.append("***** cuba.webPort=").append(config.getWebPort()) - .append(", actual=").append(request.getServerPort()).append("\n"); - } - String contextPath = request.getContextPath(); - if (contextPath.startsWith("/")) - contextPath = contextPath.substring(1); - if (!contextPath.equals(config.getWebContextName())) { - sb.append("***** cuba.webContextName=").append(config.getWebContextName()) - .append(", actual=").append(contextPath).append("\n"); - } - if (sb.length() > 0) { - sb.insert(0, "\n*****\n"); - sb.append("*****"); - log.warn(" Invalid configuration parameters that may cause problems:" + - sb.toString() - ); - } - checkCompleted = true; - } - - RemoteClientInfo remoteClientInfo = new RemoteClientInfo(); - remoteClientInfo.setAddress(request.getRemoteAddr()); - remoteClientInfo.setHost(request.getRemoteHost()); - remoteClientInfo.setPort(request.getRemotePort()); - - RemoteClientInfo.set(remoteClientInfo); - try { - super.doService(request, response); - } finally { - RemoteClientInfo.clear(); - } - } - - @Override - protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, - Object handler, Exception ex) throws Exception { - log.error("Error processing request", ex); - return super.processHandlerException(request, response, handler, ex); - } - - @Override - public void init(ServletConfig config) throws ServletException { - if (!initialized) { - super.init(config); - initialized = true; - } - } - - @Override - public Class getContextClass() { - return CubaXmlWebApplicationContext.class; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.CubaXmlWebApplicationContext; +import com.haulmont.cuba.core.sys.RemotingContextHolder; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.util.ResourceUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; + +public class RemotingServlet extends DispatcherServlet { + + private static final long serialVersionUID = 4142366570614871805L; + + public static final String SPRING_CONTEXT_CONFIG = "cuba.remotingSpringContextConfig"; + + private static final Logger log = LoggerFactory.getLogger(RemotingServlet.class); + + private volatile boolean checkCompleted; + + /* + The field is used to prevent double initialization of the servlet. + Double initialization might occur during single WAR deployment when we call the method from initializer. + */ + protected volatile boolean initialized = false; + + @Override + public String getContextConfigLocation() { + String configProperty = AppContext.getProperty(SPRING_CONTEXT_CONFIG); + if (StringUtils.isBlank(configProperty)) { + throw new IllegalStateException("Missing " + SPRING_CONTEXT_CONFIG + " application property"); + } + File baseDir = new File(AppContext.getProperty("cuba.confDir")); + + StrTokenizer tokenizer = new StrTokenizer(configProperty); + String[] tokenArray = tokenizer.getTokenArray(); + StringBuilder locations = new StringBuilder(); + for (String token : tokenArray) { + String location; + if (ResourceUtils.isUrl(token)) { + location = token; + } else { + if (token.startsWith("/")) + token = token.substring(1); + File file = new File(baseDir, token); + if (file.exists()) { + location = file.toURI().toString(); + } else { + location = "classpath:" + token; + } + } + locations.append(location).append(" "); + } + return locations.toString(); + } + + @Override + protected WebApplicationContext initWebApplicationContext() { + WebApplicationContext wac = findWebApplicationContext(); + if (wac == null) { + ApplicationContext parent = AppContext.getApplicationContext(); + wac = createWebApplicationContext(parent); + } + + onRefresh(wac); + + // Publish the context as a servlet context attribute. + String attrName = getServletContextAttributeName(); + getServletContext().setAttribute(attrName, wac); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + + "' as ServletContext attribute with name [" + attrName + "]"); + } + + RemotingContextHolder.setRemotingApplicationContext(wac); + + LocalServiceDirectory.start(); + + return wac; + } + + @Override + protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { + if (!checkCompleted) { + // Check correctness of some configuration parameters and log the warning if necesary + Configuration configuration = AppBeans.get(Configuration.NAME); + GlobalConfig config = configuration.getConfig(GlobalConfig.class); + StringBuilder sb = new StringBuilder(); + if (!request.getServerName().equals(config.getWebHostName())) { + sb.append("***** cuba.webHostName=").append(config.getWebHostName()) + .append(", actual=").append(request.getServerName()).append("\n"); + } + if (request.getServerPort() != Integer.parseInt(config.getWebPort())) { + sb.append("***** cuba.webPort=").append(config.getWebPort()) + .append(", actual=").append(request.getServerPort()).append("\n"); + } + String contextPath = request.getContextPath(); + if (contextPath.startsWith("/")) + contextPath = contextPath.substring(1); + if (!contextPath.equals(config.getWebContextName())) { + sb.append("***** cuba.webContextName=").append(config.getWebContextName()) + .append(", actual=").append(contextPath).append("\n"); + } + if (sb.length() > 0) { + sb.insert(0, "\n*****\n"); + sb.append("*****"); + log.warn(" Invalid configuration parameters that may cause problems:" + + sb.toString() + ); + } + checkCompleted = true; + } + + RemoteClientInfo remoteClientInfo = new RemoteClientInfo(); + remoteClientInfo.setAddress(request.getRemoteAddr()); + remoteClientInfo.setHost(request.getRemoteHost()); + remoteClientInfo.setPort(request.getRemotePort()); + + RemoteClientInfo.set(remoteClientInfo); + try { + super.doService(request, response); + } finally { + RemoteClientInfo.clear(); + } + } + + @Override + protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, + Object handler, Exception ex) throws Exception { + log.error("Error processing request", ex); + return super.processHandlerException(request, response, handler, ex); + } + + @Override + public void init(ServletConfig config) throws ServletException { + if (!initialized) { + super.init(config); + initialized = true; + } + } + + @Override + public Class getContextClass() { + return CubaXmlWebApplicationContext.class; + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreContextLoader.java b/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreContextLoader.java index d89a502012..46446872d9 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreContextLoader.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreContextLoader.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.singleapp; - -import com.google.common.base.Splitter; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.AppContextLoader; -import com.haulmont.cuba.core.sys.CubaCoreApplicationContext; -import com.haulmont.cuba.core.sys.SingleAppResourcePatternResolver; -import com.haulmont.cuba.core.sys.remoting.RemotingServlet; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.core.io.support.ResourcePatternResolver; - -import javax.servlet.*; -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Set; - -/** - * {@link AppContext} loader of the middleware application block packed in a WAR together with the web block. - */ -public class SingleAppCoreContextLoader extends AppContextLoader { - - private Set dependencyJars; - - /** - * Invoked reflectively by {@link SingleAppCoreServletListener}. - * @param jarNames JARs of the core block - */ - @SuppressWarnings("unused") - public void setJarNames(String jarNames) { - dependencyJars = new HashSet<>(Splitter.on("\n").omitEmptyStrings().trimResults().splitToList(jarNames)); - } - - /** - * Here we create servlets and filters manually, to make sure the classes would be loaded using necessary classloader. - */ - @Override - public void contextInitialized(ServletContextEvent servletContextEvent) { - super.contextInitialized(servletContextEvent); - - ServletContext servletContext = servletContextEvent.getServletContext(); - RemotingServlet remotingServlet = new RemotingServlet(); - try { - remotingServlet.init(new CubaServletConfig("remoting", servletContext)); - } catch (ServletException e) { - throw new RuntimeException("An error occurred while initializing remoting servlet", e); - } - ServletRegistration.Dynamic remotingReg = servletContext.addServlet("remoting", remotingServlet); - remotingReg.addMapping("/remoting/*"); - remotingReg.setLoadOnStartup(0); - - FilterRegistration.Dynamic filterReg = servletContext.addFilter("CoreSingleWarHttpFilter", new SetClassLoaderFilter()); - filterReg.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/remoting/*"); - } - - @Override - protected ClassPathXmlApplicationContext createApplicationContext(String[] locations) { - return new CubaCoreApplicationContext(locations) { - /** - * Here we create resource resolver which scans only core jars (and avoid putting web beans to core context) - * JAR_DEPENDENCIES properties is filled by com.haulmont.cuba.core.sys.singleapp.SingleAppCoreServletListener - * during application initialization. - */ - @Override - protected ResourcePatternResolver getResourcePatternResolver() { - if (dependencyJars == null || dependencyJars.isEmpty()) { - throw new RuntimeException("No JARs defined for the 'core' block. " + - "Please check that core.dependencies file exists in WEB-INF directory."); - } - return new SingleAppResourcePatternResolver(this, dependencyJars); - } - }; - } - - @Override - protected String getAppPropertiesConfig(ServletContext sc) { - return sc.getInitParameter("appPropertiesConfigCore"); - } - - protected static class SetClassLoaderFilter implements Filter { - @Override - public void init(FilterConfig filterConfig) throws ServletException { - //do nothing - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - chain.doFilter(request, response); - } - - @Override - public void destroy() { - //do nothing - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.singleapp; + +import com.google.common.base.Splitter; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.AppContextLoader; +import com.haulmont.cuba.core.sys.CubaCoreApplicationContext; +import com.haulmont.cuba.core.sys.SingleAppResourcePatternResolver; +import com.haulmont.cuba.core.sys.remoting.RemotingServlet; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.support.ResourcePatternResolver; + +import javax.servlet.*; +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +/** + * {@link AppContext} loader of the middleware application block packed in a WAR together with the web block. + */ +public class SingleAppCoreContextLoader extends AppContextLoader { + + private Set dependencyJars; + + /** + * Invoked reflectively by {@link SingleAppCoreServletListener}. + * @param jarNames JARs of the core block + */ + @SuppressWarnings("unused") + public void setJarNames(String jarNames) { + dependencyJars = new HashSet<>(Splitter.on("\n").omitEmptyStrings().trimResults().splitToList(jarNames)); + } + + /** + * Here we create servlets and filters manually, to make sure the classes would be loaded using necessary classloader. + */ + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + super.contextInitialized(servletContextEvent); + + ServletContext servletContext = servletContextEvent.getServletContext(); + RemotingServlet remotingServlet = new RemotingServlet(); + try { + remotingServlet.init(new CubaServletConfig("remoting", servletContext)); + } catch (ServletException e) { + throw new RuntimeException("An error occurred while initializing remoting servlet", e); + } + ServletRegistration.Dynamic remotingReg = servletContext.addServlet("remoting", remotingServlet); + remotingReg.addMapping("/remoting/*"); + remotingReg.setLoadOnStartup(0); + + FilterRegistration.Dynamic filterReg = servletContext.addFilter("CoreSingleWarHttpFilter", new SetClassLoaderFilter()); + filterReg.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/remoting/*"); + } + + @Override + protected ClassPathXmlApplicationContext createApplicationContext(String[] locations) { + return new CubaCoreApplicationContext(locations) { + /** + * Here we create resource resolver which scans only core jars (and avoid putting web beans to core context) + * JAR_DEPENDENCIES properties is filled by com.haulmont.cuba.core.sys.singleapp.SingleAppCoreServletListener + * during application initialization. + */ + @Override + protected ResourcePatternResolver getResourcePatternResolver() { + if (dependencyJars == null || dependencyJars.isEmpty()) { + throw new RuntimeException("No JARs defined for the 'core' block. " + + "Please check that core.dependencies file exists in WEB-INF directory."); + } + return new SingleAppResourcePatternResolver(this, dependencyJars); + } + }; + } + + @Override + protected String getAppPropertiesConfig(ServletContext sc) { + return sc.getInitParameter("appPropertiesConfigCore"); + } + + protected static class SetClassLoaderFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + //do nothing + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + //do nothing + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreServletListener.java b/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreServletListener.java index cf88ededc7..172499e590 100644 --- a/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreServletListener.java +++ b/modules/core/src/com/haulmont/cuba/core/sys/singleapp/SingleAppCoreServletListener.java @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.singleapp; - -import com.haulmont.cuba.core.sys.CubaSingleAppClassLoader; -import org.apache.commons.io.IOUtils; -import org.springframework.util.ReflectionUtils; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; - -/** - * This class and its twin com.haulmont.cuba.web.sys.singleapp.SingleAppWebServletListener separate "web" and "core" classes - * to different classloaders when we pack application to single WAR. - *

- * We create 2 URLClassLoaders (1 for core and 1 for web), with predefined (during single WAR build) list of jars (core.dependencies). - * So the classloaders load classes from the jars and only if class is not found they delegate loading to base WebAppClassLoader (their parent). - *

- * As a result, core classloader contains core classes, web classloder contains web classes and WebAppClassLoader contains "shared" classes. - *

- * To make sure the Spring context use specific classloader we load {@code AppWebContextLoader} reflectively, create new instance - * and call its initialization methods reflectively as well. - * - * As each classloader has its own AppContext version, we can put property with dependencies to AppContext (reflectively as well). - * The property will be used on spring context creation, to detect which jars to scan. - * - */ -public class SingleAppCoreServletListener implements ServletContextListener { - protected Object appContextLoader; - - @Override - public void contextInitialized(ServletContextEvent sce) { - try { - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - //need to put the following class to WebAppClassLoader, to share it between for web and core - contextClassLoader.loadClass("com.haulmont.cuba.core.sys.remoting.LocalServiceDirectory"); - - ServletContext servletContext = sce.getServletContext(); - String dependenciesFile; - try { - dependenciesFile = IOUtils.toString(servletContext.getResourceAsStream("/WEB-INF/core.dependencies"), "UTF-8"); - } catch (IOException e) { - throw new RuntimeException("An error occurred while loading dependencies file", e); - } - - String[] dependenciesNames = dependenciesFile.split("\\n"); - URL[] urls = Arrays.stream(dependenciesNames) - .map((String name) -> { - try { - return servletContext.getResource("/WEB-INF/lib/" + name); - } catch (MalformedURLException e) { - throw new RuntimeException("An error occurred while loading dependency " + name, e); - } - }) - .toArray(URL[]::new); - URLClassLoader coreClassLoader = new CubaSingleAppClassLoader(urls, contextClassLoader); - - Thread.currentThread().setContextClassLoader(coreClassLoader); - Class appContextLoaderClass = coreClassLoader.loadClass(getAppContextLoaderClassName()); - appContextLoader = appContextLoaderClass.newInstance(); - - Method setJarsNamesMethod = ReflectionUtils.findMethod(appContextLoaderClass, "setJarNames", String.class); - ReflectionUtils.invokeMethod(setJarsNamesMethod, appContextLoader, dependenciesFile); - - Method contextInitializedMethod = ReflectionUtils.findMethod(appContextLoaderClass, "contextInitialized", ServletContextEvent.class); - ReflectionUtils.invokeMethod(contextInitializedMethod, appContextLoader, sce); - - Thread.currentThread().setContextClassLoader(contextClassLoader); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { - throw new RuntimeException("An error occurred while starting single WAR application", e); - } - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - Method contextInitialized = ReflectionUtils.findMethod(appContextLoader.getClass(), "contextDestroyed", ServletContextEvent.class); - ReflectionUtils.invokeMethod(contextInitialized, appContextLoader, sce); - } - - protected String getAppContextLoaderClassName() { - return "com.haulmont.cuba.core.sys.singleapp.SingleAppCoreContextLoader"; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.singleapp; + +import com.haulmont.cuba.core.sys.CubaSingleAppClassLoader; +import org.apache.commons.io.IOUtils; +import org.springframework.util.ReflectionUtils; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; + +/** + * This class and its twin com.haulmont.cuba.web.sys.singleapp.SingleAppWebServletListener separate "web" and "core" classes + * to different classloaders when we pack application to single WAR. + *

+ * We create 2 URLClassLoaders (1 for core and 1 for web), with predefined (during single WAR build) list of jars (core.dependencies). + * So the classloaders load classes from the jars and only if class is not found they delegate loading to base WebAppClassLoader (their parent). + *

+ * As a result, core classloader contains core classes, web classloder contains web classes and WebAppClassLoader contains "shared" classes. + *

+ * To make sure the Spring context use specific classloader we load {@code AppWebContextLoader} reflectively, create new instance + * and call its initialization methods reflectively as well. + * + * As each classloader has its own AppContext version, we can put property with dependencies to AppContext (reflectively as well). + * The property will be used on spring context creation, to detect which jars to scan. + * + */ +public class SingleAppCoreServletListener implements ServletContextListener { + protected Object appContextLoader; + + @Override + public void contextInitialized(ServletContextEvent sce) { + try { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + //need to put the following class to WebAppClassLoader, to share it between for web and core + contextClassLoader.loadClass("com.haulmont.cuba.core.sys.remoting.LocalServiceDirectory"); + + ServletContext servletContext = sce.getServletContext(); + String dependenciesFile; + try { + dependenciesFile = IOUtils.toString(servletContext.getResourceAsStream("/WEB-INF/core.dependencies"), "UTF-8"); + } catch (IOException e) { + throw new RuntimeException("An error occurred while loading dependencies file", e); + } + + String[] dependenciesNames = dependenciesFile.split("\\n"); + URL[] urls = Arrays.stream(dependenciesNames) + .map((String name) -> { + try { + return servletContext.getResource("/WEB-INF/lib/" + name); + } catch (MalformedURLException e) { + throw new RuntimeException("An error occurred while loading dependency " + name, e); + } + }) + .toArray(URL[]::new); + URLClassLoader coreClassLoader = new CubaSingleAppClassLoader(urls, contextClassLoader); + + Thread.currentThread().setContextClassLoader(coreClassLoader); + Class appContextLoaderClass = coreClassLoader.loadClass(getAppContextLoaderClassName()); + appContextLoader = appContextLoaderClass.newInstance(); + + Method setJarsNamesMethod = ReflectionUtils.findMethod(appContextLoaderClass, "setJarNames", String.class); + ReflectionUtils.invokeMethod(setJarsNamesMethod, appContextLoader, dependenciesFile); + + Method contextInitializedMethod = ReflectionUtils.findMethod(appContextLoaderClass, "contextInitialized", ServletContextEvent.class); + ReflectionUtils.invokeMethod(contextInitializedMethod, appContextLoader, sce); + + Thread.currentThread().setContextClassLoader(contextClassLoader); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException("An error occurred while starting single WAR application", e); + } + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + Method contextInitialized = ReflectionUtils.findMethod(appContextLoader.getClass(), "contextDestroyed", ServletContextEvent.class); + ReflectionUtils.invokeMethod(contextInitialized, appContextLoader, sce); + } + + protected String getAppContextLoaderClassName() { + return "com.haulmont.cuba.core.sys.singleapp.SingleAppCoreContextLoader"; + } +} diff --git a/modules/core/src/com/haulmont/cuba/security/app/Authenticated.java b/modules/core/src/com/haulmont/cuba/security/app/Authenticated.java index fe490cc2fe..ce7037f3e8 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/Authenticated.java +++ b/modules/core/src/com/haulmont/cuba/security/app/Authenticated.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.app; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Annotation for bean methods which require authentication, i.e. presence of a valid user session. - * - */ -@Target({java.lang.annotation.ElementType.METHOD}) -@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) -public @interface Authenticated { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.app; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotation for bean methods which require authentication, i.e. presence of a valid user session. + * + */ +@Target({java.lang.annotation.ElementType.METHOD}) +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +public @interface Authenticated { } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/EntityLog.java b/modules/core/src/com/haulmont/cuba/security/app/EntityLog.java index b265e76496..30cfb6ed0c 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/EntityLog.java +++ b/modules/core/src/com/haulmont/cuba/security/app/EntityLog.java @@ -1,517 +1,517 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.Range; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.entity.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges; -import com.haulmont.cuba.security.entity.*; -import org.apache.commons.lang.BooleanUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; -import javax.inject.Inject; -import java.io.IOException; -import java.io.StringWriter; -import java.util.*; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; - -@Component(EntityLogAPI.NAME) -public class EntityLog implements EntityLogAPI { - - private final Logger log = LoggerFactory.getLogger(EntityLog.class); - - @Inject - protected TimeSource timeSource; - @Inject - protected Persistence persistence; - @Inject - protected Metadata metadata; - @Inject - protected MetadataTools metadataTools; - @Inject - protected UserSessionSource userSessionSource; - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - @Inject - protected ServerConfig serverConfig; - - protected volatile boolean loaded; - protected EntityLogConfig config; - - @GuardedBy("lock") - protected Map> entitiesManual; - @GuardedBy("lock") - protected Map> entitiesAuto; - - protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - protected ThreadLocal entityLogSwitchedOn = new ThreadLocal<>(); - - @Inject - public EntityLog(Configuration configuration) { - config = configuration.getConfig(EntityLogConfig.class); - } - - @Override - public void processLoggingForCurrentThread(boolean enabled) { - entityLogSwitchedOn.set(enabled); - } - - @Override - public boolean isLoggingForCurrentThread() { - return !Boolean.FALSE.equals(entityLogSwitchedOn.get()); - } - - @Override - public synchronized boolean isEnabled() { - return config.getEnabled() && isLoggingForCurrentThread(); - } - - @Override - public synchronized void setEnabled(boolean enabled) { - if (enabled != config.getEnabled()) { - config.setEnabled(enabled); - } - } - - @Override - public void invalidateCache() { - lock.writeLock().lock(); - try { - log.debug("Invalidating cache"); - entitiesManual = null; - entitiesAuto = null; - loaded = false; - } finally { - lock.writeLock().unlock(); - } - } - - protected Set getLoggedAttributes(String entity, boolean auto) { - lock.readLock().lock(); - try { - if (!loaded) { - // upgrade lock - lock.readLock().unlock(); - lock.writeLock().lock(); - try { - if (!loaded) { // recheck because we unlocked for a while - loadEntities(); - loaded = true; - } - } finally { - // downgrade lock - lock.writeLock().unlock(); - lock.readLock().lock(); - } - } - - Set attributes; - if (auto) - attributes = entitiesAuto.get(entity); - else - attributes = entitiesManual.get(entity); - - return attributes == null ? null : Collections.unmodifiableSet(attributes); - } finally { - lock.readLock().unlock(); - } - } - - protected void loadEntities() { - log.debug("Loading entities"); - entitiesManual = new HashMap<>(); - entitiesAuto = new HashMap<>(); - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - TypedQuery q = em.createQuery( - "select e from sec$LoggedEntity e where e.auto = true or e.manual = true", - LoggedEntity.class); -// q.setView(null); - List list = q.getResultList(); - for (LoggedEntity loggedEntity : list) { - if (loggedEntity.getName() == null) { - throw new IllegalStateException("Unable to initialize EntityLog: empty LoggedEntity.name"); - } - Set attributes = new HashSet<>(); - for (LoggedAttribute loggedAttribute : loggedEntity.getAttributes()) { - if (loggedAttribute.getName() == null) { - throw new IllegalStateException("Unable to initialize EntityLog: empty LoggedAttribute.name"); - } - attributes.add(loggedAttribute.getName()); - } - if (BooleanUtils.isTrue(loggedEntity.getAuto())) - entitiesAuto.put(loggedEntity.getName(), attributes); - if (BooleanUtils.isTrue(loggedEntity.getManual())) - entitiesManual.put(loggedEntity.getName(), attributes); - } - tx.commit(); - } finally { - tx.end(); - } - log.debug("Loaded: entitiesAuto={}, entitiesManual={}", entitiesAuto.size(), entitiesManual.size()); - } - - protected String getEntityName(Entity entity) { - MetaClass metaClass = metadata.getSession().getClassNN(entity.getClass()); - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); - return originalMetaClass != null ? originalMetaClass.getName() : metaClass.getName(); - } - - protected boolean doNotRegister(Entity entity) { - if (entity == null) { - return true; - } - if (entity instanceof EntityLogItem) { - return true; - } - if (metadata.getTools().hasCompositePrimaryKey(entity.getMetaClass()) && !(entity instanceof HasUuid)) { - return true; - } - return !isEnabled(); - } - - @Override - public void registerCreate(Entity entity) { - if (entity == null) - return; - registerCreate(entity, false); - } - - @Override - public void registerCreate(Entity entity, boolean auto) { - try { - if (doNotRegister(entity)) - return; - - String entityName = getEntityName(entity); - Set attributes = getLoggedAttributes(entityName, auto); - if (attributes != null && attributes.contains("*")) { - attributes = getAllAttributes(entity); - } - if (attributes == null) { - return; - } - - MetaClass metaClass = metadata.getClassNN(entityName); - attributes = filterRemovedAttributes(metaClass, attributes); - - String storeName = metadata.getTools().getStoreName(metaClass); - if (Stores.isMain(storeName)) { - internalRegisterCreate(entity, entityName, attributes); - } else { - // Create a new transaction in main DB if we are saving an entity from additional data store - try (Transaction tx = persistence.createTransaction()) { - internalRegisterCreate(entity, entityName, attributes); - tx.commit(); - } - } - } catch (Exception e) { - logError(entity, e); - } - } - - protected Set filterRemovedAttributes(MetaClass metaClass, Set attributes) { - // filter attributes that do not exists in entity anymore - return attributes.stream() - .filter(attributeName -> metaClass.getProperty(attributeName) != null) - .collect(Collectors.toSet()); - } - - protected void internalRegisterCreate(Entity entity, String entityName, Set attributes) throws IOException { - Date ts = timeSource.currentTimestamp(); - EntityManager em = persistence.getEntityManager(); - - EntityLogItem item = metadata.create(EntityLogItem.class); - item.setEventTs(ts); - item.setUser(findUser(em)); - item.setType(EntityLogItem.Type.CREATE); - item.setEntity(entityName); - item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); - - Properties properties = new Properties(); - for (String attr : attributes) { - writeAttribute(properties, entity, null, attr); - } - item.setChanges(getChanges(properties)); - - em.persist(item); - } - - protected User findUser(EntityManager em) { - if (AppContext.isStarted()) - return em.getReference(User.class, userSessionSource.getUserSession().getUser().getId()); - else { - String login = serverConfig.getJmxUserLogin(); - TypedQuery query = em.createQuery("select u from sec$User u where u.loginLowerCase = ?1", User.class); - query.setParameter(1, login); - User user = query.getFirstResult(); - if (user != null) - return user; - else - throw new RuntimeException("The user '" + login + "' specified in cuba.jmxUserLogin does not exist"); - } - } - - @Override - public void registerModify(Entity entity) { - registerModify(entity, false); - } - - @Override - public void registerModify(Entity entity, boolean auto) { - registerModify(entity, auto, null); - } - - @Override - public void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes) { - try { - if (doNotRegister(entity)) - return; - - String entityName = getEntityName(entity); - Set attributes = getLoggedAttributes(entityName, auto); - if (attributes != null && attributes.contains("*")) { - attributes = getAllAttributes(entity); - } - if (attributes == null) { - return; - } - - MetaClass metaClass = metadata.getClassNN(entityName); - attributes = filterRemovedAttributes(metaClass, attributes); - - String storeName = metadataTools.getStoreName(metaClass); - if (Stores.isMain(storeName)) { - internalRegisterModify(entity, changes, metaClass, storeName, attributes); - } else { - // Create a new transaction in main DB if we are saving an entity from additional data store - try (Transaction tx = persistence.createTransaction()) { - internalRegisterModify(entity, changes, metaClass, storeName, attributes); - tx.commit(); - } - } - } catch (Exception e) { - logError(entity, e); - } - } - - protected void internalRegisterModify(Entity entity, @Nullable EntityAttributeChanges changes, MetaClass metaClass, - String storeName, Set attributes) throws IOException { - Date ts = timeSource.currentTimestamp(); - EntityManager em = persistence.getEntityManager(); - - Set dirty; - if (changes == null) { - dirty = persistence.getTools().getDirtyFields(entity); - } else { - dirty = changes.getAttributes(); - } - - EntityLogItem.Type type; - Properties properties = new Properties(); - if (entity instanceof SoftDelete && dirty.contains("deleteTs") && !((SoftDelete) entity).isDeleted()) { - type = EntityLogItem.Type.RESTORE; - for (String attr : attributes) { - writeAttribute(properties, entity, changes, attr); - } - } else { - type = EntityLogItem.Type.MODIFY; - for (String attr : attributes) { - if (dirty.contains(attr)) { - writeAttribute(properties, entity, changes, attr); - } else if (!Stores.getAdditional().isEmpty()) { - String idAttr = metadataTools.getCrossDataStoreReferenceIdProperty(storeName, metaClass.getPropertyNN(attr)); - if (idAttr != null && dirty.contains(idAttr)) { - writeAttribute(properties, entity, changes, attr); - } - } - } - } - if (!properties.isEmpty() || type == EntityLogItem.Type.RESTORE) { - EntityLogItem item = metadata.create(EntityLogItem.class); - item.setEventTs(ts); - item.setUser(findUser(em)); - item.setType(type); - item.setEntity(metaClass.getName()); - item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); - item.setChanges(getChanges(properties)); - - em.persist(item); - } - } - - protected String getChanges(Properties properties) throws IOException { - StringWriter writer = new StringWriter(); - properties.store(writer, null); - String changes = writer.toString(); - if (changes.startsWith("#")) - changes = changes.substring(changes.indexOf("\n") + 1); // cut off comments line - return changes; - } - - protected void writeAttribute(Properties properties, Entity entity, @Nullable EntityAttributeChanges changes, String attr) { - if (!PersistenceHelper.isLoaded(entity, attr)) - return; - - Object value = entity.getValue(attr); - properties.setProperty(attr, stringify(value)); - - Object valueId = getValueId(value); - if (valueId != null) - properties.setProperty(attr + EntityLogAttr.VALUE_ID_SUFFIX, valueId.toString()); - - if (changes != null) { - Object oldValue = changes.getOldValue(attr); - properties.setProperty(attr + EntityLogAttr.OLD_VALUE_SUFFIX, stringify(oldValue)); - Object oldValueId = getValueId(oldValue); - if (oldValueId != null) { - properties.setProperty(attr + EntityLogAttr.OLD_VALUE_ID_SUFFIX, oldValueId.toString()); - } - } - - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - String mp = messageTools.inferMessagePack(attr, entity); - if (mp != null) - properties.setProperty(attr + EntityLogAttr.MP_SUFFIX, mp); - } - - @Override - public void registerDelete(Entity entity) { - registerDelete(entity, false); - } - - @Override - public void registerDelete(Entity entity, boolean auto) { - try { - if (doNotRegister(entity)) - return; - - String entityName = getEntityName(entity); - Set attributes = getLoggedAttributes(entityName, auto); - if (attributes != null && attributes.contains("*")) { - attributes = getAllAttributes(entity); - } - if (attributes == null) { - return; - } - - MetaClass metaClass = metadata.getClassNN(entityName); - attributes = filterRemovedAttributes(metaClass, attributes); - - String storeName = metadata.getTools().getStoreName(metaClass); - if (Stores.isMain(storeName)) { - internalRegisterDelete(entity, entityName, attributes); - } else { - // Create a new transaction in main DB if we are saving an entity from additional data store - try (Transaction tx = persistence.createTransaction()) { - internalRegisterDelete(entity, entityName, attributes); - tx.commit(); - } - } - } catch (Exception e) { - logError(entity, e); - } - } - - protected void internalRegisterDelete(Entity entity, String entityName, Set attributes) throws IOException { - Date ts = timeSource.currentTimestamp(); - EntityManager em = persistence.getEntityManager(); - - EntityLogItem item = metadata.create(EntityLogItem.class); - item.setEventTs(ts); - item.setUser(findUser(em)); - item.setType(EntityLogItem.Type.DELETE); - item.setEntity(entityName); - item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); - - Properties properties = new Properties(); - for (String attr : attributes) { - writeAttribute(properties, entity, null, attr); - } - item.setChanges(getChanges(properties)); - - em.persist(item); - } - - protected Set getAllAttributes(Entity entity) { - if (entity == null) { - return null; - } - Set attributes = new HashSet<>(); - for (MetaProperty metaProperty : metadata.getClassNN(entity.getClass()).getProperties()) { - Range range = metaProperty.getRange(); - if (range.isClass() && range.getCardinality().isMany()) { - continue; - } - attributes.add(metaProperty.getName()); - } - return attributes; - } - - protected Object getValueId(Object value) { - if (value instanceof EmbeddableEntity) { - return null; - } else if (value instanceof BaseGenericIdEntity) { - return referenceToEntitySupport.getReferenceId((Entity) value); - } else { - return null; - } - } - - protected String stringify(Object value) { - if (value == null) - return ""; - else if (value instanceof Instance) { - return ((Instance) value).getInstanceName(); - } else if (value instanceof Date) { - return Datatypes.getNN(value.getClass()).format(value); - } else if (value instanceof Iterable) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (Object obj : (Iterable) value) { - sb.append(stringify(obj)).append(","); - } - if (sb.length() > 1) - sb.deleteCharAt(sb.length() - 1); - sb.append("]"); - return sb.toString(); - } else { - return String.valueOf(value); - } - } - - protected void logError(Entity entity, Exception e) { - log.warn("Unable to log entity {}, id={}", entity, entity.getId(), e); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.Range; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.entity.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges; +import com.haulmont.cuba.security.entity.*; +import org.apache.commons.lang.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.inject.Inject; +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; + +@Component(EntityLogAPI.NAME) +public class EntityLog implements EntityLogAPI { + + private final Logger log = LoggerFactory.getLogger(EntityLog.class); + + @Inject + protected TimeSource timeSource; + @Inject + protected Persistence persistence; + @Inject + protected Metadata metadata; + @Inject + protected MetadataTools metadataTools; + @Inject + protected UserSessionSource userSessionSource; + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + @Inject + protected ServerConfig serverConfig; + + protected volatile boolean loaded; + protected EntityLogConfig config; + + @GuardedBy("lock") + protected Map> entitiesManual; + @GuardedBy("lock") + protected Map> entitiesAuto; + + protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + protected ThreadLocal entityLogSwitchedOn = new ThreadLocal<>(); + + @Inject + public EntityLog(Configuration configuration) { + config = configuration.getConfig(EntityLogConfig.class); + } + + @Override + public void processLoggingForCurrentThread(boolean enabled) { + entityLogSwitchedOn.set(enabled); + } + + @Override + public boolean isLoggingForCurrentThread() { + return !Boolean.FALSE.equals(entityLogSwitchedOn.get()); + } + + @Override + public synchronized boolean isEnabled() { + return config.getEnabled() && isLoggingForCurrentThread(); + } + + @Override + public synchronized void setEnabled(boolean enabled) { + if (enabled != config.getEnabled()) { + config.setEnabled(enabled); + } + } + + @Override + public void invalidateCache() { + lock.writeLock().lock(); + try { + log.debug("Invalidating cache"); + entitiesManual = null; + entitiesAuto = null; + loaded = false; + } finally { + lock.writeLock().unlock(); + } + } + + protected Set getLoggedAttributes(String entity, boolean auto) { + lock.readLock().lock(); + try { + if (!loaded) { + // upgrade lock + lock.readLock().unlock(); + lock.writeLock().lock(); + try { + if (!loaded) { // recheck because we unlocked for a while + loadEntities(); + loaded = true; + } + } finally { + // downgrade lock + lock.writeLock().unlock(); + lock.readLock().lock(); + } + } + + Set attributes; + if (auto) + attributes = entitiesAuto.get(entity); + else + attributes = entitiesManual.get(entity); + + return attributes == null ? null : Collections.unmodifiableSet(attributes); + } finally { + lock.readLock().unlock(); + } + } + + protected void loadEntities() { + log.debug("Loading entities"); + entitiesManual = new HashMap<>(); + entitiesAuto = new HashMap<>(); + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + TypedQuery q = em.createQuery( + "select e from sec$LoggedEntity e where e.auto = true or e.manual = true", + LoggedEntity.class); +// q.setView(null); + List list = q.getResultList(); + for (LoggedEntity loggedEntity : list) { + if (loggedEntity.getName() == null) { + throw new IllegalStateException("Unable to initialize EntityLog: empty LoggedEntity.name"); + } + Set attributes = new HashSet<>(); + for (LoggedAttribute loggedAttribute : loggedEntity.getAttributes()) { + if (loggedAttribute.getName() == null) { + throw new IllegalStateException("Unable to initialize EntityLog: empty LoggedAttribute.name"); + } + attributes.add(loggedAttribute.getName()); + } + if (BooleanUtils.isTrue(loggedEntity.getAuto())) + entitiesAuto.put(loggedEntity.getName(), attributes); + if (BooleanUtils.isTrue(loggedEntity.getManual())) + entitiesManual.put(loggedEntity.getName(), attributes); + } + tx.commit(); + } finally { + tx.end(); + } + log.debug("Loaded: entitiesAuto={}, entitiesManual={}", entitiesAuto.size(), entitiesManual.size()); + } + + protected String getEntityName(Entity entity) { + MetaClass metaClass = metadata.getSession().getClassNN(entity.getClass()); + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); + return originalMetaClass != null ? originalMetaClass.getName() : metaClass.getName(); + } + + protected boolean doNotRegister(Entity entity) { + if (entity == null) { + return true; + } + if (entity instanceof EntityLogItem) { + return true; + } + if (metadata.getTools().hasCompositePrimaryKey(entity.getMetaClass()) && !(entity instanceof HasUuid)) { + return true; + } + return !isEnabled(); + } + + @Override + public void registerCreate(Entity entity) { + if (entity == null) + return; + registerCreate(entity, false); + } + + @Override + public void registerCreate(Entity entity, boolean auto) { + try { + if (doNotRegister(entity)) + return; + + String entityName = getEntityName(entity); + Set attributes = getLoggedAttributes(entityName, auto); + if (attributes != null && attributes.contains("*")) { + attributes = getAllAttributes(entity); + } + if (attributes == null) { + return; + } + + MetaClass metaClass = metadata.getClassNN(entityName); + attributes = filterRemovedAttributes(metaClass, attributes); + + String storeName = metadata.getTools().getStoreName(metaClass); + if (Stores.isMain(storeName)) { + internalRegisterCreate(entity, entityName, attributes); + } else { + // Create a new transaction in main DB if we are saving an entity from additional data store + try (Transaction tx = persistence.createTransaction()) { + internalRegisterCreate(entity, entityName, attributes); + tx.commit(); + } + } + } catch (Exception e) { + logError(entity, e); + } + } + + protected Set filterRemovedAttributes(MetaClass metaClass, Set attributes) { + // filter attributes that do not exists in entity anymore + return attributes.stream() + .filter(attributeName -> metaClass.getProperty(attributeName) != null) + .collect(Collectors.toSet()); + } + + protected void internalRegisterCreate(Entity entity, String entityName, Set attributes) throws IOException { + Date ts = timeSource.currentTimestamp(); + EntityManager em = persistence.getEntityManager(); + + EntityLogItem item = metadata.create(EntityLogItem.class); + item.setEventTs(ts); + item.setUser(findUser(em)); + item.setType(EntityLogItem.Type.CREATE); + item.setEntity(entityName); + item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); + + Properties properties = new Properties(); + for (String attr : attributes) { + writeAttribute(properties, entity, null, attr); + } + item.setChanges(getChanges(properties)); + + em.persist(item); + } + + protected User findUser(EntityManager em) { + if (AppContext.isStarted()) + return em.getReference(User.class, userSessionSource.getUserSession().getUser().getId()); + else { + String login = serverConfig.getJmxUserLogin(); + TypedQuery query = em.createQuery("select u from sec$User u where u.loginLowerCase = ?1", User.class); + query.setParameter(1, login); + User user = query.getFirstResult(); + if (user != null) + return user; + else + throw new RuntimeException("The user '" + login + "' specified in cuba.jmxUserLogin does not exist"); + } + } + + @Override + public void registerModify(Entity entity) { + registerModify(entity, false); + } + + @Override + public void registerModify(Entity entity, boolean auto) { + registerModify(entity, auto, null); + } + + @Override + public void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes) { + try { + if (doNotRegister(entity)) + return; + + String entityName = getEntityName(entity); + Set attributes = getLoggedAttributes(entityName, auto); + if (attributes != null && attributes.contains("*")) { + attributes = getAllAttributes(entity); + } + if (attributes == null) { + return; + } + + MetaClass metaClass = metadata.getClassNN(entityName); + attributes = filterRemovedAttributes(metaClass, attributes); + + String storeName = metadataTools.getStoreName(metaClass); + if (Stores.isMain(storeName)) { + internalRegisterModify(entity, changes, metaClass, storeName, attributes); + } else { + // Create a new transaction in main DB if we are saving an entity from additional data store + try (Transaction tx = persistence.createTransaction()) { + internalRegisterModify(entity, changes, metaClass, storeName, attributes); + tx.commit(); + } + } + } catch (Exception e) { + logError(entity, e); + } + } + + protected void internalRegisterModify(Entity entity, @Nullable EntityAttributeChanges changes, MetaClass metaClass, + String storeName, Set attributes) throws IOException { + Date ts = timeSource.currentTimestamp(); + EntityManager em = persistence.getEntityManager(); + + Set dirty; + if (changes == null) { + dirty = persistence.getTools().getDirtyFields(entity); + } else { + dirty = changes.getAttributes(); + } + + EntityLogItem.Type type; + Properties properties = new Properties(); + if (entity instanceof SoftDelete && dirty.contains("deleteTs") && !((SoftDelete) entity).isDeleted()) { + type = EntityLogItem.Type.RESTORE; + for (String attr : attributes) { + writeAttribute(properties, entity, changes, attr); + } + } else { + type = EntityLogItem.Type.MODIFY; + for (String attr : attributes) { + if (dirty.contains(attr)) { + writeAttribute(properties, entity, changes, attr); + } else if (!Stores.getAdditional().isEmpty()) { + String idAttr = metadataTools.getCrossDataStoreReferenceIdProperty(storeName, metaClass.getPropertyNN(attr)); + if (idAttr != null && dirty.contains(idAttr)) { + writeAttribute(properties, entity, changes, attr); + } + } + } + } + if (!properties.isEmpty() || type == EntityLogItem.Type.RESTORE) { + EntityLogItem item = metadata.create(EntityLogItem.class); + item.setEventTs(ts); + item.setUser(findUser(em)); + item.setType(type); + item.setEntity(metaClass.getName()); + item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); + item.setChanges(getChanges(properties)); + + em.persist(item); + } + } + + protected String getChanges(Properties properties) throws IOException { + StringWriter writer = new StringWriter(); + properties.store(writer, null); + String changes = writer.toString(); + if (changes.startsWith("#")) + changes = changes.substring(changes.indexOf("\n") + 1); // cut off comments line + return changes; + } + + protected void writeAttribute(Properties properties, Entity entity, @Nullable EntityAttributeChanges changes, String attr) { + if (!PersistenceHelper.isLoaded(entity, attr)) + return; + + Object value = entity.getValue(attr); + properties.setProperty(attr, stringify(value)); + + Object valueId = getValueId(value); + if (valueId != null) + properties.setProperty(attr + EntityLogAttr.VALUE_ID_SUFFIX, valueId.toString()); + + if (changes != null) { + Object oldValue = changes.getOldValue(attr); + properties.setProperty(attr + EntityLogAttr.OLD_VALUE_SUFFIX, stringify(oldValue)); + Object oldValueId = getValueId(oldValue); + if (oldValueId != null) { + properties.setProperty(attr + EntityLogAttr.OLD_VALUE_ID_SUFFIX, oldValueId.toString()); + } + } + + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + String mp = messageTools.inferMessagePack(attr, entity); + if (mp != null) + properties.setProperty(attr + EntityLogAttr.MP_SUFFIX, mp); + } + + @Override + public void registerDelete(Entity entity) { + registerDelete(entity, false); + } + + @Override + public void registerDelete(Entity entity, boolean auto) { + try { + if (doNotRegister(entity)) + return; + + String entityName = getEntityName(entity); + Set attributes = getLoggedAttributes(entityName, auto); + if (attributes != null && attributes.contains("*")) { + attributes = getAllAttributes(entity); + } + if (attributes == null) { + return; + } + + MetaClass metaClass = metadata.getClassNN(entityName); + attributes = filterRemovedAttributes(metaClass, attributes); + + String storeName = metadata.getTools().getStoreName(metaClass); + if (Stores.isMain(storeName)) { + internalRegisterDelete(entity, entityName, attributes); + } else { + // Create a new transaction in main DB if we are saving an entity from additional data store + try (Transaction tx = persistence.createTransaction()) { + internalRegisterDelete(entity, entityName, attributes); + tx.commit(); + } + } + } catch (Exception e) { + logError(entity, e); + } + } + + protected void internalRegisterDelete(Entity entity, String entityName, Set attributes) throws IOException { + Date ts = timeSource.currentTimestamp(); + EntityManager em = persistence.getEntityManager(); + + EntityLogItem item = metadata.create(EntityLogItem.class); + item.setEventTs(ts); + item.setUser(findUser(em)); + item.setType(EntityLogItem.Type.DELETE); + item.setEntity(entityName); + item.setObjectEntityId(referenceToEntitySupport.getReferenceId(entity)); + + Properties properties = new Properties(); + for (String attr : attributes) { + writeAttribute(properties, entity, null, attr); + } + item.setChanges(getChanges(properties)); + + em.persist(item); + } + + protected Set getAllAttributes(Entity entity) { + if (entity == null) { + return null; + } + Set attributes = new HashSet<>(); + for (MetaProperty metaProperty : metadata.getClassNN(entity.getClass()).getProperties()) { + Range range = metaProperty.getRange(); + if (range.isClass() && range.getCardinality().isMany()) { + continue; + } + attributes.add(metaProperty.getName()); + } + return attributes; + } + + protected Object getValueId(Object value) { + if (value instanceof EmbeddableEntity) { + return null; + } else if (value instanceof BaseGenericIdEntity) { + return referenceToEntitySupport.getReferenceId((Entity) value); + } else { + return null; + } + } + + protected String stringify(Object value) { + if (value == null) + return ""; + else if (value instanceof Instance) { + return ((Instance) value).getInstanceName(); + } else if (value instanceof Date) { + return Datatypes.getNN(value.getClass()).format(value); + } else if (value instanceof Iterable) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (Object obj : (Iterable) value) { + sb.append(stringify(obj)).append(","); + } + if (sb.length() > 1) + sb.deleteCharAt(sb.length() - 1); + sb.append("]"); + return sb.toString(); + } else { + return String.valueOf(value); + } + } + + protected void logError(Entity entity, Exception e) { + log.warn("Unable to log entity {}, id={}", entity, entity.getId(), e); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/EntityLogAPI.java b/modules/core/src/com/haulmont/cuba/security/app/EntityLogAPI.java index 29a572d41e..fcbc80233b 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/EntityLogAPI.java +++ b/modules/core/src/com/haulmont/cuba/security/app/EntityLogAPI.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges; - -import javax.annotation.Nullable; - -/** - * Allows to log entity lifecycle events: create, modify, delete. - *
- * Configured by {@link com.haulmont.cuba.security.entity.LoggedEntity} and - * {@link com.haulmont.cuba.security.entity.LoggedAttribute} entities. - * See also {@link com.haulmont.cuba.security.app.EntityLogConfig} configuration interface. - */ -public interface EntityLogAPI { - - String NAME = "cuba_EntityLog"; - - boolean isEnabled(); - void setEnabled(boolean enabled); - - /** - * Logs creation of an entity which is configured for manual logging (LoggedEntity.auto == false). - */ - void registerCreate(Entity entity); - - /** - * Logs creation of an entity which is configured for auto or manual logging - * (depending on the {@code auto} parameter). - */ - void registerCreate(Entity entity, boolean auto); - - /** - * Logs modification of an entity which is configured for manual logging (LoggedEntity.auto == false). - */ - void registerModify(Entity entity); - - /** - * Logs modification of an entity which is configured for auto or manual logging - * (depending on the {@code auto} parameter). - */ - void registerModify(Entity entity, boolean auto); - - - /** - * Logs modification of an entity which is configured for auto or manual logging - * (depending on the {@code auto} parameter). - * @param changes attribute changes provided by caller - */ - void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes); - - /** - * Logs deletion of an entity which is configured for manual logging (LoggedEntity.auto == false). - */ - void registerDelete(Entity entity); - - /** - * Logs deletion of an entity which is configured for auto or manual logging - * (depending on the {@code auto} parameter). - */ - void registerDelete(Entity entity, boolean auto); - - /** - * Invalidates configuration cache. - * The configuration will be recreated from the database on next lifecycle event. - */ - void invalidateCache(); - - /** - * Disables/enables entity logging for current thread. - * Enabled by default. - * - * @param enabled entity logging disabled if false, enabled otherwise. - */ - void processLoggingForCurrentThread(boolean enabled); - - /** - * @return whether logging for the current thread is enabled - * @see #processLoggingForCurrentThread(boolean) - */ - boolean isLoggingForCurrentThread(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.sys.persistence.EntityAttributeChanges; + +import javax.annotation.Nullable; + +/** + * Allows to log entity lifecycle events: create, modify, delete. + *
+ * Configured by {@link com.haulmont.cuba.security.entity.LoggedEntity} and + * {@link com.haulmont.cuba.security.entity.LoggedAttribute} entities. + * See also {@link com.haulmont.cuba.security.app.EntityLogConfig} configuration interface. + */ +public interface EntityLogAPI { + + String NAME = "cuba_EntityLog"; + + boolean isEnabled(); + void setEnabled(boolean enabled); + + /** + * Logs creation of an entity which is configured for manual logging (LoggedEntity.auto == false). + */ + void registerCreate(Entity entity); + + /** + * Logs creation of an entity which is configured for auto or manual logging + * (depending on the {@code auto} parameter). + */ + void registerCreate(Entity entity, boolean auto); + + /** + * Logs modification of an entity which is configured for manual logging (LoggedEntity.auto == false). + */ + void registerModify(Entity entity); + + /** + * Logs modification of an entity which is configured for auto or manual logging + * (depending on the {@code auto} parameter). + */ + void registerModify(Entity entity, boolean auto); + + + /** + * Logs modification of an entity which is configured for auto or manual logging + * (depending on the {@code auto} parameter). + * @param changes attribute changes provided by caller + */ + void registerModify(Entity entity, boolean auto, @Nullable EntityAttributeChanges changes); + + /** + * Logs deletion of an entity which is configured for manual logging (LoggedEntity.auto == false). + */ + void registerDelete(Entity entity); + + /** + * Logs deletion of an entity which is configured for auto or manual logging + * (depending on the {@code auto} parameter). + */ + void registerDelete(Entity entity, boolean auto); + + /** + * Invalidates configuration cache. + * The configuration will be recreated from the database on next lifecycle event. + */ + void invalidateCache(); + + /** + * Disables/enables entity logging for current thread. + * Enabled by default. + * + * @param enabled entity logging disabled if false, enabled otherwise. + */ + void processLoggingForCurrentThread(boolean enabled); + + /** + * @return whether logging for the current thread is enabled + * @see #processLoggingForCurrentThread(boolean) + */ + boolean isLoggingForCurrentThread(); +} diff --git a/modules/core/src/com/haulmont/cuba/security/app/EntityLogConfig.java b/modules/core/src/com/haulmont/cuba/security/app/EntityLogConfig.java index ded628ca19..8d5ad27edc 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/EntityLogConfig.java +++ b/modules/core/src/com/haulmont/cuba/security/app/EntityLogConfig.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.DefaultBoolean; - -/** - * {@link com.haulmont.cuba.security.app.EntityLog} configuration parameters - * - */ -@Source(type = SourceType.DATABASE) -public interface EntityLogConfig extends Config { - /** - * @return Whether the EntityLog is enabled - */ - @Property("cuba.entityLog.enabled") - @DefaultBoolean(true) - boolean getEnabled(); - void setEnabled(boolean value); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.DefaultBoolean; + +/** + * {@link com.haulmont.cuba.security.app.EntityLog} configuration parameters + * + */ +@Source(type = SourceType.DATABASE) +public interface EntityLogConfig extends Config { + /** + * @return Whether the EntityLog is enabled + */ + @Property("cuba.entityLog.enabled") + @DefaultBoolean(true) + boolean getEnabled(); + void setEnabled(boolean value); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/LoginServiceBean.java b/modules/core/src/com/haulmont/cuba/security/app/LoginServiceBean.java index d1a9fd13be..cad556086c 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/LoginServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/security/app/LoginServiceBean.java @@ -1,189 +1,189 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.remoting.RemoteClientInfo; -import com.haulmont.cuba.security.auth.*; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.SessionParams; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Service to provide methods for user login/logout to the middleware. - */ -@Deprecated -@Component(LoginService.NAME) -public class LoginServiceBean implements LoginService { - - private final Logger log = LoggerFactory.getLogger(LoginServiceBean.class); - - @Inject - protected AuthenticationService authenticationService; - - @Inject - protected TrustedClientService trustedClientService; - - @Inject - protected LoginWorker loginWorker; - - @Inject - protected BruteForceProtectionAPI bruteForceProtectionAPI; - - @Inject - protected GlobalConfig globalConfig; - - @Override - public UserSession login(String login, String password, Locale locale) throws LoginException { - return login(login, password, locale, Collections.emptyMap()); - } - - @Override - public UserSession login(String login, String password, Locale locale, Map params) throws LoginException { - LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, password, locale, params); - copyParamsToCredentials(params, credentials); - return authenticationService.login(credentials).getSession(); - } - - @Override - public UserSession loginTrusted(String login, String password, Locale locale) throws LoginException { - return loginTrusted(login, password, locale, Collections.emptyMap()); - } - - @Override - public UserSession loginTrusted(String login, String password, Locale locale, Map params) throws LoginException { - TrustedClientCredentials credentials = new TrustedClientCredentials(login, password, locale, params); - RemoteClientInfo remoteClientInfo = RemoteClientInfo.get(); - if (remoteClientInfo != null) { - credentials.setClientIpAddress(remoteClientInfo.getAddress()); - } else { - credentials.setClientIpAddress(null); - } - - copyParamsToCredentials(params, credentials); - return authenticationService.login(credentials).getSession(); - } - - @Override - public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException { - return loginByRememberMe(login, rememberMeToken, locale, Collections.emptyMap()); - } - - @Override - public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) - throws LoginException { - RememberMeCredentials credentials = new RememberMeCredentials(login, rememberMeToken, locale, params); - copyParamsToCredentials(params, credentials); - return authenticationService.login(credentials).getSession(); - } - - @Override - public UserSession getSystemSession(String trustedClientPassword) throws LoginException { - try { - return trustedClientService.getSystemSession(trustedClientPassword); - } catch (LoginException e) { - log.info("Login failed: {}", e.toString()); - throw e; - } catch (Throwable e) { - log.error("Login error", e); - //noinspection ThrowableResultOfMethodCallIgnored - Throwable rootCause = ExceptionUtils.getRootCause(e); - if (rootCause == null) - rootCause = e; - // send text only to avoid ClassNotFoundException when the client has no dependency to some library - throw new LoginException(rootCause.toString()); - } - } - - @Override - public void logout() { - authenticationService.logout(); - } - - @Override - public UserSession substituteUser(User substitutedUser) { - return authenticationService.substituteUser(substitutedUser); - } - - @Override - public UserSession getSession(UUID sessionId) { - return loginWorker.getSession(sessionId); - } - - @Override - public boolean checkRememberMe(String login, String rememberMeToken) { - log.warn("LoginService checkRememberMe is not supported any more. Always returns false"); - return false; - } - - @Override - public boolean isBruteForceProtectionEnabled() { - // bruteForceProtectionEnabled is not accessible for clients any more - return false; - } - - @Override - public int getBruteForceBlockIntervalSec() { - return bruteForceProtectionAPI.getBruteForceBlockIntervalSec(); - } - - @Override - public int loginAttemptsLeft(String login, String ipAddress) { - return bruteForceProtectionAPI.loginAttemptsLeft(login, ipAddress); - } - - @Override - public int registerUnsuccessfulLogin(String login, String ipAddress) { - return bruteForceProtectionAPI.registerUnsuccessfulLogin(login, ipAddress); - } - - @Deprecated - protected void copyParamsToCredentials(Map params, AbstractClientCredentials credentials) { - // for compatibility only - Object clientType = params.get(ClientType.class.getName()); - if (clientType != null) { - credentials.setClientType(ClientType.valueOf((String) clientType)); - } - Object clientInfo = params.get(SessionParams.CLIENT_INFO.getId()); - if (clientInfo != null) { - credentials.setClientInfo((String) clientInfo); - } - Object ipAddress = params.get(SessionParams.IP_ADDERSS.getId()); - if (ipAddress != null) { - credentials.setIpAddress((String) ipAddress); - } - Object hostName = params.get(SessionParams.HOST_NAME.getId()); - if (hostName != null) { - credentials.setHostName((String) hostName); - } - if (!globalConfig.getLocaleSelectVisible()) { - credentials.setOverrideLocale(false); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.remoting.RemoteClientInfo; +import com.haulmont.cuba.security.auth.*; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.SessionParams; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +/** + * Service to provide methods for user login/logout to the middleware. + */ +@Deprecated +@Component(LoginService.NAME) +public class LoginServiceBean implements LoginService { + + private final Logger log = LoggerFactory.getLogger(LoginServiceBean.class); + + @Inject + protected AuthenticationService authenticationService; + + @Inject + protected TrustedClientService trustedClientService; + + @Inject + protected LoginWorker loginWorker; + + @Inject + protected BruteForceProtectionAPI bruteForceProtectionAPI; + + @Inject + protected GlobalConfig globalConfig; + + @Override + public UserSession login(String login, String password, Locale locale) throws LoginException { + return login(login, password, locale, Collections.emptyMap()); + } + + @Override + public UserSession login(String login, String password, Locale locale, Map params) throws LoginException { + LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, password, locale, params); + copyParamsToCredentials(params, credentials); + return authenticationService.login(credentials).getSession(); + } + + @Override + public UserSession loginTrusted(String login, String password, Locale locale) throws LoginException { + return loginTrusted(login, password, locale, Collections.emptyMap()); + } + + @Override + public UserSession loginTrusted(String login, String password, Locale locale, Map params) throws LoginException { + TrustedClientCredentials credentials = new TrustedClientCredentials(login, password, locale, params); + RemoteClientInfo remoteClientInfo = RemoteClientInfo.get(); + if (remoteClientInfo != null) { + credentials.setClientIpAddress(remoteClientInfo.getAddress()); + } else { + credentials.setClientIpAddress(null); + } + + copyParamsToCredentials(params, credentials); + return authenticationService.login(credentials).getSession(); + } + + @Override + public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException { + return loginByRememberMe(login, rememberMeToken, locale, Collections.emptyMap()); + } + + @Override + public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) + throws LoginException { + RememberMeCredentials credentials = new RememberMeCredentials(login, rememberMeToken, locale, params); + copyParamsToCredentials(params, credentials); + return authenticationService.login(credentials).getSession(); + } + + @Override + public UserSession getSystemSession(String trustedClientPassword) throws LoginException { + try { + return trustedClientService.getSystemSession(trustedClientPassword); + } catch (LoginException e) { + log.info("Login failed: {}", e.toString()); + throw e; + } catch (Throwable e) { + log.error("Login error", e); + //noinspection ThrowableResultOfMethodCallIgnored + Throwable rootCause = ExceptionUtils.getRootCause(e); + if (rootCause == null) + rootCause = e; + // send text only to avoid ClassNotFoundException when the client has no dependency to some library + throw new LoginException(rootCause.toString()); + } + } + + @Override + public void logout() { + authenticationService.logout(); + } + + @Override + public UserSession substituteUser(User substitutedUser) { + return authenticationService.substituteUser(substitutedUser); + } + + @Override + public UserSession getSession(UUID sessionId) { + return loginWorker.getSession(sessionId); + } + + @Override + public boolean checkRememberMe(String login, String rememberMeToken) { + log.warn("LoginService checkRememberMe is not supported any more. Always returns false"); + return false; + } + + @Override + public boolean isBruteForceProtectionEnabled() { + // bruteForceProtectionEnabled is not accessible for clients any more + return false; + } + + @Override + public int getBruteForceBlockIntervalSec() { + return bruteForceProtectionAPI.getBruteForceBlockIntervalSec(); + } + + @Override + public int loginAttemptsLeft(String login, String ipAddress) { + return bruteForceProtectionAPI.loginAttemptsLeft(login, ipAddress); + } + + @Override + public int registerUnsuccessfulLogin(String login, String ipAddress) { + return bruteForceProtectionAPI.registerUnsuccessfulLogin(login, ipAddress); + } + + @Deprecated + protected void copyParamsToCredentials(Map params, AbstractClientCredentials credentials) { + // for compatibility only + Object clientType = params.get(ClientType.class.getName()); + if (clientType != null) { + credentials.setClientType(ClientType.valueOf((String) clientType)); + } + Object clientInfo = params.get(SessionParams.CLIENT_INFO.getId()); + if (clientInfo != null) { + credentials.setClientInfo((String) clientInfo); + } + Object ipAddress = params.get(SessionParams.IP_ADDERSS.getId()); + if (ipAddress != null) { + credentials.setIpAddress((String) ipAddress); + } + Object hostName = params.get(SessionParams.HOST_NAME.getId()); + if (hostName != null) { + credentials.setHostName((String) hostName); + } + if (!globalConfig.getLocaleSelectVisible()) { + credentials.setOverrideLocale(false); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/LoginWorker.java b/modules/core/src/com/haulmont/cuba/security/app/LoginWorker.java index 28a91641bc..4f5e21632f 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/LoginWorker.java +++ b/modules/core/src/com/haulmont/cuba/security/app/LoginWorker.java @@ -1,149 +1,149 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.security.auth.*; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.UserSessionManager; - -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Interface to {@link com.haulmont.cuba.security.app.LoginWorkerBean} - * - * @deprecated Use {@link AuthenticationManager} - */ -@Deprecated -public interface LoginWorker { - - String NAME = "cuba_LoginWorker"; - - /** - * @deprecated Use {@link AuthenticationManager#logout()} - */ - @Deprecated - void logout(); - - /** - * @deprecated Use {@link AuthenticationManager#substituteUser(User)} - */ - @Deprecated - UserSession substituteUser(User substitutedUser); - - /** - * @deprecated User {@link UserSessionManager#findSession(UUID)} - */ - @Nullable - @Deprecated - UserSession getSession(UUID sessionId); - - /** - * Log in from a middleware component. This method should not be exposed to any client tier. - * - * @param login login of a system user - * @return system user session that is not replicated in cluster - * @throws LoginException in case of unsuccessful log in - * - * @deprecated Use {@link AuthenticationManager} with {@link SystemUserCredentials} - */ - @Deprecated - UserSession loginSystem(String login) throws LoginException; - - /** - * Login anonymous session for trusted clients - * - * @return anonymous user session that is not replicated in cluster - * @throws LoginException in case of login problem - * - * @deprecated Use {@link AuthenticationManager} with {@link AnonymousUserCredentials} - */ - @Deprecated - UserSession loginAnonymous() throws LoginException; - - /** - * @deprecated Use {@link AuthenticationManager} with {@link LoginPasswordCredentials} - */ - @Deprecated - UserSession login(String login, String password, Locale locale) throws LoginException; - - /** - * @deprecated Use {@link AuthenticationManager} with {@link LoginPasswordCredentials} - */ - @Deprecated - UserSession login(String login, String password, Locale locale, Map params) throws LoginException; - - /** - * @deprecated Use {@link Authentication} directly. - */ - @Deprecated - UserSession getSystemSession(String trustedClientPassword) throws LoginException; - - /** - * @see LoginService#loginTrusted(String, String, java.util.Locale) - * - * @deprecated Use {@link AuthenticationManager} with {@link TrustedClientCredentials} - */ - @Deprecated - UserSession loginTrusted(String login, String password, Locale locale) throws LoginException; - - /** - * @deprecated Use {@link AuthenticationManager} with {@link TrustedClientCredentials} - */ - @Deprecated - UserSession loginTrusted(String login, String password, Locale locale, Map params) - throws LoginException; - - /** - * @deprecated Use {@link AuthenticationManager} with {@link RememberMeCredentials} - */ - @Deprecated - UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException; - - /** - * @deprecated Use {@link AuthenticationManager} with {@link RememberMeCredentials} - */ - @Deprecated - UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) - throws LoginException; - - /** - * @deprecated is not supported any more, returns false - */ - @Deprecated - boolean checkRememberMe(String login, String rememberMeToken); - - /** - * Check credentials of user and return loaded user entity. - * - * @param login login - * @param password user's encrypted password - * @param locale locale - * @param parameters additional parameters - * @return user - * @throws LoginException in case of unsuccessful authentication - * - * @deprecated Use {@link AuthenticationManager#authenticate(Credentials)} with {@link LoginPasswordCredentials} - */ - @Deprecated - User authenticate(String login, String password, Locale locale, Map parameters) - throws LoginException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.security.auth.*; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.UserSessionManager; + +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +/** + * Interface to {@link com.haulmont.cuba.security.app.LoginWorkerBean} + * + * @deprecated Use {@link AuthenticationManager} + */ +@Deprecated +public interface LoginWorker { + + String NAME = "cuba_LoginWorker"; + + /** + * @deprecated Use {@link AuthenticationManager#logout()} + */ + @Deprecated + void logout(); + + /** + * @deprecated Use {@link AuthenticationManager#substituteUser(User)} + */ + @Deprecated + UserSession substituteUser(User substitutedUser); + + /** + * @deprecated User {@link UserSessionManager#findSession(UUID)} + */ + @Nullable + @Deprecated + UserSession getSession(UUID sessionId); + + /** + * Log in from a middleware component. This method should not be exposed to any client tier. + * + * @param login login of a system user + * @return system user session that is not replicated in cluster + * @throws LoginException in case of unsuccessful log in + * + * @deprecated Use {@link AuthenticationManager} with {@link SystemUserCredentials} + */ + @Deprecated + UserSession loginSystem(String login) throws LoginException; + + /** + * Login anonymous session for trusted clients + * + * @return anonymous user session that is not replicated in cluster + * @throws LoginException in case of login problem + * + * @deprecated Use {@link AuthenticationManager} with {@link AnonymousUserCredentials} + */ + @Deprecated + UserSession loginAnonymous() throws LoginException; + + /** + * @deprecated Use {@link AuthenticationManager} with {@link LoginPasswordCredentials} + */ + @Deprecated + UserSession login(String login, String password, Locale locale) throws LoginException; + + /** + * @deprecated Use {@link AuthenticationManager} with {@link LoginPasswordCredentials} + */ + @Deprecated + UserSession login(String login, String password, Locale locale, Map params) throws LoginException; + + /** + * @deprecated Use {@link Authentication} directly. + */ + @Deprecated + UserSession getSystemSession(String trustedClientPassword) throws LoginException; + + /** + * @see LoginService#loginTrusted(String, String, java.util.Locale) + * + * @deprecated Use {@link AuthenticationManager} with {@link TrustedClientCredentials} + */ + @Deprecated + UserSession loginTrusted(String login, String password, Locale locale) throws LoginException; + + /** + * @deprecated Use {@link AuthenticationManager} with {@link TrustedClientCredentials} + */ + @Deprecated + UserSession loginTrusted(String login, String password, Locale locale, Map params) + throws LoginException; + + /** + * @deprecated Use {@link AuthenticationManager} with {@link RememberMeCredentials} + */ + @Deprecated + UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException; + + /** + * @deprecated Use {@link AuthenticationManager} with {@link RememberMeCredentials} + */ + @Deprecated + UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) + throws LoginException; + + /** + * @deprecated is not supported any more, returns false + */ + @Deprecated + boolean checkRememberMe(String login, String rememberMeToken); + + /** + * Check credentials of user and return loaded user entity. + * + * @param login login + * @param password user's encrypted password + * @param locale locale + * @param parameters additional parameters + * @return user + * @throws LoginException in case of unsuccessful authentication + * + * @deprecated Use {@link AuthenticationManager#authenticate(Credentials)} with {@link LoginPasswordCredentials} + */ + @Deprecated + User authenticate(String login, String password, Locale locale, Map parameters) + throws LoginException; } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/LoginWorkerBean.java b/modules/core/src/com/haulmont/cuba/security/app/LoginWorkerBean.java index 04907e07f6..7a49fa692a 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/LoginWorkerBean.java +++ b/modules/core/src/com/haulmont/cuba/security/app/LoginWorkerBean.java @@ -1,196 +1,196 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.auth.*; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.SessionParams; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.TrustedLoginHandler; -import com.haulmont.cuba.security.sys.UserSessionManager; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Class that encapsulates the middleware login/logout functionality. - * - * @see LoginServiceBean - */ -@Component(LoginWorker.NAME) -@Deprecated -public class LoginWorkerBean implements LoginWorker { - - protected static final String MSG_PACK = "com.haulmont.cuba.security"; - - @Inject - protected Messages messages; - - @Inject - protected ServerConfig serverConfig; - - @Inject - protected GlobalConfig globalConfig; - - @Inject - protected UserSessionManager userSessionManager; - - @Inject - protected TrustedLoginHandler trustedLoginHandler; - - @Inject - protected Authentication authentication; - - @Inject - protected AnonymousSessionHolder anonymousSessionHolder; - - @Inject - protected AuthenticationManager authenticationManager; - - @Override - public UserSession login(String login, String password, Locale locale) throws LoginException { - return login(login, password, locale, Collections.emptyMap()); - } - - @Override - public UserSession login(String login, String password, Locale locale, Map params) throws LoginException { - return authenticationManager.login(new LoginPasswordCredentials(login, password, locale, params)).getSession(); - } - - @Override - public UserSession loginSystem(String login) throws LoginException { - return authenticationManager.login(new SystemUserCredentials(login)).getSession(); - } - - @Override - public UserSession loginAnonymous() throws LoginException { - return anonymousSessionHolder.getAnonymousSession(); - } - - @Override - public UserSession getSystemSession(String trustedClientPassword) throws LoginException { - if (!trustedLoginHandler.checkPassword(trustedClientPassword)) { - Locale locale = messages.getTools().getDefaultLocale(); - throw new LoginException(messages.formatMessage(MSG_PACK, "LoginException.InvalidLoginOrPassword", locale, - serverConfig.getJmxUserLogin())); - } - - SecurityContext currentSecContext = AppContext.getSecurityContext(); - UserSession userSession; - try { - // we need to reset security context to prevent reusing current session - AppContext.setSecurityContext(null); - - userSession = authentication.begin(); - authentication.end(); - } finally { - AppContext.setSecurityContext(currentSecContext); - } - - return userSession; - } - - @Override - public UserSession loginTrusted(String login, String password, Locale locale) throws LoginException { - return loginTrusted(login, password, locale, Collections.emptyMap()); - } - - @Override - public UserSession loginTrusted(String login, String password, Locale locale, Map params) throws LoginException { - TrustedClientCredentials credentials = new TrustedClientCredentials(login, password, locale, params); - copyParamsToCredentials(params, credentials); - return authenticationManager.login(credentials).getSession(); - } - - @Override - public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException { - return loginByRememberMe(login, rememberMeToken, locale, Collections.emptyMap()); - } - - @Override - public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) - throws LoginException { - RememberMeCredentials credentials = new RememberMeCredentials(login, rememberMeToken, locale, params); - copyParamsToCredentials(params, credentials); - return authenticationManager.login(credentials).getSession(); - } - - @Override - public void logout() { - authenticationManager.logout(); - } - - @Override - public UserSession substituteUser(User substitutedUser) { - return authenticationManager.substituteUser(substitutedUser); - } - - @Override - public UserSession getSession(UUID sessionId) { - return userSessionManager.findSession(sessionId); - } - - @Override - public boolean checkRememberMe(String login, String rememberMeToken) { - // always return false, this feature is not supported any more - return false; - } - - @Override - public User authenticate(String login, String password, Locale locale, Map params) - throws LoginException { - LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, password, locale, params); - copyParamsToCredentials(params, credentials); - AuthenticationDetails sessionDetails = authenticationManager.authenticate(credentials); - return sessionDetails.getSession().getUser(); - } - - @Deprecated - protected void copyParamsToCredentials(Map params, AbstractClientCredentials credentials) { - // for compatibility only - Object clientType = params.get(ClientType.class.getName()); - if (clientType != null && credentials.getClientType() == null) { - credentials.setClientType(ClientType.valueOf((String) clientType)); - } - Object clientInfo = params.get(SessionParams.CLIENT_INFO.getId()); - if (clientInfo != null && credentials.getClientInfo() == null) { - credentials.setClientInfo((String) clientInfo); - } - Object ipAddress = params.get(SessionParams.IP_ADDERSS.getId()); - if (ipAddress != null && credentials.getIpAddress() == null) { - credentials.setIpAddress((String) ipAddress); - } - Object hostName = params.get(SessionParams.HOST_NAME.getId()); - if (hostName != null) { - credentials.setHostName((String) hostName); - } - if (!globalConfig.getLocaleSelectVisible()) { - credentials.setOverrideLocale(false); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.auth.*; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.SessionParams; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.TrustedLoginHandler; +import com.haulmont.cuba.security.sys.UserSessionManager; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +/** + * Class that encapsulates the middleware login/logout functionality. + * + * @see LoginServiceBean + */ +@Component(LoginWorker.NAME) +@Deprecated +public class LoginWorkerBean implements LoginWorker { + + protected static final String MSG_PACK = "com.haulmont.cuba.security"; + + @Inject + protected Messages messages; + + @Inject + protected ServerConfig serverConfig; + + @Inject + protected GlobalConfig globalConfig; + + @Inject + protected UserSessionManager userSessionManager; + + @Inject + protected TrustedLoginHandler trustedLoginHandler; + + @Inject + protected Authentication authentication; + + @Inject + protected AnonymousSessionHolder anonymousSessionHolder; + + @Inject + protected AuthenticationManager authenticationManager; + + @Override + public UserSession login(String login, String password, Locale locale) throws LoginException { + return login(login, password, locale, Collections.emptyMap()); + } + + @Override + public UserSession login(String login, String password, Locale locale, Map params) throws LoginException { + return authenticationManager.login(new LoginPasswordCredentials(login, password, locale, params)).getSession(); + } + + @Override + public UserSession loginSystem(String login) throws LoginException { + return authenticationManager.login(new SystemUserCredentials(login)).getSession(); + } + + @Override + public UserSession loginAnonymous() throws LoginException { + return anonymousSessionHolder.getAnonymousSession(); + } + + @Override + public UserSession getSystemSession(String trustedClientPassword) throws LoginException { + if (!trustedLoginHandler.checkPassword(trustedClientPassword)) { + Locale locale = messages.getTools().getDefaultLocale(); + throw new LoginException(messages.formatMessage(MSG_PACK, "LoginException.InvalidLoginOrPassword", locale, + serverConfig.getJmxUserLogin())); + } + + SecurityContext currentSecContext = AppContext.getSecurityContext(); + UserSession userSession; + try { + // we need to reset security context to prevent reusing current session + AppContext.setSecurityContext(null); + + userSession = authentication.begin(); + authentication.end(); + } finally { + AppContext.setSecurityContext(currentSecContext); + } + + return userSession; + } + + @Override + public UserSession loginTrusted(String login, String password, Locale locale) throws LoginException { + return loginTrusted(login, password, locale, Collections.emptyMap()); + } + + @Override + public UserSession loginTrusted(String login, String password, Locale locale, Map params) throws LoginException { + TrustedClientCredentials credentials = new TrustedClientCredentials(login, password, locale, params); + copyParamsToCredentials(params, credentials); + return authenticationManager.login(credentials).getSession(); + } + + @Override + public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException { + return loginByRememberMe(login, rememberMeToken, locale, Collections.emptyMap()); + } + + @Override + public UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) + throws LoginException { + RememberMeCredentials credentials = new RememberMeCredentials(login, rememberMeToken, locale, params); + copyParamsToCredentials(params, credentials); + return authenticationManager.login(credentials).getSession(); + } + + @Override + public void logout() { + authenticationManager.logout(); + } + + @Override + public UserSession substituteUser(User substitutedUser) { + return authenticationManager.substituteUser(substitutedUser); + } + + @Override + public UserSession getSession(UUID sessionId) { + return userSessionManager.findSession(sessionId); + } + + @Override + public boolean checkRememberMe(String login, String rememberMeToken) { + // always return false, this feature is not supported any more + return false; + } + + @Override + public User authenticate(String login, String password, Locale locale, Map params) + throws LoginException { + LoginPasswordCredentials credentials = new LoginPasswordCredentials(login, password, locale, params); + copyParamsToCredentials(params, credentials); + AuthenticationDetails sessionDetails = authenticationManager.authenticate(credentials); + return sessionDetails.getSession().getUser(); + } + + @Deprecated + protected void copyParamsToCredentials(Map params, AbstractClientCredentials credentials) { + // for compatibility only + Object clientType = params.get(ClientType.class.getName()); + if (clientType != null && credentials.getClientType() == null) { + credentials.setClientType(ClientType.valueOf((String) clientType)); + } + Object clientInfo = params.get(SessionParams.CLIENT_INFO.getId()); + if (clientInfo != null && credentials.getClientInfo() == null) { + credentials.setClientInfo((String) clientInfo); + } + Object ipAddress = params.get(SessionParams.IP_ADDERSS.getId()); + if (ipAddress != null && credentials.getIpAddress() == null) { + credentials.setIpAddress((String) ipAddress); + } + Object hostName = params.get(SessionParams.HOST_NAME.getId()); + if (hostName != null) { + credentials.setHostName((String) hostName); + } + if (!globalConfig.getLocaleSelectVisible()) { + credentials.setOverrideLocale(false); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/UserManagementServiceBean.java b/modules/core/src/com/haulmont/cuba/security/app/UserManagementServiceBean.java index 2a6d686142..3640b898e1 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/UserManagementServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/security/app/UserManagementServiceBean.java @@ -1,727 +1,727 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.app; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.app.EmailerAPI; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.*; -import groovy.text.SimpleTemplateEngine; -import groovy.text.Template; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.IOException; -import java.io.StringWriter; -import java.util.*; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -@Service(UserManagementService.NAME) -public class UserManagementServiceBean implements UserManagementService { - - private final Logger log = LoggerFactory.getLogger(UserManagementServiceBean.class); - - protected static final String GROUP_COPY_VIEW = "group.copy"; - - protected static final String ROLE_COPY_VIEW = "role.copy"; - - protected static final String MOVE_USER_TO_GROUP_VIEW = "user.moveToGroup"; - - protected static final String RESET_PASSWORD_VIEW = "user.resetPassword"; - - protected static final String CHANGE_PASSWORD_VIEW = "user.changePassword"; - - protected static final String CHECK_PASSWORD_VIEW = "user.check"; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected PasswordEncryption passwordEncryption; - - @Inject - protected EmailerAPI emailerAPI; - - @Inject - protected Resources resources; - - @Inject - protected ServerConfig serverConfig; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected MessageTools messageTools; - - @Inject - protected Security security; - - @Inject - protected Messages messages; - - protected void checkUpdatePermission(Class entityClass) { - checkPermission(entityClass, EntityOp.UPDATE); - } - - protected void checkPermission(Class entityClass, EntityOp op) { - MetaClass metaClass = metadata.getClassNN(entityClass); - - if (!security.isEntityOpPermitted(metaClass, op)) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, metaClass.getName()); - } - } - - @Override - public Group copyAccessGroup(UUID accessGroupId) { - checkNotNullArgument(accessGroupId, "Null access group id"); - checkUpdatePermission(Group.class); - - Group clone = null; - - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - Query groupNamesQuery = em.createQuery("select g.name from sec$Group g"); - @SuppressWarnings("unchecked") - Set groupNames = new HashSet<>(groupNamesQuery.getResultList()); - - Group accessGroup = em.find(Group.class, accessGroupId, GROUP_COPY_VIEW); - if (accessGroup == null) - throw new IllegalStateException("Unable to find specified access group with id: " + accessGroupId); - - clone = cloneGroup(accessGroup, accessGroup.getParent(), groupNames, em); - - tx.commit(); - } finally { - tx.end(); - } - - return clone; - } - - @Override - public Role copyRole(UUID roleId) { - checkNotNullArgument(roleId, "Null access role id"); - checkUpdatePermission(Role.class); - - Role clone = null; - - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - Query roleNamesQuery = em.createQuery("select g.name from sec$Role g"); - @SuppressWarnings("unchecked") - Set roleNames = new HashSet<>(roleNamesQuery.getResultList()); - - Role role = em.find(Role.class, roleId, ROLE_COPY_VIEW); - if (role == null) - throw new IllegalStateException("Unable to find specified role with id: " + roleId); - - clone = cloneRole(role, roleNames, em); - clone.setDefaultRole(false); - - tx.commit(); - } finally { - tx.end(); - } - - return clone; - } - - @Override - public Integer moveUsersToGroup(List userIds, @Nullable UUID targetAccessGroupId) { - checkNotNullArgument(userIds, "Null users list"); - checkUpdatePermission(User.class); - - if (userIds.isEmpty()) - return 0; - - Transaction tx = persistence.getTransaction(); - - int modifiedUsers = 0; - try { - EntityManager em = persistence.getEntityManager(); - - Group targetAccessGroup = null; - if (targetAccessGroupId != null) { - targetAccessGroup = em.find(Group.class, targetAccessGroupId); - if (targetAccessGroup == null) - throw new IllegalStateException("Could not found target access group with id: " + targetAccessGroupId); - } - - TypedQuery query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class); - query.setParameter("userIds", userIds); - query.setViewName(MOVE_USER_TO_GROUP_VIEW); - - List users = query.getResultList(); - if (users == null || users.size() != userIds.size()) - throw new IllegalStateException("Not all users found in database"); - - for (User user : users) { - if (!ObjectUtils.equals(user.getGroup(), targetAccessGroup)) { - user.setGroup(targetAccessGroup); - modifiedUsers++; - } - } - - tx.commit(); - } finally { - tx.end(); - } - return modifiedUsers; - } - - @Override - public Integer changePasswordsAtLogonAndSendEmails(List userIds) { - checkNotNullArgument(userIds, "Null users list"); - checkUpdatePermission(User.class); - - if (userIds.isEmpty()) - return 0; - - Map modifiedUsers = updateUserPasswords(userIds, true); - - // email templates - String resetPasswordBodyTemplate = serverConfig.getResetPasswordEmailBodyTemplate(); - String resetPasswordSubjectTemplate = serverConfig.getResetPasswordEmailSubjectTemplate(); - - SimpleTemplateEngine templateEngine = new SimpleTemplateEngine(); - - Map localizedBodyTemplates = new HashMap<>(); - Map localizedSubjectTemplates = new HashMap<>(); - - // load default - Template bodyDefaultTemplate = loadDefaultTemplate(resetPasswordBodyTemplate, templateEngine); - Template subjectDefaultTemplate = loadDefaultTemplate(resetPasswordSubjectTemplate, templateEngine); - - for (Map.Entry userPasswordEntry : modifiedUsers.entrySet()) { - User user = userPasswordEntry.getKey(); - if (StringUtils.isNotEmpty(user.getEmail())) { - EmailTemplate template = getResetPasswordTemplate(user, templateEngine, - resetPasswordSubjectTemplate, resetPasswordBodyTemplate, - subjectDefaultTemplate, bodyDefaultTemplate, - localizedSubjectTemplates, localizedBodyTemplates); - - String password = userPasswordEntry.getValue(); - sendResetPasswordEmail(user, password, template.getSubjectTemplate(), template.getBodyTemplate()); - } - } - - return modifiedUsers.size(); - } - - @Override - public Map changePasswordsAtLogon(List userIds, boolean generatePassword) { - checkNotNullArgument(userIds, "Null users list"); - - checkUpdatePermission(User.class); - - if (userIds.isEmpty()) - return Collections.emptyMap(); - - Map modifiedUsers = updateUserPasswords(userIds, generatePassword); - Map userPasswords = new LinkedHashMap<>(); - for (Map.Entry entry : modifiedUsers.entrySet()) - userPasswords.put(entry.getKey().getId(), entry.getValue()); - - return userPasswords; - } - - @Override - public boolean checkPassword(UUID userId, String passwordHash) { - checkNotNullArgument(userId, "Null userId"); - checkNotNullArgument(passwordHash, "Null new password hash"); - - User user; - - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - user = em.find(User.class, userId, CHECK_PASSWORD_VIEW); - if (user == null) - throw new RuntimeException("Unable to find user with id: " + userId); - - tx.commit(); - } finally { - tx.end(); - } - - return passwordEncryption.checkPassword(user, passwordHash); - } - - @Override - public void resetRememberMeTokens(List userIds) { - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id in :userIds"); - query.setParameter("userIds", userIds); - query.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Override - public void resetRememberMeTokens() { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - Query query = em.createQuery("delete from sec$RememberMeToken rt"); - query.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Override - public String generateRememberMeToken(UUID userId) { - String token = RandomStringUtils.randomAlphanumeric(RememberMeToken.TOKEN_LENGTH); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - RememberMeToken rememberMeToken = metadata.create(RememberMeToken.class); - rememberMeToken.setToken(token); - rememberMeToken.setUser(em.getReference(User.class, userId)); - - em.persist(rememberMeToken); - - tx.commit(); - } finally { - tx.end(); - } - - return token; - } - - @Override - public List getSessionAttributeNames(UUID groupId) { - Preconditions.checkNotNullArgument(groupId, "groupId is null"); - checkPermission(SessionAttribute.class, EntityOp.READ); - checkUpdatePermission(Group.class); - checkUpdatePermission(Constraint.class); - - Set attributes = new HashSet<>(); - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - Query query = em.createQuery("select a.name from sec$SessionAttribute a where a.group.id = ?1"); - query.setParameter(1, groupId); - //noinspection unchecked - attributes.addAll(query.getResultList()); - - query = em.createQuery("select a.name from sec$GroupHierarchy h join h.parent.sessionAttributes a where h.group.id = ?1"); - query.setParameter(1, groupId); - //noinspection unchecked - attributes.addAll(query.getResultList()); - - tx.commit(); - } - return new ArrayList<>(attributes); - } - - @Override - public UserTimeZone loadOwnTimeZone() { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.timeZone"); - if (user == null) - throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); - tx.commit(); - return new UserTimeZone(user.getTimeZone(), Boolean.TRUE.equals(user.getTimeZoneAuto())); - } finally { - tx.end(); - } - } - - @Override - public void saveOwnTimeZone(UserTimeZone timeZone) { - log.debug("Saving user's time zone settings: " + timeZone); - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.timeZone"); - if (user == null) - throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); - user.setTimeZone(timeZone.name); - user.setTimeZoneAuto(timeZone.auto); - tx.commit(); - } finally { - tx.end(); - } - } - - @Override - public String loadOwnLocale() { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.locale"); - if (user == null) - throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); - tx.commit(); - return user.getLanguage(); - } - } - - @Override - public void saveOwnLocale(String locale) { - UUID userId = userSessionSource.getUserSession().getUser().getId(); - log.debug("Saving user's {} language settings: {}", userId, locale); - - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - User user = em.find(User.class, userId, "user.locale"); - if (user == null) - throw new EntityAccessException(User.class, userId); - - user.setLanguage(locale); - tx.commit(); - } - } - - @Override - public void changeUserPassword(UUID userId, String newPasswordHash) { - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - User user = em.find(User.class, userId, CHANGE_PASSWORD_VIEW); - if (user == null) { - throw new EntityAccessException(User.class, userId); - } - - user.setPassword(newPasswordHash); - user.setChangePasswordAtNextLogon(false); - - // reset remember me for user - Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id=:userId"); - query.setParameter("userId", userId); - query.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - - protected EmailTemplate getResetPasswordTemplate(User user, - SimpleTemplateEngine templateEngine, - String resetPasswordSubjectTemplate, - String resetPasswordBodyTemplate, - Template subjectDefaultTemplate, - Template bodyDefaultTemplate, - Map localizedSubjectTemplates, - Map localizedBodyTemplates) { - - boolean userLocaleIsUnknown = StringUtils.isEmpty(user.getLanguage()); - String locale = userLocaleIsUnknown ? - messageTools.getDefaultLocale().getLanguage() : user.getLanguage(); - - Template bodyTemplate; - if (userLocaleIsUnknown) { - bodyTemplate = bodyDefaultTemplate; - } else { - if (localizedBodyTemplates.containsKey(locale)) - bodyTemplate = localizedBodyTemplates.get(locale); - else { - String templateString = getLocalizedTemplateContent(resetPasswordBodyTemplate, locale); - if (templateString == null) { - log.warn("Reset passwords: Not found email body template for locale: '{}'", locale); - bodyTemplate = bodyDefaultTemplate; - } else { - bodyTemplate = getTemplate(templateEngine, templateString); - } - localizedBodyTemplates.put(locale, bodyTemplate); - } - } - - Template subjectTemplate; - if (userLocaleIsUnknown) { - subjectTemplate = subjectDefaultTemplate; - } else { - if (localizedSubjectTemplates.containsKey(locale)) - subjectTemplate = localizedSubjectTemplates.get(locale); - else { - String templateString = getLocalizedTemplateContent(resetPasswordSubjectTemplate, locale); - if (templateString == null) { - log.warn("Reset passwords: Not found email subject template for locale '{}'", locale); - subjectTemplate = subjectDefaultTemplate; - } else { - subjectTemplate = getTemplate(templateEngine, templateString); - } - localizedSubjectTemplates.put(locale, subjectTemplate); - } - } - - return new EmailTemplate(subjectTemplate, bodyTemplate); - } - - private String getLocalizedTemplateContent(String defaultTemplateName, String locale) { - String localizedTemplate = FilenameUtils.getFullPath(defaultTemplateName) - + FilenameUtils.getBaseName(defaultTemplateName) + - "_" + locale + - "." + FilenameUtils.getExtension(defaultTemplateName); - - return resources.getResourceAsString(localizedTemplate); - } - - protected Template getTemplate(SimpleTemplateEngine templateEngine, String templateString) { - Template bodyTemplate; - try { - bodyTemplate = templateEngine.createTemplate(templateString); - } catch (Exception e) { - throw new RuntimeException("Unable to compile Groovy template", e); - } - return bodyTemplate; - } - - protected Template loadDefaultTemplate(String templatePath, SimpleTemplateEngine templateEngine) { - String defaultTemplateContent = resources.getResourceAsString(templatePath); - if (defaultTemplateContent == null) { - throw new IllegalStateException("Not found default email template for reset passwords operation"); - } - - //noinspection UnnecessaryLocalVariable - Template template = getTemplate(templateEngine, defaultTemplateContent); - return template; - } - - protected void sendResetPasswordEmail(User user, String password, Template subjectTemplate, Template bodyTemplate) { - Transaction tx = persistence.getTransaction(); - String emailBody; - String emailSubject; - try { - Map binding = new HashMap<>(); - binding.put("user", user); - binding.put("password", password); - binding.put("persistence", persistence); - - emailBody = bodyTemplate.make(binding).writeTo(new StringWriter(0)).toString(); - emailSubject = subjectTemplate.make(binding).writeTo(new StringWriter(0)).toString(); - - tx.commit(); - } catch (IOException e) { - throw new RuntimeException("Unable to write Groovy template content", e); - } finally { - tx.end(); - } - - EmailInfo emailInfo = new EmailInfo(user.getEmail(), emailSubject, emailBody); - emailerAPI.sendEmailAsync(emailInfo); - } - - protected Map updateUserPasswords(List userIds, boolean generatePassword) { - Map modifiedUsers = new LinkedHashMap<>(); - - Transaction tx = persistence.getTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - - TypedQuery query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class); - query.setParameter("userIds", userIds); - query.setViewName(RESET_PASSWORD_VIEW); - - List users = query.getResultList(); - - if (users == null || users.size() != userIds.size()) - throw new IllegalStateException("Not all users found in database"); - - for (User user : users) { - String password = null; - if (generatePassword) { - password = passwordEncryption.generateRandomPassword(); - - String passwordHash = passwordEncryption.getPasswordHash(user.getId(), password); - user.setPassword(passwordHash); - } - user.setChangePasswordAtNextLogon(true); - - modifiedUsers.put(user, password); - } - - resetRememberMeTokens(userIds); - - tx.commit(); - } finally { - tx.end(); - } - - return modifiedUsers; - } - - protected Role cloneRole(Role role, Set roleNames, EntityManager em) { - Role roleClone = metadata.create(Role.class); - - String newRoleName = generateName(role.getName(), roleNames); - roleClone.setName(newRoleName); - roleClone.setType(role.getType()); - roleClone.setDefaultRole(role.getDefaultRole()); - roleClone.setLocName(role.getLocName()); - roleClone.setDescription(role.getDescription()); - - em.persist(roleClone); - - if (role.getPermissions() != null) { - for (Permission permission : role.getPermissions()) { - Permission permissionClone = clonePermission(permission, roleClone); - em.persist(permissionClone); - } - } - - return roleClone; - } - - protected Group cloneGroup(Group group, Group parent, Set groupNames, EntityManager em) { - Group groupClone = metadata.create(Group.class); - - String newGroupName = generateName(group.getName(), groupNames); - groupClone.setName(newGroupName); - groupNames.add(newGroupName); - - groupClone.setParent(parent); - - em.persist(groupClone); - // fire hierarchy listeners - em.flush(); - - if (group.getConstraints() != null) { - for (Constraint constraint : group.getConstraints()) { - Constraint constraintClone = cloneConstraint(constraint, groupClone); - em.persist(constraintClone); - } - } - - if (group.getSessionAttributes() != null) { - for (SessionAttribute attribute : group.getSessionAttributes()) { - SessionAttribute attributeClone = cloneSessionAttribute(attribute, groupClone); - em.persist(attributeClone); - } - } - - TypedQuery query = em.createQuery("select g from sec$Group g where g.parent.id = :group", Group.class); - query.setParameter("group", group); - - List subGroups = query.getResultList(); - if (subGroups != null && subGroups.size() > 0) { - for (Group subGroup : subGroups) { - cloneGroup(subGroup, groupClone, groupNames, em); - } - } - - return groupClone; - } - - protected String generateName(String originalGroupName, Set groupNames) { - String newGroupName; - - int i = 1; - do { - newGroupName = originalGroupName + " (" + i + ")"; - i++; - } while (groupNames.contains(newGroupName)); - - return newGroupName; - } - - protected SessionAttribute cloneSessionAttribute(SessionAttribute attribute, Group group) { - SessionAttribute resultAttribute = metadata.create(SessionAttribute.class); - resultAttribute.setName(attribute.getName()); - resultAttribute.setDatatype(attribute.getDatatype()); - resultAttribute.setStringValue(attribute.getStringValue()); - resultAttribute.setGroup(group); - return resultAttribute; - } - - protected Constraint cloneConstraint(Constraint constraint, Group group) { - Constraint resultConstraint = metadata.create(Constraint.class); - resultConstraint.setEntityName(constraint.getEntityName()); - resultConstraint.setCode(constraint.getCode()); - resultConstraint.setCheckType(constraint.getCheckType()); - resultConstraint.setOperationType(constraint.getOperationType()); - resultConstraint.setJoinClause(constraint.getJoinClause()); - resultConstraint.setWhereClause(constraint.getWhereClause()); - resultConstraint.setGroovyScript(constraint.getGroovyScript()); - resultConstraint.setFilterXml(constraint.getFilterXml()); - resultConstraint.setIsActive(constraint.getIsActive()); - resultConstraint.setGroup(group); - return resultConstraint; - } - - protected Permission clonePermission(Permission permission, Role role) { - Permission resultPermission = metadata.create(Permission.class); - resultPermission.setValue(permission.getValue()); - resultPermission.setType(permission.getType()); - resultPermission.setTarget(permission.getTarget()); - resultPermission.setRole(role); - - return resultPermission; - } - - /** - * Template pair : subject + body - */ - protected static class EmailTemplate { - - private Template subjectTemplate; - private Template bodyTemplate; - - private EmailTemplate(Template subjectTemplate, Template bodyTemplate) { - this.subjectTemplate = subjectTemplate; - this.bodyTemplate = bodyTemplate; - } - - public Template getSubjectTemplate() { - return subjectTemplate; - } - - public Template getBodyTemplate() { - return bodyTemplate; - } - } - - @Override - public boolean isUsersRemovingAllowed(Collection userLogins) { - return !userLogins.contains(serverConfig.getJmxUserLogin()) && !userLogins.contains(serverConfig.getAnonymousLogin()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.app; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.app.EmailerAPI; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.*; +import groovy.text.SimpleTemplateEngine; +import groovy.text.Template; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +@Service(UserManagementService.NAME) +public class UserManagementServiceBean implements UserManagementService { + + private final Logger log = LoggerFactory.getLogger(UserManagementServiceBean.class); + + protected static final String GROUP_COPY_VIEW = "group.copy"; + + protected static final String ROLE_COPY_VIEW = "role.copy"; + + protected static final String MOVE_USER_TO_GROUP_VIEW = "user.moveToGroup"; + + protected static final String RESET_PASSWORD_VIEW = "user.resetPassword"; + + protected static final String CHANGE_PASSWORD_VIEW = "user.changePassword"; + + protected static final String CHECK_PASSWORD_VIEW = "user.check"; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected PasswordEncryption passwordEncryption; + + @Inject + protected EmailerAPI emailerAPI; + + @Inject + protected Resources resources; + + @Inject + protected ServerConfig serverConfig; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected MessageTools messageTools; + + @Inject + protected Security security; + + @Inject + protected Messages messages; + + protected void checkUpdatePermission(Class entityClass) { + checkPermission(entityClass, EntityOp.UPDATE); + } + + protected void checkPermission(Class entityClass, EntityOp op) { + MetaClass metaClass = metadata.getClassNN(entityClass); + + if (!security.isEntityOpPermitted(metaClass, op)) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, metaClass.getName()); + } + } + + @Override + public Group copyAccessGroup(UUID accessGroupId) { + checkNotNullArgument(accessGroupId, "Null access group id"); + checkUpdatePermission(Group.class); + + Group clone = null; + + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + Query groupNamesQuery = em.createQuery("select g.name from sec$Group g"); + @SuppressWarnings("unchecked") + Set groupNames = new HashSet<>(groupNamesQuery.getResultList()); + + Group accessGroup = em.find(Group.class, accessGroupId, GROUP_COPY_VIEW); + if (accessGroup == null) + throw new IllegalStateException("Unable to find specified access group with id: " + accessGroupId); + + clone = cloneGroup(accessGroup, accessGroup.getParent(), groupNames, em); + + tx.commit(); + } finally { + tx.end(); + } + + return clone; + } + + @Override + public Role copyRole(UUID roleId) { + checkNotNullArgument(roleId, "Null access role id"); + checkUpdatePermission(Role.class); + + Role clone = null; + + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + Query roleNamesQuery = em.createQuery("select g.name from sec$Role g"); + @SuppressWarnings("unchecked") + Set roleNames = new HashSet<>(roleNamesQuery.getResultList()); + + Role role = em.find(Role.class, roleId, ROLE_COPY_VIEW); + if (role == null) + throw new IllegalStateException("Unable to find specified role with id: " + roleId); + + clone = cloneRole(role, roleNames, em); + clone.setDefaultRole(false); + + tx.commit(); + } finally { + tx.end(); + } + + return clone; + } + + @Override + public Integer moveUsersToGroup(List userIds, @Nullable UUID targetAccessGroupId) { + checkNotNullArgument(userIds, "Null users list"); + checkUpdatePermission(User.class); + + if (userIds.isEmpty()) + return 0; + + Transaction tx = persistence.getTransaction(); + + int modifiedUsers = 0; + try { + EntityManager em = persistence.getEntityManager(); + + Group targetAccessGroup = null; + if (targetAccessGroupId != null) { + targetAccessGroup = em.find(Group.class, targetAccessGroupId); + if (targetAccessGroup == null) + throw new IllegalStateException("Could not found target access group with id: " + targetAccessGroupId); + } + + TypedQuery query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class); + query.setParameter("userIds", userIds); + query.setViewName(MOVE_USER_TO_GROUP_VIEW); + + List users = query.getResultList(); + if (users == null || users.size() != userIds.size()) + throw new IllegalStateException("Not all users found in database"); + + for (User user : users) { + if (!ObjectUtils.equals(user.getGroup(), targetAccessGroup)) { + user.setGroup(targetAccessGroup); + modifiedUsers++; + } + } + + tx.commit(); + } finally { + tx.end(); + } + return modifiedUsers; + } + + @Override + public Integer changePasswordsAtLogonAndSendEmails(List userIds) { + checkNotNullArgument(userIds, "Null users list"); + checkUpdatePermission(User.class); + + if (userIds.isEmpty()) + return 0; + + Map modifiedUsers = updateUserPasswords(userIds, true); + + // email templates + String resetPasswordBodyTemplate = serverConfig.getResetPasswordEmailBodyTemplate(); + String resetPasswordSubjectTemplate = serverConfig.getResetPasswordEmailSubjectTemplate(); + + SimpleTemplateEngine templateEngine = new SimpleTemplateEngine(); + + Map localizedBodyTemplates = new HashMap<>(); + Map localizedSubjectTemplates = new HashMap<>(); + + // load default + Template bodyDefaultTemplate = loadDefaultTemplate(resetPasswordBodyTemplate, templateEngine); + Template subjectDefaultTemplate = loadDefaultTemplate(resetPasswordSubjectTemplate, templateEngine); + + for (Map.Entry userPasswordEntry : modifiedUsers.entrySet()) { + User user = userPasswordEntry.getKey(); + if (StringUtils.isNotEmpty(user.getEmail())) { + EmailTemplate template = getResetPasswordTemplate(user, templateEngine, + resetPasswordSubjectTemplate, resetPasswordBodyTemplate, + subjectDefaultTemplate, bodyDefaultTemplate, + localizedSubjectTemplates, localizedBodyTemplates); + + String password = userPasswordEntry.getValue(); + sendResetPasswordEmail(user, password, template.getSubjectTemplate(), template.getBodyTemplate()); + } + } + + return modifiedUsers.size(); + } + + @Override + public Map changePasswordsAtLogon(List userIds, boolean generatePassword) { + checkNotNullArgument(userIds, "Null users list"); + + checkUpdatePermission(User.class); + + if (userIds.isEmpty()) + return Collections.emptyMap(); + + Map modifiedUsers = updateUserPasswords(userIds, generatePassword); + Map userPasswords = new LinkedHashMap<>(); + for (Map.Entry entry : modifiedUsers.entrySet()) + userPasswords.put(entry.getKey().getId(), entry.getValue()); + + return userPasswords; + } + + @Override + public boolean checkPassword(UUID userId, String passwordHash) { + checkNotNullArgument(userId, "Null userId"); + checkNotNullArgument(passwordHash, "Null new password hash"); + + User user; + + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + user = em.find(User.class, userId, CHECK_PASSWORD_VIEW); + if (user == null) + throw new RuntimeException("Unable to find user with id: " + userId); + + tx.commit(); + } finally { + tx.end(); + } + + return passwordEncryption.checkPassword(user, passwordHash); + } + + @Override + public void resetRememberMeTokens(List userIds) { + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id in :userIds"); + query.setParameter("userIds", userIds); + query.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Override + public void resetRememberMeTokens() { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + Query query = em.createQuery("delete from sec$RememberMeToken rt"); + query.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Override + public String generateRememberMeToken(UUID userId) { + String token = RandomStringUtils.randomAlphanumeric(RememberMeToken.TOKEN_LENGTH); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + RememberMeToken rememberMeToken = metadata.create(RememberMeToken.class); + rememberMeToken.setToken(token); + rememberMeToken.setUser(em.getReference(User.class, userId)); + + em.persist(rememberMeToken); + + tx.commit(); + } finally { + tx.end(); + } + + return token; + } + + @Override + public List getSessionAttributeNames(UUID groupId) { + Preconditions.checkNotNullArgument(groupId, "groupId is null"); + checkPermission(SessionAttribute.class, EntityOp.READ); + checkUpdatePermission(Group.class); + checkUpdatePermission(Constraint.class); + + Set attributes = new HashSet<>(); + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + Query query = em.createQuery("select a.name from sec$SessionAttribute a where a.group.id = ?1"); + query.setParameter(1, groupId); + //noinspection unchecked + attributes.addAll(query.getResultList()); + + query = em.createQuery("select a.name from sec$GroupHierarchy h join h.parent.sessionAttributes a where h.group.id = ?1"); + query.setParameter(1, groupId); + //noinspection unchecked + attributes.addAll(query.getResultList()); + + tx.commit(); + } + return new ArrayList<>(attributes); + } + + @Override + public UserTimeZone loadOwnTimeZone() { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.timeZone"); + if (user == null) + throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); + tx.commit(); + return new UserTimeZone(user.getTimeZone(), Boolean.TRUE.equals(user.getTimeZoneAuto())); + } finally { + tx.end(); + } + } + + @Override + public void saveOwnTimeZone(UserTimeZone timeZone) { + log.debug("Saving user's time zone settings: " + timeZone); + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.timeZone"); + if (user == null) + throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); + user.setTimeZone(timeZone.name); + user.setTimeZoneAuto(timeZone.auto); + tx.commit(); + } finally { + tx.end(); + } + } + + @Override + public String loadOwnLocale() { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + User user = em.find(User.class, userSessionSource.getUserSession().getUser().getId(), "user.locale"); + if (user == null) + throw new EntityAccessException(User.class, userSessionSource.getUserSession().getUser().getId()); + tx.commit(); + return user.getLanguage(); + } + } + + @Override + public void saveOwnLocale(String locale) { + UUID userId = userSessionSource.getUserSession().getUser().getId(); + log.debug("Saving user's {} language settings: {}", userId, locale); + + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + User user = em.find(User.class, userId, "user.locale"); + if (user == null) + throw new EntityAccessException(User.class, userId); + + user.setLanguage(locale); + tx.commit(); + } + } + + @Override + public void changeUserPassword(UUID userId, String newPasswordHash) { + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + User user = em.find(User.class, userId, CHANGE_PASSWORD_VIEW); + if (user == null) { + throw new EntityAccessException(User.class, userId); + } + + user.setPassword(newPasswordHash); + user.setChangePasswordAtNextLogon(false); + + // reset remember me for user + Query query = em.createQuery("delete from sec$RememberMeToken rt where rt.user.id=:userId"); + query.setParameter("userId", userId); + query.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + + protected EmailTemplate getResetPasswordTemplate(User user, + SimpleTemplateEngine templateEngine, + String resetPasswordSubjectTemplate, + String resetPasswordBodyTemplate, + Template subjectDefaultTemplate, + Template bodyDefaultTemplate, + Map localizedSubjectTemplates, + Map localizedBodyTemplates) { + + boolean userLocaleIsUnknown = StringUtils.isEmpty(user.getLanguage()); + String locale = userLocaleIsUnknown ? + messageTools.getDefaultLocale().getLanguage() : user.getLanguage(); + + Template bodyTemplate; + if (userLocaleIsUnknown) { + bodyTemplate = bodyDefaultTemplate; + } else { + if (localizedBodyTemplates.containsKey(locale)) + bodyTemplate = localizedBodyTemplates.get(locale); + else { + String templateString = getLocalizedTemplateContent(resetPasswordBodyTemplate, locale); + if (templateString == null) { + log.warn("Reset passwords: Not found email body template for locale: '{}'", locale); + bodyTemplate = bodyDefaultTemplate; + } else { + bodyTemplate = getTemplate(templateEngine, templateString); + } + localizedBodyTemplates.put(locale, bodyTemplate); + } + } + + Template subjectTemplate; + if (userLocaleIsUnknown) { + subjectTemplate = subjectDefaultTemplate; + } else { + if (localizedSubjectTemplates.containsKey(locale)) + subjectTemplate = localizedSubjectTemplates.get(locale); + else { + String templateString = getLocalizedTemplateContent(resetPasswordSubjectTemplate, locale); + if (templateString == null) { + log.warn("Reset passwords: Not found email subject template for locale '{}'", locale); + subjectTemplate = subjectDefaultTemplate; + } else { + subjectTemplate = getTemplate(templateEngine, templateString); + } + localizedSubjectTemplates.put(locale, subjectTemplate); + } + } + + return new EmailTemplate(subjectTemplate, bodyTemplate); + } + + private String getLocalizedTemplateContent(String defaultTemplateName, String locale) { + String localizedTemplate = FilenameUtils.getFullPath(defaultTemplateName) + + FilenameUtils.getBaseName(defaultTemplateName) + + "_" + locale + + "." + FilenameUtils.getExtension(defaultTemplateName); + + return resources.getResourceAsString(localizedTemplate); + } + + protected Template getTemplate(SimpleTemplateEngine templateEngine, String templateString) { + Template bodyTemplate; + try { + bodyTemplate = templateEngine.createTemplate(templateString); + } catch (Exception e) { + throw new RuntimeException("Unable to compile Groovy template", e); + } + return bodyTemplate; + } + + protected Template loadDefaultTemplate(String templatePath, SimpleTemplateEngine templateEngine) { + String defaultTemplateContent = resources.getResourceAsString(templatePath); + if (defaultTemplateContent == null) { + throw new IllegalStateException("Not found default email template for reset passwords operation"); + } + + //noinspection UnnecessaryLocalVariable + Template template = getTemplate(templateEngine, defaultTemplateContent); + return template; + } + + protected void sendResetPasswordEmail(User user, String password, Template subjectTemplate, Template bodyTemplate) { + Transaction tx = persistence.getTransaction(); + String emailBody; + String emailSubject; + try { + Map binding = new HashMap<>(); + binding.put("user", user); + binding.put("password", password); + binding.put("persistence", persistence); + + emailBody = bodyTemplate.make(binding).writeTo(new StringWriter(0)).toString(); + emailSubject = subjectTemplate.make(binding).writeTo(new StringWriter(0)).toString(); + + tx.commit(); + } catch (IOException e) { + throw new RuntimeException("Unable to write Groovy template content", e); + } finally { + tx.end(); + } + + EmailInfo emailInfo = new EmailInfo(user.getEmail(), emailSubject, emailBody); + emailerAPI.sendEmailAsync(emailInfo); + } + + protected Map updateUserPasswords(List userIds, boolean generatePassword) { + Map modifiedUsers = new LinkedHashMap<>(); + + Transaction tx = persistence.getTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + + TypedQuery query = em.createQuery("select u from sec$User u where u.id in :userIds", User.class); + query.setParameter("userIds", userIds); + query.setViewName(RESET_PASSWORD_VIEW); + + List users = query.getResultList(); + + if (users == null || users.size() != userIds.size()) + throw new IllegalStateException("Not all users found in database"); + + for (User user : users) { + String password = null; + if (generatePassword) { + password = passwordEncryption.generateRandomPassword(); + + String passwordHash = passwordEncryption.getPasswordHash(user.getId(), password); + user.setPassword(passwordHash); + } + user.setChangePasswordAtNextLogon(true); + + modifiedUsers.put(user, password); + } + + resetRememberMeTokens(userIds); + + tx.commit(); + } finally { + tx.end(); + } + + return modifiedUsers; + } + + protected Role cloneRole(Role role, Set roleNames, EntityManager em) { + Role roleClone = metadata.create(Role.class); + + String newRoleName = generateName(role.getName(), roleNames); + roleClone.setName(newRoleName); + roleClone.setType(role.getType()); + roleClone.setDefaultRole(role.getDefaultRole()); + roleClone.setLocName(role.getLocName()); + roleClone.setDescription(role.getDescription()); + + em.persist(roleClone); + + if (role.getPermissions() != null) { + for (Permission permission : role.getPermissions()) { + Permission permissionClone = clonePermission(permission, roleClone); + em.persist(permissionClone); + } + } + + return roleClone; + } + + protected Group cloneGroup(Group group, Group parent, Set groupNames, EntityManager em) { + Group groupClone = metadata.create(Group.class); + + String newGroupName = generateName(group.getName(), groupNames); + groupClone.setName(newGroupName); + groupNames.add(newGroupName); + + groupClone.setParent(parent); + + em.persist(groupClone); + // fire hierarchy listeners + em.flush(); + + if (group.getConstraints() != null) { + for (Constraint constraint : group.getConstraints()) { + Constraint constraintClone = cloneConstraint(constraint, groupClone); + em.persist(constraintClone); + } + } + + if (group.getSessionAttributes() != null) { + for (SessionAttribute attribute : group.getSessionAttributes()) { + SessionAttribute attributeClone = cloneSessionAttribute(attribute, groupClone); + em.persist(attributeClone); + } + } + + TypedQuery query = em.createQuery("select g from sec$Group g where g.parent.id = :group", Group.class); + query.setParameter("group", group); + + List subGroups = query.getResultList(); + if (subGroups != null && subGroups.size() > 0) { + for (Group subGroup : subGroups) { + cloneGroup(subGroup, groupClone, groupNames, em); + } + } + + return groupClone; + } + + protected String generateName(String originalGroupName, Set groupNames) { + String newGroupName; + + int i = 1; + do { + newGroupName = originalGroupName + " (" + i + ")"; + i++; + } while (groupNames.contains(newGroupName)); + + return newGroupName; + } + + protected SessionAttribute cloneSessionAttribute(SessionAttribute attribute, Group group) { + SessionAttribute resultAttribute = metadata.create(SessionAttribute.class); + resultAttribute.setName(attribute.getName()); + resultAttribute.setDatatype(attribute.getDatatype()); + resultAttribute.setStringValue(attribute.getStringValue()); + resultAttribute.setGroup(group); + return resultAttribute; + } + + protected Constraint cloneConstraint(Constraint constraint, Group group) { + Constraint resultConstraint = metadata.create(Constraint.class); + resultConstraint.setEntityName(constraint.getEntityName()); + resultConstraint.setCode(constraint.getCode()); + resultConstraint.setCheckType(constraint.getCheckType()); + resultConstraint.setOperationType(constraint.getOperationType()); + resultConstraint.setJoinClause(constraint.getJoinClause()); + resultConstraint.setWhereClause(constraint.getWhereClause()); + resultConstraint.setGroovyScript(constraint.getGroovyScript()); + resultConstraint.setFilterXml(constraint.getFilterXml()); + resultConstraint.setIsActive(constraint.getIsActive()); + resultConstraint.setGroup(group); + return resultConstraint; + } + + protected Permission clonePermission(Permission permission, Role role) { + Permission resultPermission = metadata.create(Permission.class); + resultPermission.setValue(permission.getValue()); + resultPermission.setType(permission.getType()); + resultPermission.setTarget(permission.getTarget()); + resultPermission.setRole(role); + + return resultPermission; + } + + /** + * Template pair : subject + body + */ + protected static class EmailTemplate { + + private Template subjectTemplate; + private Template bodyTemplate; + + private EmailTemplate(Template subjectTemplate, Template bodyTemplate) { + this.subjectTemplate = subjectTemplate; + this.bodyTemplate = bodyTemplate; + } + + public Template getSubjectTemplate() { + return subjectTemplate; + } + + public Template getBodyTemplate() { + return bodyTemplate; + } + } + + @Override + public boolean isUsersRemovingAllowed(Collection userLogins) { + return !userLogins.contains(serverConfig.getJmxUserLogin()) && !userLogins.contains(serverConfig.getAnonymousLogin()); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/UserSessionServiceBean.java b/modules/core/src/com/haulmont/cuba/security/app/UserSessionServiceBean.java index b5f5560527..4cbc3d4dfb 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/UserSessionServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/security/app/UserSessionServiceBean.java @@ -1,177 +1,177 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.security.entity.PermissionType; -import com.haulmont.cuba.security.entity.SessionAction; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserSessionEntity; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.security.sys.UserSessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.Serializable; -import java.util.*; - -/** - * Service facade to active {@link UserSession}s management. - */ -@Service(UserSessionService.NAME) -public class UserSessionServiceBean implements UserSessionService { - public static final String MESSAGE_ATTR_PREFIX = "message-"; - - private final Logger log = LoggerFactory.getLogger(UserSessionServiceBean.class); - - @Inject - private UserSessionManager userSessionManager; - - @Inject - private UserSessionsAPI userSessions; - - @Inject - private UserSessionLog userSessionLog; - - @Inject - private UserSessionSource userSessionSource; - - @Inject - private TimeSource timeSource; - - @Override - public UserSession getUserSession(UUID sessionId) { - UserSession userSession = userSessionManager.getSession(sessionId); - return userSession; - } - - @Override - public void setSessionAttribute(UUID sessionId, String name, Serializable value) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.setAttribute(name, value); - userSessions.propagate(sessionId); - } - - @Override - public void removeSessionAttribute(UUID sessionId, String name) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.removeAttribute(name); - userSessions.propagate(sessionId); - } - - @Override - public void setSessionLocale(UUID sessionId, Locale locale) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.setLocale(locale); - userSessions.propagate(sessionId); - } - - @Override - public void setSessionTimeZone(UUID sessionId, TimeZone timeZone) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.setTimeZone(timeZone); - userSessions.propagate(sessionId); - } - - @Override - public void setSessionAddress(UUID sessionId, String address) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.setAddress(address); - userSessions.propagate(sessionId); - } - - @Override - public void setSessionClientInfo(UUID sessionId, String clientInfo) { - UserSession userSession = userSessionManager.getSession(sessionId); - userSession.setClientInfo(clientInfo); - userSessions.propagate(sessionId); - } - - @Override - public Collection getUserSessionInfo() { - return userSessions.getUserSessionInfo(); - } - - @Override - public void killSession(UUID id) { - UserSession userSession = userSessions.get(id, false); - userSessionLog.updateSessionLogRecord(userSession, SessionAction.TERMINATION); - userSessions.killSession(id); - } - - @Override - public void postMessage(List sessionIds, String message) { - long time = timeSource.currentTimeMillis(); - for (UUID sessionId : sessionIds) { - UserSession userSession = userSessionManager.findSession(sessionId); - if (userSession != null) { - userSession.setAttribute(MESSAGE_ATTR_PREFIX + time, message); - userSessions.propagate(sessionId); - } - } - } - - @Override - @Nullable - public String getMessages() { - UserSession userSession = userSessionSource.getUserSession(); - try { - Map messages = new TreeMap<>(); - for (String name : userSession.getAttributeNames()) { - if (name.startsWith(MESSAGE_ATTR_PREFIX)) { - Object message = userSession.getAttribute(name); - if (message instanceof String) - messages.put(name, (String) message); - } - } - if (!messages.isEmpty()) { - Datatype datatype = Datatypes.getNN(Date.class); - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : messages.entrySet()) { - if (sb.length() != 0) - sb.append("\n\n"); - - String name = entry.getKey(); - String dateTimeMillis = name.substring(MESSAGE_ATTR_PREFIX.length()); - Date dateTime = new Date(Long.parseLong(dateTimeMillis)); - - sb.append(datatype.format(dateTime, userSession.getLocale())).append("\n"); - sb.append(entry.getValue()); - - userSession.removeAttribute(name); - } - userSessions.propagate(userSession.getId()); - return sb.toString(); - } - } catch (Throwable e) { - log.warn("Error getting messages for session " + userSession, e); - } - return null; - } - - @Override - public Integer getPermissionValue(User user, PermissionType permissionType, String target) { - return userSessionManager.getPermissionValue(user, permissionType, target); - } - +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.security.entity.PermissionType; +import com.haulmont.cuba.security.entity.SessionAction; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserSessionEntity; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.security.sys.UserSessionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.Serializable; +import java.util.*; + +/** + * Service facade to active {@link UserSession}s management. + */ +@Service(UserSessionService.NAME) +public class UserSessionServiceBean implements UserSessionService { + public static final String MESSAGE_ATTR_PREFIX = "message-"; + + private final Logger log = LoggerFactory.getLogger(UserSessionServiceBean.class); + + @Inject + private UserSessionManager userSessionManager; + + @Inject + private UserSessionsAPI userSessions; + + @Inject + private UserSessionLog userSessionLog; + + @Inject + private UserSessionSource userSessionSource; + + @Inject + private TimeSource timeSource; + + @Override + public UserSession getUserSession(UUID sessionId) { + UserSession userSession = userSessionManager.getSession(sessionId); + return userSession; + } + + @Override + public void setSessionAttribute(UUID sessionId, String name, Serializable value) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.setAttribute(name, value); + userSessions.propagate(sessionId); + } + + @Override + public void removeSessionAttribute(UUID sessionId, String name) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.removeAttribute(name); + userSessions.propagate(sessionId); + } + + @Override + public void setSessionLocale(UUID sessionId, Locale locale) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.setLocale(locale); + userSessions.propagate(sessionId); + } + + @Override + public void setSessionTimeZone(UUID sessionId, TimeZone timeZone) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.setTimeZone(timeZone); + userSessions.propagate(sessionId); + } + + @Override + public void setSessionAddress(UUID sessionId, String address) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.setAddress(address); + userSessions.propagate(sessionId); + } + + @Override + public void setSessionClientInfo(UUID sessionId, String clientInfo) { + UserSession userSession = userSessionManager.getSession(sessionId); + userSession.setClientInfo(clientInfo); + userSessions.propagate(sessionId); + } + + @Override + public Collection getUserSessionInfo() { + return userSessions.getUserSessionInfo(); + } + + @Override + public void killSession(UUID id) { + UserSession userSession = userSessions.get(id, false); + userSessionLog.updateSessionLogRecord(userSession, SessionAction.TERMINATION); + userSessions.killSession(id); + } + + @Override + public void postMessage(List sessionIds, String message) { + long time = timeSource.currentTimeMillis(); + for (UUID sessionId : sessionIds) { + UserSession userSession = userSessionManager.findSession(sessionId); + if (userSession != null) { + userSession.setAttribute(MESSAGE_ATTR_PREFIX + time, message); + userSessions.propagate(sessionId); + } + } + } + + @Override + @Nullable + public String getMessages() { + UserSession userSession = userSessionSource.getUserSession(); + try { + Map messages = new TreeMap<>(); + for (String name : userSession.getAttributeNames()) { + if (name.startsWith(MESSAGE_ATTR_PREFIX)) { + Object message = userSession.getAttribute(name); + if (message instanceof String) + messages.put(name, (String) message); + } + } + if (!messages.isEmpty()) { + Datatype datatype = Datatypes.getNN(Date.class); + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : messages.entrySet()) { + if (sb.length() != 0) + sb.append("\n\n"); + + String name = entry.getKey(); + String dateTimeMillis = name.substring(MESSAGE_ATTR_PREFIX.length()); + Date dateTime = new Date(Long.parseLong(dateTimeMillis)); + + sb.append(datatype.format(dateTime, userSession.getLocale())).append("\n"); + sb.append(entry.getValue()); + + userSession.removeAttribute(name); + } + userSessions.propagate(userSession.getId()); + return sb.toString(); + } + } catch (Throwable e) { + log.warn("Error getting messages for session " + userSession, e); + } + return null; + } + + @Override + public Integer getPermissionValue(User user, PermissionType permissionType, String target) { + return userSessionManager.getPermissionValue(user, permissionType, target); + } + } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/UserSessions.java b/modules/core/src/com/haulmont/cuba/security/app/UserSessions.java index b588172184..9c57226852 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/UserSessions.java +++ b/modules/core/src/com/haulmont/cuba/security/app/UserSessions.java @@ -1,346 +1,346 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.app.ClusterListener; -import com.haulmont.cuba.core.app.ClusterManagerAPI; -import com.haulmont.cuba.core.app.ServerConfig; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.security.entity.SessionAction; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserSessionEntity; -import com.haulmont.cuba.security.global.UserSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.*; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * User sessions distributed cache. - */ -@Component(UserSessionsAPI.NAME) -public class UserSessions implements UserSessionsAPI { - - protected static class UserSessionInfo implements Serializable { - private static final long serialVersionUID = -4834267718111570841L; - - protected final UserSession session; - protected final long since; - protected volatile long lastUsedTs; // set to 0 when propagating removal to cluster - protected volatile long lastSentTs; - - public UserSessionInfo(UserSession session, long now) { - this.session = session; - this.since = now; - this.lastUsedTs = now; - this.lastSentTs = now; - } - - public UserSession getSession() { - return session; - } - - public long getSince() { - return since; - } - - public long getLastUsedTs() { - return lastUsedTs; - } - - public long getLastSentTs() { - return lastSentTs; - } - - @Override - public String toString() { - return String.format("%s, since: %s, lastUsed: %s", - session, new Date(since), new Date(lastSentTs)); - } - } - - private Logger log = LoggerFactory.getLogger(UserSessions.class); - - protected Map cache = new ConcurrentHashMap<>(); - - protected volatile int expirationTimeout = 1800; - - protected volatile int sendTimeout = 10; - - protected ClusterManagerAPI clusterManager; - - protected UserSession NO_USER_SESSION; - - protected ServerConfig serverConfig; - - @Inject - protected TimeSource timeSource; - - @Inject - protected Metadata metadata; - - @Inject - protected UserSessionLog userSessionLog; - - public UserSessions() { - User noUser = new User(); - noUser.setLogin("server"); - NO_USER_SESSION = new UserSession( - UUID.fromString("a66abe96-3b9d-11e2-9db2-3860770d7eaf"), noUser, - Collections.emptyList(), Locale.ENGLISH, true) { - @Override - public UUID getId() { - return AppContext.NO_USER_CONTEXT.getSessionId(); - } - }; - } - - @Inject - public void setConfiguration(Configuration configuration) { - serverConfig = configuration.getConfig(ServerConfig.class); - setExpirationTimeoutSec(serverConfig.getUserSessionExpirationTimeoutSec()); - setSendTimeoutSec(serverConfig.getUserSessionSendTimeoutSec()); - } - - @Inject - public void setClusterManager(ClusterManagerAPI clusterManager) { - this.clusterManager = clusterManager; - this.clusterManager.addListener( - UserSessionInfo.class, - new ClusterListener() { - - @Override - public void receive(UserSessionInfo message) { - UUID id = message.session.getId(); - if (message.lastUsedTs == 0) { - log.debug("Removing session due to cluster message: {}", message); - cache.remove(id); - } else { - UserSessionInfo usi = cache.get(id); - if (usi == null || usi.lastUsedTs < message.lastUsedTs) { - cache.put(id, message); - } - } - } - - @Override - public byte[] getState() { - if (cache.isEmpty()) - return new byte[0]; - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - try { - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeInt(cache.size()); - for (UserSessionInfo usi : cache.values()) { - oos.writeObject(usi); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return bos.toByteArray(); - } - - @Override - public void setState(byte[] state) { - if (state == null || state.length == 0) - return; - - ByteArrayInputStream bis = new ByteArrayInputStream(state); - try { - ObjectInputStream ois = new ObjectInputStream(bis); - int size = ois.readInt(); - for (int i = 0; i < size; i++) { - UserSessionInfo usi = (UserSessionInfo) ois.readObject(); - receive(usi); - } - } catch (IOException | ClassNotFoundException e) { - log.error("Error receiving state", e); - } - } - } - ); - } - - @Override - public void add(UserSession session) { - UserSessionInfo usi = new UserSessionInfo(session, timeSource.currentTimeMillis()); - cache.put(session.getId(), usi); - if (!session.isSystem()) { - if (serverConfig.getSyncNewUserSessionReplication()) - clusterManager.sendSync(usi); - else - clusterManager.send(usi); - } - } - - @Override - public void remove(UserSession session) { - UserSessionInfo usi = cache.remove(session.getId()); - if (usi != null) { - log.debug("Removed session: {}", usi); - if (!session.isSystem()) { - usi.lastUsedTs = 0; - clusterManager.send(usi); - } - } - } - - @Nullable - @Override - public UserSession get(UUID id) { - return get(id, false); - } - - @Nullable - @Override - public UserSession get(UUID id, boolean propagate) { - if (!AppContext.isStarted()) - return NO_USER_SESSION; - - UserSessionInfo usi = cache.get(id); - if (usi != null) { - long now = timeSource.currentTimeMillis(); - usi.lastUsedTs = now; - if (propagate && !usi.session.isSystem()) { - if (now > (usi.lastSentTs + sendTimeout * 1000)) { - usi.lastSentTs = now; - clusterManager.send(usi); - } - } - return usi.session; - } - return null; - } - - @Override - public void propagate(UUID id) { - UserSessionInfo usi = cache.get(id); - if (usi != null) { - long now = timeSource.currentTimeMillis(); - usi.lastUsedTs = now; - usi.lastSentTs = now; - clusterManager.send(usi); - } - } - - @Override - public int getExpirationTimeoutSec() { - return expirationTimeout; - } - - @Override - public void setExpirationTimeoutSec(int value) { - expirationTimeout = value; - } - - @Override - public int getSendTimeoutSec() { - return sendTimeout; - } - - @Override - public void setSendTimeoutSec(int timeout) { - this.sendTimeout = timeout; - } - - @Override - public Collection getUserSessionInfo() { - ArrayList sessionInfoList = new ArrayList<>(); - for (UserSessionInfo nfo : cache.values()) { - UserSessionEntity use = createUserSessionEntity(nfo.session, nfo.since, nfo.lastUsedTs); - sessionInfoList.add(use); - } - return sessionInfoList; - } - - protected UserSessionEntity createUserSessionEntity(UserSession session, long since, long lastUsedTs) { - UserSessionEntity use = metadata.create(UserSessionEntity.class); - use.setId(session.getId()); - use.setLogin(session.getUser().getLoginLowerCase()); - use.setUserName(session.getUser().getName()); - use.setAddress(session.getAddress()); - use.setClientInfo(session.getClientInfo()); - Date currSince = timeSource.currentTimestamp(); - currSince.setTime(since); - use.setSince(currSince); - Date last = timeSource.currentTimestamp(); - last.setTime(lastUsedTs); - use.setLastUsedTs(last); - use.setSystem(session.isSystem()); - return use; - } - - @Override - public void killSession(UUID id) { - UserSessionInfo usi = cache.remove(id); - - if (usi != null) { - log.debug("Killed session: {}", usi); - - usi.lastUsedTs = 0; - clusterManager.send(usi); - } - } - - @Override - public List findUserSessionsByAttribute(String attributeName, Object attributeValue) { - Preconditions.checkNotNullArgument(attributeName); - - List sessionInfos = new ArrayList<>(cache.values()); - - //noinspection UnnecessaryLocalVariable - List sessionIds = sessionInfos.stream() - .filter(usInfo -> Objects.equals(usInfo.session.getAttribute(attributeName), attributeValue)) - .map(userSessionInfo -> userSessionInfo.session.getId()) - .collect(Collectors.toList()); - - return sessionIds; - } - - @Override - public void processEviction() { - if (!AppContext.isStarted()) - return; - - log.trace("Processing eviction"); - long now = timeSource.currentTimeMillis(); - for (Iterator it = cache.values().iterator(); it.hasNext();) { - UserSessionInfo usi = it.next(); - if (!usi.session.isSystem() && now > (usi.lastUsedTs + expirationTimeout * 1000)) { - log.debug("Removing session due to timeout: {}", usi); - - userSessionLog.updateSessionLogRecord(usi.getSession(), SessionAction.EXPIRATION); - it.remove(); - - usi.lastUsedTs = 0; - clusterManager.send(usi); - } - } - } - +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.app.ClusterListener; +import com.haulmont.cuba.core.app.ClusterManagerAPI; +import com.haulmont.cuba.core.app.ServerConfig; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.security.entity.SessionAction; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserSessionEntity; +import com.haulmont.cuba.security.global.UserSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * User sessions distributed cache. + */ +@Component(UserSessionsAPI.NAME) +public class UserSessions implements UserSessionsAPI { + + protected static class UserSessionInfo implements Serializable { + private static final long serialVersionUID = -4834267718111570841L; + + protected final UserSession session; + protected final long since; + protected volatile long lastUsedTs; // set to 0 when propagating removal to cluster + protected volatile long lastSentTs; + + public UserSessionInfo(UserSession session, long now) { + this.session = session; + this.since = now; + this.lastUsedTs = now; + this.lastSentTs = now; + } + + public UserSession getSession() { + return session; + } + + public long getSince() { + return since; + } + + public long getLastUsedTs() { + return lastUsedTs; + } + + public long getLastSentTs() { + return lastSentTs; + } + + @Override + public String toString() { + return String.format("%s, since: %s, lastUsed: %s", + session, new Date(since), new Date(lastSentTs)); + } + } + + private Logger log = LoggerFactory.getLogger(UserSessions.class); + + protected Map cache = new ConcurrentHashMap<>(); + + protected volatile int expirationTimeout = 1800; + + protected volatile int sendTimeout = 10; + + protected ClusterManagerAPI clusterManager; + + protected UserSession NO_USER_SESSION; + + protected ServerConfig serverConfig; + + @Inject + protected TimeSource timeSource; + + @Inject + protected Metadata metadata; + + @Inject + protected UserSessionLog userSessionLog; + + public UserSessions() { + User noUser = new User(); + noUser.setLogin("server"); + NO_USER_SESSION = new UserSession( + UUID.fromString("a66abe96-3b9d-11e2-9db2-3860770d7eaf"), noUser, + Collections.emptyList(), Locale.ENGLISH, true) { + @Override + public UUID getId() { + return AppContext.NO_USER_CONTEXT.getSessionId(); + } + }; + } + + @Inject + public void setConfiguration(Configuration configuration) { + serverConfig = configuration.getConfig(ServerConfig.class); + setExpirationTimeoutSec(serverConfig.getUserSessionExpirationTimeoutSec()); + setSendTimeoutSec(serverConfig.getUserSessionSendTimeoutSec()); + } + + @Inject + public void setClusterManager(ClusterManagerAPI clusterManager) { + this.clusterManager = clusterManager; + this.clusterManager.addListener( + UserSessionInfo.class, + new ClusterListener() { + + @Override + public void receive(UserSessionInfo message) { + UUID id = message.session.getId(); + if (message.lastUsedTs == 0) { + log.debug("Removing session due to cluster message: {}", message); + cache.remove(id); + } else { + UserSessionInfo usi = cache.get(id); + if (usi == null || usi.lastUsedTs < message.lastUsedTs) { + cache.put(id, message); + } + } + } + + @Override + public byte[] getState() { + if (cache.isEmpty()) + return new byte[0]; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeInt(cache.size()); + for (UserSessionInfo usi : cache.values()) { + oos.writeObject(usi); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return bos.toByteArray(); + } + + @Override + public void setState(byte[] state) { + if (state == null || state.length == 0) + return; + + ByteArrayInputStream bis = new ByteArrayInputStream(state); + try { + ObjectInputStream ois = new ObjectInputStream(bis); + int size = ois.readInt(); + for (int i = 0; i < size; i++) { + UserSessionInfo usi = (UserSessionInfo) ois.readObject(); + receive(usi); + } + } catch (IOException | ClassNotFoundException e) { + log.error("Error receiving state", e); + } + } + } + ); + } + + @Override + public void add(UserSession session) { + UserSessionInfo usi = new UserSessionInfo(session, timeSource.currentTimeMillis()); + cache.put(session.getId(), usi); + if (!session.isSystem()) { + if (serverConfig.getSyncNewUserSessionReplication()) + clusterManager.sendSync(usi); + else + clusterManager.send(usi); + } + } + + @Override + public void remove(UserSession session) { + UserSessionInfo usi = cache.remove(session.getId()); + if (usi != null) { + log.debug("Removed session: {}", usi); + if (!session.isSystem()) { + usi.lastUsedTs = 0; + clusterManager.send(usi); + } + } + } + + @Nullable + @Override + public UserSession get(UUID id) { + return get(id, false); + } + + @Nullable + @Override + public UserSession get(UUID id, boolean propagate) { + if (!AppContext.isStarted()) + return NO_USER_SESSION; + + UserSessionInfo usi = cache.get(id); + if (usi != null) { + long now = timeSource.currentTimeMillis(); + usi.lastUsedTs = now; + if (propagate && !usi.session.isSystem()) { + if (now > (usi.lastSentTs + sendTimeout * 1000)) { + usi.lastSentTs = now; + clusterManager.send(usi); + } + } + return usi.session; + } + return null; + } + + @Override + public void propagate(UUID id) { + UserSessionInfo usi = cache.get(id); + if (usi != null) { + long now = timeSource.currentTimeMillis(); + usi.lastUsedTs = now; + usi.lastSentTs = now; + clusterManager.send(usi); + } + } + + @Override + public int getExpirationTimeoutSec() { + return expirationTimeout; + } + + @Override + public void setExpirationTimeoutSec(int value) { + expirationTimeout = value; + } + + @Override + public int getSendTimeoutSec() { + return sendTimeout; + } + + @Override + public void setSendTimeoutSec(int timeout) { + this.sendTimeout = timeout; + } + + @Override + public Collection getUserSessionInfo() { + ArrayList sessionInfoList = new ArrayList<>(); + for (UserSessionInfo nfo : cache.values()) { + UserSessionEntity use = createUserSessionEntity(nfo.session, nfo.since, nfo.lastUsedTs); + sessionInfoList.add(use); + } + return sessionInfoList; + } + + protected UserSessionEntity createUserSessionEntity(UserSession session, long since, long lastUsedTs) { + UserSessionEntity use = metadata.create(UserSessionEntity.class); + use.setId(session.getId()); + use.setLogin(session.getUser().getLoginLowerCase()); + use.setUserName(session.getUser().getName()); + use.setAddress(session.getAddress()); + use.setClientInfo(session.getClientInfo()); + Date currSince = timeSource.currentTimestamp(); + currSince.setTime(since); + use.setSince(currSince); + Date last = timeSource.currentTimestamp(); + last.setTime(lastUsedTs); + use.setLastUsedTs(last); + use.setSystem(session.isSystem()); + return use; + } + + @Override + public void killSession(UUID id) { + UserSessionInfo usi = cache.remove(id); + + if (usi != null) { + log.debug("Killed session: {}", usi); + + usi.lastUsedTs = 0; + clusterManager.send(usi); + } + } + + @Override + public List findUserSessionsByAttribute(String attributeName, Object attributeValue) { + Preconditions.checkNotNullArgument(attributeName); + + List sessionInfos = new ArrayList<>(cache.values()); + + //noinspection UnnecessaryLocalVariable + List sessionIds = sessionInfos.stream() + .filter(usInfo -> Objects.equals(usInfo.session.getAttribute(attributeName), attributeValue)) + .map(userSessionInfo -> userSessionInfo.session.getId()) + .collect(Collectors.toList()); + + return sessionIds; + } + + @Override + public void processEviction() { + if (!AppContext.isStarted()) + return; + + log.trace("Processing eviction"); + long now = timeSource.currentTimeMillis(); + for (Iterator it = cache.values().iterator(); it.hasNext();) { + UserSessionInfo usi = it.next(); + if (!usi.session.isSystem() && now > (usi.lastUsedTs + expirationTimeout * 1000)) { + log.debug("Removing session due to timeout: {}", usi); + + userSessionLog.updateSessionLogRecord(usi.getSession(), SessionAction.EXPIRATION); + it.remove(); + + usi.lastUsedTs = 0; + clusterManager.send(usi); + } + } + } + } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/UserSessionsAPI.java b/modules/core/src/com/haulmont/cuba/security/app/UserSessionsAPI.java index b69e030817..62eae40a4a 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/UserSessionsAPI.java +++ b/modules/core/src/com/haulmont/cuba/security/app/UserSessionsAPI.java @@ -1,112 +1,112 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.security.entity.UserSessionEntity; -import com.haulmont.cuba.security.global.UserSession; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.List; -import java.util.UUID; - -/** - * User sessions distributed cache API. - */ -public interface UserSessionsAPI { - - String NAME = "cuba_UserSessions"; - - void add(UserSession session); - - void remove(UserSession session); - - /** - * Get user session from cache. - * - * @param id session id - * @return user session instance or null if not found - */ - @Nullable - UserSession get(UUID id); - - /** - * Get user session from cache, updating its "last used" timestamp. - * - * @param id session id - * @param propagate whether to propagate the new "last used" timestamp to the cluster - * @return user session instance or null if not found - */ - @Nullable - UserSession get(UUID id, boolean propagate); - - /** - * Propagates the user session state to the cluster - * @param id session id. If session with this id is not found, does nothing. - */ - void propagate(UUID id); - - /** - * @return collection of all active sessions - */ - Collection getUserSessionInfo(); - - /** - * Immediately remove a sessions from cache. - * @param id session id - */ - void killSession(UUID id); - - /** - * Finds sessions with attribute with name {@code attributeName} and value equal to passed {@code attributeValue} - * - * @param attributeName attribute name - * @param attributeValue attribute value - * @return session ids - */ - List findUserSessionsByAttribute(String attributeName, Object attributeValue); - - /** - * @return session expiration timeout in the cache - */ - int getExpirationTimeoutSec(); - - /** - * Set session expiration timeout for the cache. - * @param value timeout in seconds - */ - void setExpirationTimeoutSec(int value); - - /** - * @return session send timeout in cluster - */ - int getSendTimeoutSec(); - - /** - * Set user session ping timeout in cluster. - * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, - * user session sends in cluster only after specified timeout - * - * @param timeout in seconds - */ - void setSendTimeoutSec(int timeout); - - /** - * Evict timed out sessions from the cache. - */ - void processEviction(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.security.entity.UserSessionEntity; +import com.haulmont.cuba.security.global.UserSession; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +/** + * User sessions distributed cache API. + */ +public interface UserSessionsAPI { + + String NAME = "cuba_UserSessions"; + + void add(UserSession session); + + void remove(UserSession session); + + /** + * Get user session from cache. + * + * @param id session id + * @return user session instance or null if not found + */ + @Nullable + UserSession get(UUID id); + + /** + * Get user session from cache, updating its "last used" timestamp. + * + * @param id session id + * @param propagate whether to propagate the new "last used" timestamp to the cluster + * @return user session instance or null if not found + */ + @Nullable + UserSession get(UUID id, boolean propagate); + + /** + * Propagates the user session state to the cluster + * @param id session id. If session with this id is not found, does nothing. + */ + void propagate(UUID id); + + /** + * @return collection of all active sessions + */ + Collection getUserSessionInfo(); + + /** + * Immediately remove a sessions from cache. + * @param id session id + */ + void killSession(UUID id); + + /** + * Finds sessions with attribute with name {@code attributeName} and value equal to passed {@code attributeValue} + * + * @param attributeName attribute name + * @param attributeValue attribute value + * @return session ids + */ + List findUserSessionsByAttribute(String attributeName, Object attributeValue); + + /** + * @return session expiration timeout in the cache + */ + int getExpirationTimeoutSec(); + + /** + * Set session expiration timeout for the cache. + * @param value timeout in seconds + */ + void setExpirationTimeoutSec(int value); + + /** + * @return session send timeout in cluster + */ + int getSendTimeoutSec(); + + /** + * Set user session ping timeout in cluster. + * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, + * user session sends in cluster only after specified timeout + * + * @param timeout in seconds + */ + void setSendTimeoutSec(int timeout); + + /** + * Evict timed out sessions from the cache. + */ + void processEviction(); } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/UserSettingServiceBean.java b/modules/core/src/com/haulmont/cuba/security/app/UserSettingServiceBean.java index 90d5ddfc3c..c845a0ad3b 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/UserSettingServiceBean.java +++ b/modules/core/src/com/haulmont/cuba/security/app/UserSettingServiceBean.java @@ -1,310 +1,310 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.*; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.Element; -import org.springframework.stereotype.Service; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@Service(UserSettingService.NAME) -public class UserSettingServiceBean implements UserSettingService { - - @Inject - protected Persistence persistence; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected Metadata metadata; - - @Override - public String loadSetting(String name) { - return loadSetting(null, name); - } - - @Override - public String loadSetting(ClientType clientType, String name) { - String value; - try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { - UserSetting us = findUserSettings(clientType, name); - value = us == null ? null : us.getValue(); - tx.commit(); - } - return value; - } - - @Override - public void saveSetting(String name, String value) { - saveSetting(null, name, value); - } - - @Override - public void saveSetting(ClientType clientType, String name, String value) { - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - UserSetting us = findUserSettings(clientType, name); - if (us == null) { - us = metadata.create(UserSetting.class); - us.setUser(em.getReference(User.class, userSessionSource.getUserSession().getUser().getId())); - us.setName(name); - us.setClientType(clientType); - us.setValue(value); - - em.persist(us); - } else { - us.setValue(value); - } - tx.commit(); - } - } - - @Override - public void deleteSettings(ClientType clientType, String name) { - try (Transaction tx = persistence.createTransaction()) { - UserSetting us = findUserSettings(clientType, name); - EntityManager em = persistence.getEntityManager(); - if(us!=null){ - em.remove(us); - } - tx.commit(); - } - } - - @Override - public void copySettings(User fromUser, User toUser) { - MetaClass metaClass = metadata.getClassNN(UserSetting.class); - - Security security = AppBeans.get(Security.NAME); - if (!security.isEntityOpPermitted(metaClass, EntityOp.CREATE)) { - throw new AccessDeniedException(PermissionType.ENTITY_OP, metaClass.getName()); - } - - Map presentationsMap = copyPresentations(fromUser, toUser); - copyUserFolders(fromUser, toUser, presentationsMap); - Map filtersMap = copyFilters(fromUser, toUser); - - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - Query deleteSettingsQuery = em.createQuery("delete from sec$UserSetting s where s.user.id = ?1"); - deleteSettingsQuery.setParameter(1, toUser); - deleteSettingsQuery.executeUpdate(); - tx.commitRetaining(); - em = persistence.getEntityManager(); - - TypedQuery q = em.createQuery("select s from sec$UserSetting s where s.user.id = ?1", UserSetting.class); - q.setParameter(1, fromUser); - List fromUserSettings = q.getResultList(); - - for (UserSetting currSetting : fromUserSettings) { - UserSetting newSetting = metadata.create(UserSetting.class); - newSetting.setUser(toUser); - newSetting.setClientType(currSetting.getClientType()); - newSetting.setName(currSetting.getName()); - - try { - Document doc = Dom4j.readDocument(currSetting.getValue()); - - List components = doc.getRootElement().element("components").elements("component"); - for (Element component : components) { - Attribute presentationAttr = component.attribute("presentation"); - if (presentationAttr != null) { - UUID presentationId = UuidProvider.fromString(presentationAttr.getValue()); - Presentation newPresentation = presentationsMap.get(presentationId); - if (newPresentation != null) { - presentationAttr.setValue(newPresentation.getId().toString()); - } - } - Element defaultFilterEl = component.element("defaultFilter"); - if (defaultFilterEl != null) { - Attribute idAttr = defaultFilterEl.attribute("id"); - if (idAttr != null) { - UUID filterId = UuidProvider.fromString(idAttr.getValue()); - FilterEntity newFilter = filtersMap.get(filterId); - if (newFilter != null) { - idAttr.setValue(newFilter.getId().toString()); - } - } - } - } - - newSetting.setValue(Dom4j.writeDocument(doc, true)); - } catch (Exception e) { - newSetting.setValue(currSetting.getValue()); - } - em.persist(newSetting); - } - - tx.commit(); - } - } - - @Nullable - protected UserSetting findUserSettings(ClientType clientType, String name) { - EntityManager em = persistence.getEntityManager(); - - TypedQuery q = em.createQuery( - "select s from sec$UserSetting s where s.user.id = ?1 and s.name =?2 and s.clientType = ?3", - UserSetting.class); - q.setParameter(1, userSessionSource.getUserSession().getUser().getId()); - q.setParameter(2, name); - q.setParameter(3, clientType == null ? null : clientType.getId()); - - return q.getFirstResult(); - } - - protected Map copyPresentations(User fromUser, User toUser) { - Map presentationMap = new HashMap<>(); - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - Query delete = em.createQuery("delete from sec$Presentation p where p.user.id=?1"); - delete.setParameter(1, toUser); - delete.executeUpdate(); - Query selectQuery = em.createQuery("select p from sec$Presentation p where p.user.id=?1"); - selectQuery.setParameter(1, fromUser); - List presentations = selectQuery.getResultList(); - for (Presentation presentation : presentations) { - Presentation newPresentation = metadata.create(Presentation.class); - newPresentation.setUser(toUser); - newPresentation.setComponentId(presentation.getComponentId()); - newPresentation.setAutoSave(presentation.getAutoSave()); - newPresentation.setName(presentation.getName()); - newPresentation.setXml(presentation.getXml()); - presentationMap.put(presentation.getId(), newPresentation); - em.persist(newPresentation); - } - tx.commit(); - return presentationMap; - } - } - - - protected void copyUserFolders(User fromUser, User toUser, Map presentationsMap) { - try (Transaction tx = persistence.createTransaction()) { - MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(SearchFolder.class); - EntityManager em = persistence.getEntityManager(); - Query deleteSettingsQuery = em.createQuery("delete from " + effectiveMetaClass.getName() + " s where s.user.id = ?1"); - deleteSettingsQuery.setParameter(1, toUser); - deleteSettingsQuery.executeUpdate(); - Query q = em.createQuery("select s from " + effectiveMetaClass.getName() + " s where s.user.id = ?1"); - q.setParameter(1, fromUser); - List fromUserFolders = q.getResultList(); - Map copiedFolders = new HashMap<>(); - for (SearchFolder searchFolder : fromUserFolders) { - copyFolder(searchFolder, toUser, copiedFolders, presentationsMap); - } - tx.commit(); - } - } - - protected SearchFolder copyFolder(SearchFolder searchFolder, - User toUser, - Map copiedFolders, - Map presentationsMap) { - SearchFolder newFolder; - if (searchFolder.getUser() == null) - return searchFolder; - newFolder = copiedFolders.get(searchFolder); - if (newFolder != null) - return null; - newFolder = metadata.create(SearchFolder.class); - newFolder.setUser(toUser); - newFolder.setApplyDefault(searchFolder.getApplyDefault()); - newFolder.setFilterComponentId(searchFolder.getFilterComponentId()); - newFolder.setFilterXml(searchFolder.getFilterXml()); - newFolder.setItemStyle(searchFolder.getItemStyle()); - newFolder.setName(searchFolder.getName()); - newFolder.setTabName(searchFolder.getTabName()); - newFolder.setSortOrder(searchFolder.getSortOrder()); - newFolder.setIsSet(searchFolder.getIsSet()); - newFolder.setEntityType(searchFolder.getEntityType()); - SearchFolder copiedFolder = copiedFolders.get(searchFolder.getParent()); - if (searchFolder.getParent() != null) { - if (copiedFolder != null) { - newFolder.setParent(copiedFolder); - } else { - SearchFolder newParent = getParent((SearchFolder) searchFolder.getParent(), toUser, copiedFolders, presentationsMap); - newFolder.setParent(newParent); - } - } - if (searchFolder.getPresentation() != null) { - if (searchFolder.getPresentation().getUser() == null) { - newFolder.setPresentation(searchFolder.getPresentation()); - } else { - Presentation newPresentation = presentationsMap.get(searchFolder.getPresentation().getId()); - newFolder.setPresentation(newPresentation); - } - } - copiedFolders.put(searchFolder, newFolder); - EntityManager em = persistence.getEntityManager(); - em.persist(newFolder); - return newFolder; - } - - protected SearchFolder getParent(SearchFolder parentFolder, User toUser, Map copiedFolders, Map presentationMap) { - if (parentFolder == null) { - return null; - } - if (parentFolder.getUser() == null) { - return parentFolder; - } - return copyFolder(parentFolder, toUser, copiedFolders, presentationMap); - } - - protected Map copyFilters(User fromUser, User toUser) { - Map filtersMap = new HashMap<>(); - try (Transaction tx = persistence.createTransaction()) { - MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(FilterEntity.class); - - EntityManager em = persistence.getEntityManager(); - Query deleteFiltersQuery = em.createQuery("delete from " + effectiveMetaClass.getName() + " f where f.user.id = ?1"); - deleteFiltersQuery.setParameter(1, toUser); - deleteFiltersQuery.executeUpdate(); - Query q = em.createQuery("select f from " + effectiveMetaClass.getName() + " f where f.user.id = ?1"); - q.setParameter(1, fromUser); - List fromUserFilters = q.getResultList(); - - for (FilterEntity filter : fromUserFilters) { - FilterEntity newFilter = metadata.create(FilterEntity.class); - newFilter.setUser(toUser); - newFilter.setCode(filter.getCode()); - newFilter.setName(filter.getName()); - newFilter.setComponentId(filter.getComponentId()); - newFilter.setXml(filter.getXml()); - filtersMap.put(filter.getId(), newFilter); - em.persist(newFilter); - } - tx.commit(); - return filtersMap; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.*; +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.Element; +import org.springframework.stereotype.Service; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Service(UserSettingService.NAME) +public class UserSettingServiceBean implements UserSettingService { + + @Inject + protected Persistence persistence; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected Metadata metadata; + + @Override + public String loadSetting(String name) { + return loadSetting(null, name); + } + + @Override + public String loadSetting(ClientType clientType, String name) { + String value; + try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { + UserSetting us = findUserSettings(clientType, name); + value = us == null ? null : us.getValue(); + tx.commit(); + } + return value; + } + + @Override + public void saveSetting(String name, String value) { + saveSetting(null, name, value); + } + + @Override + public void saveSetting(ClientType clientType, String name, String value) { + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + UserSetting us = findUserSettings(clientType, name); + if (us == null) { + us = metadata.create(UserSetting.class); + us.setUser(em.getReference(User.class, userSessionSource.getUserSession().getUser().getId())); + us.setName(name); + us.setClientType(clientType); + us.setValue(value); + + em.persist(us); + } else { + us.setValue(value); + } + tx.commit(); + } + } + + @Override + public void deleteSettings(ClientType clientType, String name) { + try (Transaction tx = persistence.createTransaction()) { + UserSetting us = findUserSettings(clientType, name); + EntityManager em = persistence.getEntityManager(); + if(us!=null){ + em.remove(us); + } + tx.commit(); + } + } + + @Override + public void copySettings(User fromUser, User toUser) { + MetaClass metaClass = metadata.getClassNN(UserSetting.class); + + Security security = AppBeans.get(Security.NAME); + if (!security.isEntityOpPermitted(metaClass, EntityOp.CREATE)) { + throw new AccessDeniedException(PermissionType.ENTITY_OP, metaClass.getName()); + } + + Map presentationsMap = copyPresentations(fromUser, toUser); + copyUserFolders(fromUser, toUser, presentationsMap); + Map filtersMap = copyFilters(fromUser, toUser); + + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + Query deleteSettingsQuery = em.createQuery("delete from sec$UserSetting s where s.user.id = ?1"); + deleteSettingsQuery.setParameter(1, toUser); + deleteSettingsQuery.executeUpdate(); + tx.commitRetaining(); + em = persistence.getEntityManager(); + + TypedQuery q = em.createQuery("select s from sec$UserSetting s where s.user.id = ?1", UserSetting.class); + q.setParameter(1, fromUser); + List fromUserSettings = q.getResultList(); + + for (UserSetting currSetting : fromUserSettings) { + UserSetting newSetting = metadata.create(UserSetting.class); + newSetting.setUser(toUser); + newSetting.setClientType(currSetting.getClientType()); + newSetting.setName(currSetting.getName()); + + try { + Document doc = Dom4j.readDocument(currSetting.getValue()); + + List components = doc.getRootElement().element("components").elements("component"); + for (Element component : components) { + Attribute presentationAttr = component.attribute("presentation"); + if (presentationAttr != null) { + UUID presentationId = UuidProvider.fromString(presentationAttr.getValue()); + Presentation newPresentation = presentationsMap.get(presentationId); + if (newPresentation != null) { + presentationAttr.setValue(newPresentation.getId().toString()); + } + } + Element defaultFilterEl = component.element("defaultFilter"); + if (defaultFilterEl != null) { + Attribute idAttr = defaultFilterEl.attribute("id"); + if (idAttr != null) { + UUID filterId = UuidProvider.fromString(idAttr.getValue()); + FilterEntity newFilter = filtersMap.get(filterId); + if (newFilter != null) { + idAttr.setValue(newFilter.getId().toString()); + } + } + } + } + + newSetting.setValue(Dom4j.writeDocument(doc, true)); + } catch (Exception e) { + newSetting.setValue(currSetting.getValue()); + } + em.persist(newSetting); + } + + tx.commit(); + } + } + + @Nullable + protected UserSetting findUserSettings(ClientType clientType, String name) { + EntityManager em = persistence.getEntityManager(); + + TypedQuery q = em.createQuery( + "select s from sec$UserSetting s where s.user.id = ?1 and s.name =?2 and s.clientType = ?3", + UserSetting.class); + q.setParameter(1, userSessionSource.getUserSession().getUser().getId()); + q.setParameter(2, name); + q.setParameter(3, clientType == null ? null : clientType.getId()); + + return q.getFirstResult(); + } + + protected Map copyPresentations(User fromUser, User toUser) { + Map presentationMap = new HashMap<>(); + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + Query delete = em.createQuery("delete from sec$Presentation p where p.user.id=?1"); + delete.setParameter(1, toUser); + delete.executeUpdate(); + Query selectQuery = em.createQuery("select p from sec$Presentation p where p.user.id=?1"); + selectQuery.setParameter(1, fromUser); + List presentations = selectQuery.getResultList(); + for (Presentation presentation : presentations) { + Presentation newPresentation = metadata.create(Presentation.class); + newPresentation.setUser(toUser); + newPresentation.setComponentId(presentation.getComponentId()); + newPresentation.setAutoSave(presentation.getAutoSave()); + newPresentation.setName(presentation.getName()); + newPresentation.setXml(presentation.getXml()); + presentationMap.put(presentation.getId(), newPresentation); + em.persist(newPresentation); + } + tx.commit(); + return presentationMap; + } + } + + + protected void copyUserFolders(User fromUser, User toUser, Map presentationsMap) { + try (Transaction tx = persistence.createTransaction()) { + MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(SearchFolder.class); + EntityManager em = persistence.getEntityManager(); + Query deleteSettingsQuery = em.createQuery("delete from " + effectiveMetaClass.getName() + " s where s.user.id = ?1"); + deleteSettingsQuery.setParameter(1, toUser); + deleteSettingsQuery.executeUpdate(); + Query q = em.createQuery("select s from " + effectiveMetaClass.getName() + " s where s.user.id = ?1"); + q.setParameter(1, fromUser); + List fromUserFolders = q.getResultList(); + Map copiedFolders = new HashMap<>(); + for (SearchFolder searchFolder : fromUserFolders) { + copyFolder(searchFolder, toUser, copiedFolders, presentationsMap); + } + tx.commit(); + } + } + + protected SearchFolder copyFolder(SearchFolder searchFolder, + User toUser, + Map copiedFolders, + Map presentationsMap) { + SearchFolder newFolder; + if (searchFolder.getUser() == null) + return searchFolder; + newFolder = copiedFolders.get(searchFolder); + if (newFolder != null) + return null; + newFolder = metadata.create(SearchFolder.class); + newFolder.setUser(toUser); + newFolder.setApplyDefault(searchFolder.getApplyDefault()); + newFolder.setFilterComponentId(searchFolder.getFilterComponentId()); + newFolder.setFilterXml(searchFolder.getFilterXml()); + newFolder.setItemStyle(searchFolder.getItemStyle()); + newFolder.setName(searchFolder.getName()); + newFolder.setTabName(searchFolder.getTabName()); + newFolder.setSortOrder(searchFolder.getSortOrder()); + newFolder.setIsSet(searchFolder.getIsSet()); + newFolder.setEntityType(searchFolder.getEntityType()); + SearchFolder copiedFolder = copiedFolders.get(searchFolder.getParent()); + if (searchFolder.getParent() != null) { + if (copiedFolder != null) { + newFolder.setParent(copiedFolder); + } else { + SearchFolder newParent = getParent((SearchFolder) searchFolder.getParent(), toUser, copiedFolders, presentationsMap); + newFolder.setParent(newParent); + } + } + if (searchFolder.getPresentation() != null) { + if (searchFolder.getPresentation().getUser() == null) { + newFolder.setPresentation(searchFolder.getPresentation()); + } else { + Presentation newPresentation = presentationsMap.get(searchFolder.getPresentation().getId()); + newFolder.setPresentation(newPresentation); + } + } + copiedFolders.put(searchFolder, newFolder); + EntityManager em = persistence.getEntityManager(); + em.persist(newFolder); + return newFolder; + } + + protected SearchFolder getParent(SearchFolder parentFolder, User toUser, Map copiedFolders, Map presentationMap) { + if (parentFolder == null) { + return null; + } + if (parentFolder.getUser() == null) { + return parentFolder; + } + return copyFolder(parentFolder, toUser, copiedFolders, presentationMap); + } + + protected Map copyFilters(User fromUser, User toUser) { + Map filtersMap = new HashMap<>(); + try (Transaction tx = persistence.createTransaction()) { + MetaClass effectiveMetaClass = metadata.getExtendedEntities().getEffectiveMetaClass(FilterEntity.class); + + EntityManager em = persistence.getEntityManager(); + Query deleteFiltersQuery = em.createQuery("delete from " + effectiveMetaClass.getName() + " f where f.user.id = ?1"); + deleteFiltersQuery.setParameter(1, toUser); + deleteFiltersQuery.executeUpdate(); + Query q = em.createQuery("select f from " + effectiveMetaClass.getName() + " f where f.user.id = ?1"); + q.setParameter(1, fromUser); + List fromUserFilters = q.getResultList(); + + for (FilterEntity filter : fromUserFilters) { + FilterEntity newFilter = metadata.create(FilterEntity.class); + newFilter.setUser(toUser); + newFilter.setCode(filter.getCode()); + newFilter.setName(filter.getName()); + newFilter.setComponentId(filter.getComponentId()); + newFilter.setXml(filter.getXml()); + filtersMap.put(filter.getId(), newFilter); + em.persist(newFilter); + } + tx.commit(); + return filtersMap; + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body.gsp b/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body.gsp index 3ae74e927a..3d52adb38a 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body.gsp +++ b/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body.gsp @@ -1,10 +1,10 @@ -Hello, ${user.name}. - -The password for your CUBA Application account has been reset by administrator. - -Please login with the following temporary password: -${password} -and immediately create a new one for the further work. - -Thank you, +Hello, ${user.name}. + +The password for your CUBA Application account has been reset by administrator. + +Please login with the following temporary password: +${password} +and immediately create a new one for the further work. + +Thank you, CUBA Team \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body_ru.gsp b/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body_ru.gsp index ebd91e5d43..5bd4437b49 100644 --- a/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body_ru.gsp +++ b/modules/core/src/com/haulmont/cuba/security/app/email/reset-password-body_ru.gsp @@ -1,10 +1,10 @@ -Здравствуйте, ${user.name}. - -Пароль вашей учетной записи CUBA Application был сброшен администратором. - -Пожалуйста войдите в систему со следующим временным паролем: -${password} -и немедленно создайте новый для дальнейшей работы. - -Спасибо, +Здравствуйте, ${user.name}. + +Пароль вашей учетной записи CUBA Application был сброшен администратором. + +Пожалуйста войдите в систему со следующим временным паролем: +${password} +и немедленно создайте новый для дальнейшей работы. + +Спасибо, CUBA Team \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/jmx/EntityLogMBean.java b/modules/core/src/com/haulmont/cuba/security/jmx/EntityLogMBean.java index ec0d52c15e..794690040a 100644 --- a/modules/core/src/com/haulmont/cuba/security/jmx/EntityLogMBean.java +++ b/modules/core/src/com/haulmont/cuba/security/jmx/EntityLogMBean.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.jmx; - -/** - * JMX interface for {@link com.haulmont.cuba.security.app.EntityLogAPI} - * - */ -public interface EntityLogMBean { - /** - * Is logging enabled? - */ - boolean isEnabled(); - - /** - * Enables or disables logging - */ - void setEnabled(boolean enabled); - - /** - * Invalidates configuration cache. - * The configuration will be recreated from the database on next lifecycle event. - */ - void invalidateCache(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.jmx; + +/** + * JMX interface for {@link com.haulmont.cuba.security.app.EntityLogAPI} + * + */ +public interface EntityLogMBean { + /** + * Is logging enabled? + */ + boolean isEnabled(); + + /** + * Enables or disables logging + */ + void setEnabled(boolean enabled); + + /** + * Invalidates configuration cache. + * The configuration will be recreated from the database on next lifecycle event. + */ + void invalidateCache(); +} diff --git a/modules/core/src/com/haulmont/cuba/security/jmx/UserSessionsMBean.java b/modules/core/src/com/haulmont/cuba/security/jmx/UserSessionsMBean.java index 476eefcf89..ba21875b3d 100644 --- a/modules/core/src/com/haulmont/cuba/security/jmx/UserSessionsMBean.java +++ b/modules/core/src/com/haulmont/cuba/security/jmx/UserSessionsMBean.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.jmx; - -/** - * JMX interface for {@link com.haulmont.cuba.security.app.UserSessionsAPI} - * - */ -public interface UserSessionsMBean { - - /** - * User session expiration timeout. Not the same as HTTP session timeout, but should have the same value. - * @return timeout in seconds - */ - int getExpirationTimeoutSec(); - - /** - * Set user session expiration timeout for the current server session. - * @param value timeout in seconds - */ - void setExpirationTimeoutSec(int value); - - /** - * @return session send timeout in cluster - */ - int getSendTimeoutSec(); - - /** - * Set user session ping timeout in cluster. - * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, - * user session sends in cluster only after specified timeout - * @param timeout in seconds - */ - void setSendTimeoutSec(int timeout); - - int getCount(); - - String printSessions(); - - void processEviction(); - - /** - * Kill specified session - * - * @param id Session id - * @return Result status - */ - String killSession(String id); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.jmx; + +/** + * JMX interface for {@link com.haulmont.cuba.security.app.UserSessionsAPI} + * + */ +public interface UserSessionsMBean { + + /** + * User session expiration timeout. Not the same as HTTP session timeout, but should have the same value. + * @return timeout in seconds + */ + int getExpirationTimeoutSec(); + + /** + * Set user session expiration timeout for the current server session. + * @param value timeout in seconds + */ + void setExpirationTimeoutSec(int value); + + /** + * @return session send timeout in cluster + */ + int getSendTimeoutSec(); + + /** + * Set user session ping timeout in cluster. + * If ping performed {@link com.haulmont.cuba.security.app.UserSessions#get}, + * user session sends in cluster only after specified timeout + * @param timeout in seconds + */ + void setSendTimeoutSec(int timeout); + + int getCount(); + + String printSessions(); + + void processEviction(); + + /** + * Kill specified session + * + * @param id Session id + * @return Result status + */ + String killSession(String id); +} diff --git a/modules/core/src/com/haulmont/cuba/security/listener/GroupEntityListener.java b/modules/core/src/com/haulmont/cuba/security/listener/GroupEntityListener.java index aaa6c84fe5..3a8e29171b 100644 --- a/modules/core/src/com/haulmont/cuba/security/listener/GroupEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/security/listener/GroupEntityListener.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.PersistenceHelper; -import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; -import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.GroupHierarchy; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.List; - -@Component("cuba_GroupEntityListener") -public class GroupEntityListener implements - BeforeInsertEntityListener, - BeforeUpdateEntityListener { - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Override - public void onBeforeInsert(Group entity, EntityManager entityManager) { - createNewHierarchy(entity, entity.getParent()); - } - - protected void createNewHierarchy(Group entity, Group parent) { - if (parent == null) { - entity.setHierarchyList(new ArrayList<>()); - - return; - } - - if (!PersistenceHelper.isManaged(parent) && !PersistenceHelper.isDetached(parent)) - throw new IllegalStateException("Unable to create GroupHierarchy. Commit parent group first."); - - EntityManager em = persistence.getEntityManager(); - - if (entity.getHierarchyList() == null) { - entity.setHierarchyList(new ArrayList<>()); - } else { - entity.getHierarchyList().clear(); - } - - if (PersistenceHelper.isDetached(parent)) - parent = em.find(Group.class, parent.getId()); // refresh parent in case of detached - - int level = 0; - for (GroupHierarchy hierarchy : parent.getHierarchyList()) { - GroupHierarchy h = metadata.create(GroupHierarchy.class); - h.setGroup(entity); - h.setParent(hierarchy.getParent()); - h.setLevel(level++); - em.persist(h); - entity.getHierarchyList().add(h); - } - GroupHierarchy h = metadata.create(GroupHierarchy.class); - h.setGroup(entity); - h.setParent(parent); - h.setLevel(level); - em.persist(h); - entity.getHierarchyList().add(h); - } - - @Override - public void onBeforeUpdate(Group entity, EntityManager entityManager) { - if (!persistence.getTools().getDirtyFields(entity).contains("parent")) - return; - - EntityManager em = persistence.getEntityManager(); - - for (GroupHierarchy oldHierarchy : entity.getHierarchyList()) { - em.remove(oldHierarchy); - } - createNewHierarchy(entity, entity.getParent()); - - TypedQuery q = em.createQuery( - "select h from sec$GroupHierarchy h join fetch h.group " + - "where h.parent.id = ?1", GroupHierarchy.class); - q.setParameter(1, entity); - List list = q.getResultList(); - for (GroupHierarchy hierarchy : list) { - Group dependentGroup = hierarchy.getGroup(); - for (GroupHierarchy depHierarchy : dependentGroup.getHierarchyList()) { - em.remove(depHierarchy); - } - em.remove(hierarchy); - createNewHierarchy(dependentGroup, dependentGroup.getParent()); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.PersistenceHelper; +import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; +import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.GroupHierarchy; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; + +@Component("cuba_GroupEntityListener") +public class GroupEntityListener implements + BeforeInsertEntityListener, + BeforeUpdateEntityListener { + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Override + public void onBeforeInsert(Group entity, EntityManager entityManager) { + createNewHierarchy(entity, entity.getParent()); + } + + protected void createNewHierarchy(Group entity, Group parent) { + if (parent == null) { + entity.setHierarchyList(new ArrayList<>()); + + return; + } + + if (!PersistenceHelper.isManaged(parent) && !PersistenceHelper.isDetached(parent)) + throw new IllegalStateException("Unable to create GroupHierarchy. Commit parent group first."); + + EntityManager em = persistence.getEntityManager(); + + if (entity.getHierarchyList() == null) { + entity.setHierarchyList(new ArrayList<>()); + } else { + entity.getHierarchyList().clear(); + } + + if (PersistenceHelper.isDetached(parent)) + parent = em.find(Group.class, parent.getId()); // refresh parent in case of detached + + int level = 0; + for (GroupHierarchy hierarchy : parent.getHierarchyList()) { + GroupHierarchy h = metadata.create(GroupHierarchy.class); + h.setGroup(entity); + h.setParent(hierarchy.getParent()); + h.setLevel(level++); + em.persist(h); + entity.getHierarchyList().add(h); + } + GroupHierarchy h = metadata.create(GroupHierarchy.class); + h.setGroup(entity); + h.setParent(parent); + h.setLevel(level); + em.persist(h); + entity.getHierarchyList().add(h); + } + + @Override + public void onBeforeUpdate(Group entity, EntityManager entityManager) { + if (!persistence.getTools().getDirtyFields(entity).contains("parent")) + return; + + EntityManager em = persistence.getEntityManager(); + + for (GroupHierarchy oldHierarchy : entity.getHierarchyList()) { + em.remove(oldHierarchy); + } + createNewHierarchy(entity, entity.getParent()); + + TypedQuery q = em.createQuery( + "select h from sec$GroupHierarchy h join fetch h.group " + + "where h.parent.id = ?1", GroupHierarchy.class); + q.setParameter(1, entity); + List list = q.getResultList(); + for (GroupHierarchy hierarchy : list) { + Group dependentGroup = hierarchy.getGroup(); + for (GroupHierarchy depHierarchy : dependentGroup.getHierarchyList()) { + em.remove(depHierarchy); + } + em.remove(hierarchy); + createNewHierarchy(dependentGroup, dependentGroup.getParent()); + } + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/listener/UserEntityListener.java b/modules/core/src/com/haulmont/cuba/security/listener/UserEntityListener.java index 104bc61278..c70410b2d9 100644 --- a/modules/core/src/com/haulmont/cuba/security/listener/UserEntityListener.java +++ b/modules/core/src/com/haulmont/cuba/security/listener/UserEntityListener.java @@ -1,67 +1,67 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.listener; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.PersistenceTools; -import com.haulmont.cuba.core.global.Events; -import com.haulmont.cuba.core.listener.AfterDeleteEntityListener; -import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; -import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.events.UserInvalidationEvent; -import org.apache.commons.lang.BooleanUtils; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.sql.Connection; - -@Component("cuba_UserEntityListener") -public class UserEntityListener implements BeforeInsertEntityListener, BeforeUpdateEntityListener, - AfterDeleteEntityListener { - - @Inject - protected Events events; - - @Inject - protected PersistenceTools persistenceTools; - - @Override - public void onBeforeInsert(User entity, EntityManager entityManager) { - updateLoginLowerCase(entity); - } - - @Override - public void onBeforeUpdate(User entity, EntityManager entityManager) { - updateLoginLowerCase(entity); - - //noinspection ConstantConditions - if (persistenceTools.getDirtyFields(entity).contains("active") - && BooleanUtils.isTrue((Boolean) persistenceTools.getOldValue(entity, "active"))) { - events.publish(new UserInvalidationEvent(entity)); - } - } - - protected void updateLoginLowerCase(User user) { - user.setLoginLowerCase(user.getLogin() != null ? user.getLogin().toLowerCase() : null); - } - - @Override - public void onAfterDelete(User entity, Connection connection) { - events.publish(new UserInvalidationEvent(entity)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.listener; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.PersistenceTools; +import com.haulmont.cuba.core.global.Events; +import com.haulmont.cuba.core.listener.AfterDeleteEntityListener; +import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; +import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.events.UserInvalidationEvent; +import org.apache.commons.lang.BooleanUtils; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.sql.Connection; + +@Component("cuba_UserEntityListener") +public class UserEntityListener implements BeforeInsertEntityListener, BeforeUpdateEntityListener, + AfterDeleteEntityListener { + + @Inject + protected Events events; + + @Inject + protected PersistenceTools persistenceTools; + + @Override + public void onBeforeInsert(User entity, EntityManager entityManager) { + updateLoginLowerCase(entity); + } + + @Override + public void onBeforeUpdate(User entity, EntityManager entityManager) { + updateLoginLowerCase(entity); + + //noinspection ConstantConditions + if (persistenceTools.getDirtyFields(entity).contains("active") + && BooleanUtils.isTrue((Boolean) persistenceTools.getOldValue(entity, "active"))) { + events.publish(new UserInvalidationEvent(entity)); + } + } + + protected void updateLoginLowerCase(User user) { + user.setLoginLowerCase(user.getLogin() != null ? user.getLogin().toLowerCase() : null); + } + + @Override + public void onAfterDelete(User entity, Connection connection) { + events.publish(new UserInvalidationEvent(entity)); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/messages.properties b/modules/core/src/com/haulmont/cuba/security/messages.properties index 13de825bd7..d0c7d14fac 100644 --- a/modules/core/src/com/haulmont/cuba/security/messages.properties +++ b/modules/core/src/com/haulmont/cuba/security/messages.properties @@ -1,23 +1,23 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -LoginException.InvalidLoginOrPassword = Unknown login name or bad password: %s -LoginException.InvalidUser = Unknown user: %s -LoginException.invalidIP = You are not permitted to login from this IP address -LoginException.loginFailedAttemptsLeft = Login attempts left: %s -LoginException.restApiAccessDenied = User is not allowed to use the REST API +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +LoginException.InvalidLoginOrPassword = Unknown login name or bad password: %s +LoginException.InvalidUser = Unknown user: %s +LoginException.invalidIP = You are not permitted to login from this IP address +LoginException.loginFailedAttemptsLeft = Login attempts left: %s +LoginException.restApiAccessDenied = User is not allowed to use the REST API LoginException.loginAttemptsNumberExceeded = The number of unsuccessful login attempts exceeded. Your account is blocked for %s seconds \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/messages_ru.properties b/modules/core/src/com/haulmont/cuba/security/messages_ru.properties index b142fcfe98..6e782c023d 100644 --- a/modules/core/src/com/haulmont/cuba/security/messages_ru.properties +++ b/modules/core/src/com/haulmont/cuba/security/messages_ru.properties @@ -1,23 +1,23 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -LoginException.InvalidLoginOrPassword = Неверный логин или пароль: %s -LoginException.InvalidUser = Незарегистрированный пользователь: %s -LoginException.invalidIP = Вы не имеете права входить с данного IP адреса -LoginException.loginFailedAttemptsLeft = Осталось попыток: %s. -LoginException.restApiAccessDenied = Пользователю запрещён доступ к REST APIó +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +LoginException.InvalidLoginOrPassword = Неверный логин или пароль: %s +LoginException.InvalidUser = Незарегистрированный пользователь: %s +LoginException.invalidIP = Вы не имеете права входить с данного IP адреса +LoginException.loginFailedAttemptsLeft = Осталось попыток: %s. +LoginException.restApiAccessDenied = Пользователю запрещён доступ к REST APIó LoginException.loginAttemptsNumberExceeded = Превышено количество неудачных попыток входа. Ваш аккаунт заблокирован на %s секунд \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/sys/TrustedLoginHandler.java b/modules/core/src/com/haulmont/cuba/security/sys/TrustedLoginHandler.java index 2e3e554ce4..f14fc049e7 100644 --- a/modules/core/src/com/haulmont/cuba/security/sys/TrustedLoginHandler.java +++ b/modules/core/src/com/haulmont/cuba/security/sys/TrustedLoginHandler.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.sys; - -import com.haulmont.cuba.core.app.ServerConfig; -import org.apache.commons.lang.StringUtils; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.regex.Pattern; - -@Component(TrustedLoginHandler.NAME) -public class TrustedLoginHandler { - public static final String NAME = "cuba_TrustedLoginHandler"; - - @Inject - protected ServerConfig serverConfig; - - /** - * @param address ip-address - * @return true if address in trusted list - */ - public boolean checkAddress(String address) { - String permittedIpList = convertToRegex(serverConfig.getTrustedClientPermittedIpList()); - Pattern permittedIpMaskPattern = Pattern.compile(permittedIpList); - return permittedIpMaskPattern.matcher(address).matches(); - } - - protected String convertToRegex(String ipList) { - String regex = null; - if (StringUtils.isNotEmpty(ipList)) { - regex = ipList; - regex = regex.replace(" ", "").replace(",", "|").replace("*", "([01]?\\d\\d?|2[0-4]\\d|25[0-5])").replace(".", "\\."); - } - return regex; - } - - /** - * @param password password to check - * @return true if password is trusted - */ - public boolean checkPassword(String password) { - String trustedClientPassword = serverConfig.getTrustedClientPassword(); - return (StringUtils.isNotBlank(trustedClientPassword) && trustedClientPassword.equals(password)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.sys; + +import com.haulmont.cuba.core.app.ServerConfig; +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.regex.Pattern; + +@Component(TrustedLoginHandler.NAME) +public class TrustedLoginHandler { + public static final String NAME = "cuba_TrustedLoginHandler"; + + @Inject + protected ServerConfig serverConfig; + + /** + * @param address ip-address + * @return true if address in trusted list + */ + public boolean checkAddress(String address) { + String permittedIpList = convertToRegex(serverConfig.getTrustedClientPermittedIpList()); + Pattern permittedIpMaskPattern = Pattern.compile(permittedIpList); + return permittedIpMaskPattern.matcher(address).matches(); + } + + protected String convertToRegex(String ipList) { + String regex = null; + if (StringUtils.isNotEmpty(ipList)) { + regex = ipList; + regex = regex.replace(" ", "").replace(",", "|").replace("*", "([01]?\\d\\d?|2[0-4]\\d|25[0-5])").replace(".", "\\."); + } + return regex; + } + + /** + * @param password password to check + * @return true if password is trusted + */ + public boolean checkPassword(String password) { + String trustedClientPassword = serverConfig.getTrustedClientPassword(); + return (StringUtils.isNotBlank(trustedClientPassword) && trustedClientPassword.equals(password)); + } } \ No newline at end of file diff --git a/modules/core/src/com/haulmont/cuba/security/sys/UserSessionManager.java b/modules/core/src/com/haulmont/cuba/security/sys/UserSessionManager.java index 1cd17dcff1..589b1e0ff5 100644 --- a/modules/core/src/com/haulmont/cuba/security/sys/UserSessionManager.java +++ b/modules/core/src/com/haulmont/cuba/security/sys/UserSessionManager.java @@ -1,301 +1,301 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.sys; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.*; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.PersistenceHelper; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.core.global.UuidSource; -import com.haulmont.cuba.core.sys.DefaultPermissionValuesConfig; -import com.haulmont.cuba.core.sys.UserSessionFinder; -import com.haulmont.cuba.security.app.UserSessionsAPI; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.security.global.NoUserSessionException; -import com.haulmont.cuba.security.global.UserSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.io.Serializable; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.UUID; - -/** - * System-level class managing {@link UserSession}s. - */ -@Component(UserSessionManager.NAME) -public class UserSessionManager implements UserSessionFinder { - - private final Logger log = LoggerFactory.getLogger(UserSessionManager.class); - - public static final String NAME = "cuba_UserSessionManager"; - - @Inject - protected UuidSource uuidSource; - - @Inject - protected UserSessionsAPI sessions; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected Persistence persistence; - - @Inject - protected Metadata metadata; - - @Inject - protected DefaultPermissionValuesConfig defaultPermissionValuesConfig; - - /** - * Create a new session and fill it with security data. Must be called inside a transaction. - * @param user user instance - * @param locale user locale - * @param system create system session - * @return new session instance - */ - public UserSession createSession(User user, Locale locale, boolean system) { - return createSession(uuidSource.createUuid(), user, locale, system); - } - - /** - * Create a new session and fill it with security data. Must be called inside a transaction. - * @param sessionId target session id - * @param user user instance - * @param locale user locale - * @param system create system session - * @return new session instance - */ - public UserSession createSession(UUID sessionId, User user, Locale locale, boolean system) { - List roles = new ArrayList<>(); - for (UserRole userRole : user.getUserRoles()) { - if (userRole.getRole() != null) { - roles.add(userRole.getRole()); - } - } - UserSession session = new UserSession(sessionId, user, roles, locale, system); - compilePermissions(session, roles); - if (user.getGroup() == null) - throw new IllegalStateException("User is not in a Group"); - compileConstraints(session, user.getGroup()); - compileSessionAttributes(session, user.getGroup()); - return session; - } - - /** - * Create a new session from existing for another user and fill it with security data for that new user. - * Must be called inside a transaction. - * @param src existing session - * @param user another user instance - * @return new session with the same ID as existing - */ - public UserSession createSession(UserSession src, User user) { - List roles = new ArrayList<>(); - for (UserRole userRole : user.getUserRoles()) { - if (userRole.getRole() != null) { - roles.add(userRole.getRole()); - } - } - UserSession session = new UserSession(src, user, roles, src.getLocale()); - compilePermissions(session, roles); - if (user.getGroup() == null) - throw new IllegalStateException("User is not in a Group"); - compileConstraints(session, user.getGroup()); - compileSessionAttributes(session, user.getGroup()); - return session; - } - - protected void compilePermissions(UserSession session, List roles) { - for (Role role : roles) { - if (RoleType.SUPER.equals(role.getType())) { - // Don't waste memory, as the user with SUPER role has all permissions. - return; - } - } - for (Role role : roles) { - for (Permission permission : role.getPermissions()) { - PermissionType type = permission.getType(); - if (type != null && permission.getValue() != null) { - try { - session.addPermission(type, - permission.getTarget(), convertToExtendedEntityTarget(permission), permission.getValue()); - } catch (Exception ignored) {} - } - } - } - - defaultPermissionValuesConfig.getDefaultPermissionValues().forEach((target, permission) -> { - if (session.getPermissionValue(permission.getType(), permission.getTarget()) == null) { - session.addPermission(permission.getType(), permission.getTarget(), - convertToExtendedEntityTarget(permission), permission.getValue()); - } - }); - } - - protected String convertToExtendedEntityTarget(Permission permission) { - if (permission.getType() == PermissionType.ENTITY_OP || permission.getType() == PermissionType.ENTITY_ATTR) { - String target = permission.getTarget(); - int pos = target.indexOf(Permission.TARGET_PATH_DELIMETER); - if (pos > -1) { - String entityName = target.substring(0, pos); - Class extendedClass = metadata.getExtendedEntities().getExtendedClass(metadata.getClassNN(entityName)); - if (extendedClass != null) { - MetaClass extMetaClass = metadata.getClassNN(extendedClass); - return extMetaClass.getName() + Permission.TARGET_PATH_DELIMETER + target.substring(pos + 1); - } - } - } - return null; - } - - protected void compileConstraints(UserSession session, Group group) { - EntityManager em = persistence.getEntityManager(); - TypedQuery q = em.createQuery("select c from sec$GroupHierarchy h join h.parent.constraints c " + - "where h.group.id = ?1", Constraint.class); - q.setParameter(1, group); - List constraints = q.getResultList(); - List list = new ArrayList<>(constraints); - list.addAll(group.getConstraints()); - for (Constraint constraint : list) { - if (Boolean.TRUE.equals(constraint.getIsActive())) { - session.addConstraint(constraint); - } - } - } - - protected void compileSessionAttributes(UserSession session, Group group) { - List list = new ArrayList<>(group.getSessionAttributes()); - - EntityManager em = persistence.getEntityManager(); - TypedQuery q = em.createQuery("select a from sec$GroupHierarchy h join h.parent.sessionAttributes a " + - "where h.group.id = ?1 order by h.level desc", SessionAttribute.class); - q.setParameter(1, group); - List attributes = q.getResultList(); - list.addAll(attributes); - - for (SessionAttribute attribute : list) { - Datatype datatype = Datatypes.get(attribute.getDatatype()); - try { - if (session.getAttributeNames().contains(attribute.getName())) { - log.warn("Duplicate definition of '{}' session attribute in the group hierarchy", attribute.getName()); - } - Serializable value = (Serializable) datatype.parse(attribute.getStringValue()); - if (value != null) - session.setAttribute(attribute.getName(), value); - else - session.removeAttribute(attribute.getName()); - } catch (ParseException e) { - throw new RuntimeException("Unable to set session attribute " + attribute.getName(), e); - } - } - } - - /** - * Store session in the distributed sessions cache. - * Should be called outside of transaction to ensure all persistent objects have been detached. - * @param session session instance - */ - public void storeSession(UserSession session) { - sessions.add(session); - } - - /** - * Remove the session from the distributed sessions cache. - * Should be called outside of transaction to ensure all persistent objects have been detached. - * @param session session instance - */ - public void removeSession(UserSession session) { - sessions.remove(session); - } - - /** - * Search for session in cache. - * @param sessionId session's ID - * @return session instance - * @throws NoUserSessionException in case of session with the specified ID is not found in cache. - */ - public UserSession getSession(UUID sessionId) { - UserSession session = findSession(sessionId); - if (session == null) { - throw new NoUserSessionException(sessionId); - } - return session; - } - - /** - * Search for session in cache. - * @param sessionId session's ID - * @return session instance or null if not found - */ - @Override - public UserSession findSession(UUID sessionId) { - return sessions.get(sessionId, false); - } - - public Integer getPermissionValue(User user, PermissionType permissionType, String target) { - Integer result; - List roles = new ArrayList<>(); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = persistence.getEntityManager(); - user = em.find(User.class, user.getId()); - for (UserRole userRole : user.getUserRoles()) { - if (userRole.getRole() != null) { - roles.add(userRole.getRole()); - } - } - UserSession session = new UserSession(uuidSource.createUuid(), user, roles, userSessionSource.getLocale(), false); - compilePermissions(session, roles); - result = session.getPermissionValue(permissionType, target); - tx.commit(); - } finally { - tx.end(); - } - return result; - } - - /** - * INTERNAL - */ - public void clearPermissionsOnUser(UserSession session) { - List users = new ArrayList<>(); - users.add(session.getUser()); - if (session.getSubstitutedUser() != null) { - users.add(session.getSubstitutedUser()); - } - for (User user : users) { - if (PersistenceHelper.isDetached(user) && user.getUserRoles() != null) { - for (UserRole userRole : user.getUserRoles()) { - Role role = userRole.getRole(); - if (userRole.getRole() != null && PersistenceHelper.isLoaded(role, "permissions")) { - userRole.getRole().setPermissions(null); - } - } - } - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.sys; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.*; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.PersistenceHelper; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.core.global.UuidSource; +import com.haulmont.cuba.core.sys.DefaultPermissionValuesConfig; +import com.haulmont.cuba.core.sys.UserSessionFinder; +import com.haulmont.cuba.security.app.UserSessionsAPI; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.security.global.NoUserSessionException; +import com.haulmont.cuba.security.global.UserSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.io.Serializable; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +/** + * System-level class managing {@link UserSession}s. + */ +@Component(UserSessionManager.NAME) +public class UserSessionManager implements UserSessionFinder { + + private final Logger log = LoggerFactory.getLogger(UserSessionManager.class); + + public static final String NAME = "cuba_UserSessionManager"; + + @Inject + protected UuidSource uuidSource; + + @Inject + protected UserSessionsAPI sessions; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected Persistence persistence; + + @Inject + protected Metadata metadata; + + @Inject + protected DefaultPermissionValuesConfig defaultPermissionValuesConfig; + + /** + * Create a new session and fill it with security data. Must be called inside a transaction. + * @param user user instance + * @param locale user locale + * @param system create system session + * @return new session instance + */ + public UserSession createSession(User user, Locale locale, boolean system) { + return createSession(uuidSource.createUuid(), user, locale, system); + } + + /** + * Create a new session and fill it with security data. Must be called inside a transaction. + * @param sessionId target session id + * @param user user instance + * @param locale user locale + * @param system create system session + * @return new session instance + */ + public UserSession createSession(UUID sessionId, User user, Locale locale, boolean system) { + List roles = new ArrayList<>(); + for (UserRole userRole : user.getUserRoles()) { + if (userRole.getRole() != null) { + roles.add(userRole.getRole()); + } + } + UserSession session = new UserSession(sessionId, user, roles, locale, system); + compilePermissions(session, roles); + if (user.getGroup() == null) + throw new IllegalStateException("User is not in a Group"); + compileConstraints(session, user.getGroup()); + compileSessionAttributes(session, user.getGroup()); + return session; + } + + /** + * Create a new session from existing for another user and fill it with security data for that new user. + * Must be called inside a transaction. + * @param src existing session + * @param user another user instance + * @return new session with the same ID as existing + */ + public UserSession createSession(UserSession src, User user) { + List roles = new ArrayList<>(); + for (UserRole userRole : user.getUserRoles()) { + if (userRole.getRole() != null) { + roles.add(userRole.getRole()); + } + } + UserSession session = new UserSession(src, user, roles, src.getLocale()); + compilePermissions(session, roles); + if (user.getGroup() == null) + throw new IllegalStateException("User is not in a Group"); + compileConstraints(session, user.getGroup()); + compileSessionAttributes(session, user.getGroup()); + return session; + } + + protected void compilePermissions(UserSession session, List roles) { + for (Role role : roles) { + if (RoleType.SUPER.equals(role.getType())) { + // Don't waste memory, as the user with SUPER role has all permissions. + return; + } + } + for (Role role : roles) { + for (Permission permission : role.getPermissions()) { + PermissionType type = permission.getType(); + if (type != null && permission.getValue() != null) { + try { + session.addPermission(type, + permission.getTarget(), convertToExtendedEntityTarget(permission), permission.getValue()); + } catch (Exception ignored) {} + } + } + } + + defaultPermissionValuesConfig.getDefaultPermissionValues().forEach((target, permission) -> { + if (session.getPermissionValue(permission.getType(), permission.getTarget()) == null) { + session.addPermission(permission.getType(), permission.getTarget(), + convertToExtendedEntityTarget(permission), permission.getValue()); + } + }); + } + + protected String convertToExtendedEntityTarget(Permission permission) { + if (permission.getType() == PermissionType.ENTITY_OP || permission.getType() == PermissionType.ENTITY_ATTR) { + String target = permission.getTarget(); + int pos = target.indexOf(Permission.TARGET_PATH_DELIMETER); + if (pos > -1) { + String entityName = target.substring(0, pos); + Class extendedClass = metadata.getExtendedEntities().getExtendedClass(metadata.getClassNN(entityName)); + if (extendedClass != null) { + MetaClass extMetaClass = metadata.getClassNN(extendedClass); + return extMetaClass.getName() + Permission.TARGET_PATH_DELIMETER + target.substring(pos + 1); + } + } + } + return null; + } + + protected void compileConstraints(UserSession session, Group group) { + EntityManager em = persistence.getEntityManager(); + TypedQuery q = em.createQuery("select c from sec$GroupHierarchy h join h.parent.constraints c " + + "where h.group.id = ?1", Constraint.class); + q.setParameter(1, group); + List constraints = q.getResultList(); + List list = new ArrayList<>(constraints); + list.addAll(group.getConstraints()); + for (Constraint constraint : list) { + if (Boolean.TRUE.equals(constraint.getIsActive())) { + session.addConstraint(constraint); + } + } + } + + protected void compileSessionAttributes(UserSession session, Group group) { + List list = new ArrayList<>(group.getSessionAttributes()); + + EntityManager em = persistence.getEntityManager(); + TypedQuery q = em.createQuery("select a from sec$GroupHierarchy h join h.parent.sessionAttributes a " + + "where h.group.id = ?1 order by h.level desc", SessionAttribute.class); + q.setParameter(1, group); + List attributes = q.getResultList(); + list.addAll(attributes); + + for (SessionAttribute attribute : list) { + Datatype datatype = Datatypes.get(attribute.getDatatype()); + try { + if (session.getAttributeNames().contains(attribute.getName())) { + log.warn("Duplicate definition of '{}' session attribute in the group hierarchy", attribute.getName()); + } + Serializable value = (Serializable) datatype.parse(attribute.getStringValue()); + if (value != null) + session.setAttribute(attribute.getName(), value); + else + session.removeAttribute(attribute.getName()); + } catch (ParseException e) { + throw new RuntimeException("Unable to set session attribute " + attribute.getName(), e); + } + } + } + + /** + * Store session in the distributed sessions cache. + * Should be called outside of transaction to ensure all persistent objects have been detached. + * @param session session instance + */ + public void storeSession(UserSession session) { + sessions.add(session); + } + + /** + * Remove the session from the distributed sessions cache. + * Should be called outside of transaction to ensure all persistent objects have been detached. + * @param session session instance + */ + public void removeSession(UserSession session) { + sessions.remove(session); + } + + /** + * Search for session in cache. + * @param sessionId session's ID + * @return session instance + * @throws NoUserSessionException in case of session with the specified ID is not found in cache. + */ + public UserSession getSession(UUID sessionId) { + UserSession session = findSession(sessionId); + if (session == null) { + throw new NoUserSessionException(sessionId); + } + return session; + } + + /** + * Search for session in cache. + * @param sessionId session's ID + * @return session instance or null if not found + */ + @Override + public UserSession findSession(UUID sessionId) { + return sessions.get(sessionId, false); + } + + public Integer getPermissionValue(User user, PermissionType permissionType, String target) { + Integer result; + List roles = new ArrayList<>(); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = persistence.getEntityManager(); + user = em.find(User.class, user.getId()); + for (UserRole userRole : user.getUserRoles()) { + if (userRole.getRole() != null) { + roles.add(userRole.getRole()); + } + } + UserSession session = new UserSession(uuidSource.createUuid(), user, roles, userSessionSource.getLocale(), false); + compilePermissions(session, roles); + result = session.getPermissionValue(permissionType, target); + tx.commit(); + } finally { + tx.end(); + } + return result; + } + + /** + * INTERNAL + */ + public void clearPermissionsOnUser(UserSession session) { + List users = new ArrayList<>(); + users.add(session.getUser()); + if (session.getSubstitutedUser() != null) { + users.add(session.getSubstitutedUser()); + } + for (User user : users) { + if (PersistenceHelper.isDetached(user) && user.getUserRoles() != null) { + for (UserRole userRole : user.getUserRoles()) { + Role role = userRole.getRole(); + if (userRole.getRole() != null && PersistenceHelper.isLoaded(role, "permissions")) { + userRole.getRole().setPermissions(null); + } + } + } + } + } +} diff --git a/modules/core/src/cuba-app.properties b/modules/core/src/cuba-app.properties index f1b46ad0ce..2bdd134cca 100644 --- a/modules/core/src/cuba-app.properties +++ b/modules/core/src/cuba-app.properties @@ -1,75 +1,75 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -############################################################################### -# Names and Directories # -############################################################################### - -# URL -cuba.webHostName=localhost -cuba.webPort=8080 -cuba.webContextName=cuba-core - -cuba.dispatcherBaseUrl=http://${cuba.webHostName}:${cuba.webPort}/${cuba.webContextName}/remoting - -cuba.dataSourceJndiName=java:comp/env/jdbc/CubaDS - -# System directories -cuba.confDir=${catalina.base}/conf/${cuba.webContextName} -cuba.dbDir=${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/db -cuba.logDir=${catalina.base}/logs -cuba.tempDir=${catalina.base}/temp/${cuba.webContextName} -cuba.dataDir=${catalina.base}/work/${cuba.webContextName} - -cuba.download.directories=${cuba.tempDir};\ - ${cuba.logDir} - -cuba.classpath.directories=${catalina.base}/lib;\ - ${catalina.base}/shared/classes;\ - ${catalina.base}/shared/lib;\ - ${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/classes;\ - ${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/lib - -############################################################################### -# Configuration # -############################################################################### - -cuba.dbmsType=hsql - -cuba.springContextConfig=cuba-spring.xml -cuba.remotingSpringContextConfig=cuba-remoting-spring.xml -cuba.persistenceConfig = base-persistence.xml cuba-persistence.xml -cuba.metadataConfig = cuba-metadata.xml -cuba.viewsConfig=cuba-views.xml -cuba.defaultPermissionValuesConfig=cuba-default-permission-values.xml -cuba.mainMessagePack=com.haulmont.cuba.core - -cuba.groovyClassPath= -cuba.groovyEvaluatorImport=com.haulmont.cuba.core.global.PersistenceHelper - -cuba.automaticDatabaseUpdate=false - -cuba.passwordEncryptionModule=cuba_Sha1EncryptionModule - -cuba.trustedClientPassword=MLdWm1Ik4NmM - -cuba.anonymousSessionId=9c91dbdf-3e73-428e-9088-d586da2434c5 - -# ORM properties (see http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/persistenceproperties_ref.htm) -eclipselink.cache.shared.default = false -eclipselink.cache.coordination.protocol = com.haulmont.cuba.core.sys.entitycache.EntityCacheTransportManager -eclipselink.cache.coordination.propagate-asynchronously = false +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +############################################################################### +# Names and Directories # +############################################################################### + +# URL +cuba.webHostName=localhost +cuba.webPort=8080 +cuba.webContextName=cuba-core + +cuba.dispatcherBaseUrl=http://${cuba.webHostName}:${cuba.webPort}/${cuba.webContextName}/remoting + +cuba.dataSourceJndiName=java:comp/env/jdbc/CubaDS + +# System directories +cuba.confDir=${catalina.base}/conf/${cuba.webContextName} +cuba.dbDir=${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/db +cuba.logDir=${catalina.base}/logs +cuba.tempDir=${catalina.base}/temp/${cuba.webContextName} +cuba.dataDir=${catalina.base}/work/${cuba.webContextName} + +cuba.download.directories=${cuba.tempDir};\ + ${cuba.logDir} + +cuba.classpath.directories=${catalina.base}/lib;\ + ${catalina.base}/shared/classes;\ + ${catalina.base}/shared/lib;\ + ${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/classes;\ + ${catalina.base}/webapps/${cuba.webContextName}/WEB-INF/lib + +############################################################################### +# Configuration # +############################################################################### + +cuba.dbmsType=hsql + +cuba.springContextConfig=cuba-spring.xml +cuba.remotingSpringContextConfig=cuba-remoting-spring.xml +cuba.persistenceConfig = base-persistence.xml cuba-persistence.xml +cuba.metadataConfig = cuba-metadata.xml +cuba.viewsConfig=cuba-views.xml +cuba.defaultPermissionValuesConfig=cuba-default-permission-values.xml +cuba.mainMessagePack=com.haulmont.cuba.core + +cuba.groovyClassPath= +cuba.groovyEvaluatorImport=com.haulmont.cuba.core.global.PersistenceHelper + +cuba.automaticDatabaseUpdate=false + +cuba.passwordEncryptionModule=cuba_Sha1EncryptionModule + +cuba.trustedClientPassword=MLdWm1Ik4NmM + +cuba.anonymousSessionId=9c91dbdf-3e73-428e-9088-d586da2434c5 + +# ORM properties (see http://www.eclipse.org/eclipselink/documentation/2.6/jpa/extensions/persistenceproperties_ref.htm) +eclipselink.cache.shared.default = false +eclipselink.cache.coordination.protocol = com.haulmont.cuba.core.sys.entitycache.EntityCacheTransportManager +eclipselink.cache.coordination.propagate-asynchronously = false diff --git a/modules/core/src/cuba-default-permission-values.xml b/modules/core/src/cuba-default-permission-values.xml index 50b466f947..5f3fd120dd 100644 --- a/modules/core/src/cuba-default-permission-values.xml +++ b/modules/core/src/cuba-default-permission-values.xml @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/core/src/cuba-mybatis.xml b/modules/core/src/cuba-mybatis.xml index 5580f9f63a..476a640419 100644 --- a/modules/core/src/cuba-mybatis.xml +++ b/modules/core/src/cuba-mybatis.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/core/src/cuba-remoting-spring.xml b/modules/core/src/cuba-remoting-spring.xml index c62a6f1d1d..59dc7c6e8e 100644 --- a/modules/core/src/cuba-remoting-spring.xml +++ b/modules/core/src/cuba-remoting-spring.xml @@ -1,62 +1,62 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/core/src/cuba-spring.xml b/modules/core/src/cuba-spring.xml index 5f6f3adc58..5da9e1eec7 100644 --- a/modules/core/src/cuba-spring.xml +++ b/modules/core/src/cuba-spring.xml @@ -1,214 +1,214 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/core/src/default-permission-values.xsd b/modules/core/src/default-permission-values.xsd index 098b8d49be..9f5ec7b4af 100644 --- a/modules/core/src/default-permission-values.xsd +++ b/modules/core/src/default-permission-values.xsd @@ -1,40 +1,40 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/modules/core/test/com/haulmont/cuba/core/AppContextTest.java b/modules/core/test/com/haulmont/cuba/core/AppContextTest.java index d61dcb768e..5e34c67644 100644 --- a/modules/core/test/com/haulmont/cuba/core/AppContextTest.java +++ b/modules/core/test/com/haulmont/cuba/core/AppContextTest.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - -public class AppContextTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void test() { - Persistence persistence = AppBeans.get(Persistence.NAME, Persistence.class); - assertNotNull(persistence); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +public class AppContextTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void test() { + Persistence persistence = AppBeans.get(Persistence.NAME, Persistence.class); + assertNotNull(persistence); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/ConfigProviderTest.java b/modules/core/test/com/haulmont/cuba/core/ConfigProviderTest.java index 28d2f3c890..b2d0495287 100644 --- a/modules/core/test/com/haulmont/cuba/core/ConfigProviderTest.java +++ b/modules/core/test/com/haulmont/cuba/core/ConfigProviderTest.java @@ -1,245 +1,245 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.config.TestBeanToInjectConfig; -import com.haulmont.cuba.core.config.TestConfig; -import com.haulmont.cuba.core.entity.Config; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.security.entity.RoleType; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.ClassRule; -import org.junit.Test; - -import java.lang.reflect.Method; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class ConfigProviderTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @After - public void tearDown() throws Exception { - cleanup(); - } - - @Test - public void testAppProperties() { - TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); - - // String property - - String stringProp = config.getStringProp(); - assertNull(stringProp); - - String stringPropDef = config.getStringPropDef(); - assertEquals("def_value", stringPropDef); - - config.setStringProp("test_value"); - stringProp = config.getStringProp(); - assertEquals("test_value", stringProp); - - // Integer property - - Integer integerProp = config.getIntegerProp(); - assertNull(integerProp); - - Integer integerPropDef = config.getIntegerPropDef(); - assertEquals(Integer.valueOf(100), integerPropDef); - - Integer integerPropDefRuntime = config.getIntegerPropDefRuntime(200); - assertEquals(Integer.valueOf(200), integerPropDefRuntime); - - config.setIntegerProp(10); - integerProp = config.getIntegerProp(); - assertEquals(Integer.valueOf(10), integerProp); - - // primitive int - - int intPropDef = config.getIntPropDef(); - assertEquals(0, intPropDef); - - config.setIntPropDef(1); - intPropDef = config.getIntPropDef(); - assertEquals(1, intPropDef); - - int intPropDefRuntime = config.getIntPropDefRuntime(11); - assertEquals(11, intPropDefRuntime); - - config.setIntPropDefRuntime(12); - intPropDefRuntime = config.getIntPropDefRuntime(11); - assertEquals(12, intPropDefRuntime); - - // Boolean property - - Boolean booleanProp = config.getBooleanProp(); - assertNull(booleanProp); - - config.setBooleanProp(true); - booleanProp = config.getBooleanProp(); - assertTrue(booleanProp); - - Boolean booleanPropDef = config.getBooleanPropDef(); - assertTrue(booleanPropDef); - - // primitive boolean - - boolean boolProp = config.getBoolProp(); - assertFalse(boolProp); - - config.setBoolProp(true); - boolProp = config.getBoolProp(); - assertTrue(boolProp); - - // UUID property - - UUID uuidProp = config.getUuidProp(); - assertNull(uuidProp); - - UUID uuid = UUID.randomUUID(); - config.setUuidProp(uuid); - uuidProp = config.getUuidProp(); - assertEquals(uuid, uuidProp); - - // Entity property - User adminUser = config.getAdminUser(); - assertNotNull(adminUser); - assertEquals("admin", adminUser.getLogin()); - - // Enum property - RoleType roleType = config.getRoleTypeProp(); - assertTrue(roleType == RoleType.STANDARD); - - // Date property - Date date = config.getDateProp(); - try { - assertEquals(new SimpleDateFormat("yyyy-MM-dd").parse("2013-12-12"), date); - } catch (ParseException e) { - throw new RuntimeException(e); - } - - // List of Integer - List integerList = config.getIntegerListProp(); - assertEquals(Arrays.asList(1, 2, 3), integerList); - - // List of String - List stringList = config.getStringListProp(); - assertEquals(Arrays.asList("aaa", "bbb", "ccc"), stringList); - } - - @Test - public void testDatabaseProperties() throws Exception { - TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); - - String dbProp = config.getDatabaseProp(); - assertNull(dbProp); - - config.setDatabaseProp("test_value"); - dbProp = config.getDatabaseProp(); - assertEquals("test_value", dbProp); - - config.setDatabaseProp("test_value_1"); - dbProp = config.getDatabaseProp(); - assertEquals("test_value_1", dbProp); - - AppContext.setProperty("cuba.test.databaseProp", "overridden_value"); - dbProp = config.getDatabaseProp(); - assertEquals("overridden_value", dbProp); - - AppContext.setProperty("cuba.test.databaseProp", ""); - dbProp = config.getDatabaseProp(); - assertEquals("test_value_1", dbProp); - } - - @Test - public void testBooleanType() throws Exception { - Method booleanMethod = TestConfig.class.getMethod("getBooleanProp"); - Class booleanMethodReturnType = booleanMethod.getReturnType(); - assertFalse(Boolean.TYPE.equals(booleanMethodReturnType)); - - Method boolMethod = TestConfig.class.getMethod("getBoolProp"); - Class boolMethodReturnType = boolMethod.getReturnType(); - assertEquals(Boolean.TYPE, boolMethodReturnType); - } - - @Test - public void testInjectedConfig() throws Exception { - TestBeanToInjectConfig bean = AppBeans.get(TestBeanToInjectConfig.class); - TestConfig config = bean.getConfig(); - assertNotNull(config); - assertTrue(config.getBooleanPropDef()); - } - - @Test - public void testInjectedConfigBySetter() throws Exception { - TestBeanToInjectConfig bean = AppBeans.get(TestBeanToInjectConfig.class); - TestConfig config = bean.getConfig2(); - assertNotNull(config); - assertTrue(config.getBooleanPropDef()); - } - - @Test - public void testSystemPropOverridesAppProp() throws Exception { - TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); - - String value = config.getStringPropDef(); - assertEquals("def_value", value); - - System.setProperty("cuba.test.stringPropDef", "new_value"); - value = config.getStringPropDef(); - assertEquals("new_value", value); - } - - @Test - public void testNotFoundGetterForProperty() { - try { - TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); - config.setStringNotFoundGetProp("problem"); - fail("Exception is not thrown for property without getter"); - } catch (Exception e) { - //it's OK - } - } - - private void cleanup() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Query query = em.createQuery("select c from sys$Config c where c.name like ?1"); - query.setParameter(1, "cuba.test.%"); - List list = query.getResultList(); - for (Config config : list) { - em.remove(config); - } - tx.commit(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.config.TestBeanToInjectConfig; +import com.haulmont.cuba.core.config.TestConfig; +import com.haulmont.cuba.core.entity.Config; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.security.entity.RoleType; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class ConfigProviderTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @After + public void tearDown() throws Exception { + cleanup(); + } + + @Test + public void testAppProperties() { + TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); + + // String property + + String stringProp = config.getStringProp(); + assertNull(stringProp); + + String stringPropDef = config.getStringPropDef(); + assertEquals("def_value", stringPropDef); + + config.setStringProp("test_value"); + stringProp = config.getStringProp(); + assertEquals("test_value", stringProp); + + // Integer property + + Integer integerProp = config.getIntegerProp(); + assertNull(integerProp); + + Integer integerPropDef = config.getIntegerPropDef(); + assertEquals(Integer.valueOf(100), integerPropDef); + + Integer integerPropDefRuntime = config.getIntegerPropDefRuntime(200); + assertEquals(Integer.valueOf(200), integerPropDefRuntime); + + config.setIntegerProp(10); + integerProp = config.getIntegerProp(); + assertEquals(Integer.valueOf(10), integerProp); + + // primitive int + + int intPropDef = config.getIntPropDef(); + assertEquals(0, intPropDef); + + config.setIntPropDef(1); + intPropDef = config.getIntPropDef(); + assertEquals(1, intPropDef); + + int intPropDefRuntime = config.getIntPropDefRuntime(11); + assertEquals(11, intPropDefRuntime); + + config.setIntPropDefRuntime(12); + intPropDefRuntime = config.getIntPropDefRuntime(11); + assertEquals(12, intPropDefRuntime); + + // Boolean property + + Boolean booleanProp = config.getBooleanProp(); + assertNull(booleanProp); + + config.setBooleanProp(true); + booleanProp = config.getBooleanProp(); + assertTrue(booleanProp); + + Boolean booleanPropDef = config.getBooleanPropDef(); + assertTrue(booleanPropDef); + + // primitive boolean + + boolean boolProp = config.getBoolProp(); + assertFalse(boolProp); + + config.setBoolProp(true); + boolProp = config.getBoolProp(); + assertTrue(boolProp); + + // UUID property + + UUID uuidProp = config.getUuidProp(); + assertNull(uuidProp); + + UUID uuid = UUID.randomUUID(); + config.setUuidProp(uuid); + uuidProp = config.getUuidProp(); + assertEquals(uuid, uuidProp); + + // Entity property + User adminUser = config.getAdminUser(); + assertNotNull(adminUser); + assertEquals("admin", adminUser.getLogin()); + + // Enum property + RoleType roleType = config.getRoleTypeProp(); + assertTrue(roleType == RoleType.STANDARD); + + // Date property + Date date = config.getDateProp(); + try { + assertEquals(new SimpleDateFormat("yyyy-MM-dd").parse("2013-12-12"), date); + } catch (ParseException e) { + throw new RuntimeException(e); + } + + // List of Integer + List integerList = config.getIntegerListProp(); + assertEquals(Arrays.asList(1, 2, 3), integerList); + + // List of String + List stringList = config.getStringListProp(); + assertEquals(Arrays.asList("aaa", "bbb", "ccc"), stringList); + } + + @Test + public void testDatabaseProperties() throws Exception { + TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); + + String dbProp = config.getDatabaseProp(); + assertNull(dbProp); + + config.setDatabaseProp("test_value"); + dbProp = config.getDatabaseProp(); + assertEquals("test_value", dbProp); + + config.setDatabaseProp("test_value_1"); + dbProp = config.getDatabaseProp(); + assertEquals("test_value_1", dbProp); + + AppContext.setProperty("cuba.test.databaseProp", "overridden_value"); + dbProp = config.getDatabaseProp(); + assertEquals("overridden_value", dbProp); + + AppContext.setProperty("cuba.test.databaseProp", ""); + dbProp = config.getDatabaseProp(); + assertEquals("test_value_1", dbProp); + } + + @Test + public void testBooleanType() throws Exception { + Method booleanMethod = TestConfig.class.getMethod("getBooleanProp"); + Class booleanMethodReturnType = booleanMethod.getReturnType(); + assertFalse(Boolean.TYPE.equals(booleanMethodReturnType)); + + Method boolMethod = TestConfig.class.getMethod("getBoolProp"); + Class boolMethodReturnType = boolMethod.getReturnType(); + assertEquals(Boolean.TYPE, boolMethodReturnType); + } + + @Test + public void testInjectedConfig() throws Exception { + TestBeanToInjectConfig bean = AppBeans.get(TestBeanToInjectConfig.class); + TestConfig config = bean.getConfig(); + assertNotNull(config); + assertTrue(config.getBooleanPropDef()); + } + + @Test + public void testInjectedConfigBySetter() throws Exception { + TestBeanToInjectConfig bean = AppBeans.get(TestBeanToInjectConfig.class); + TestConfig config = bean.getConfig2(); + assertNotNull(config); + assertTrue(config.getBooleanPropDef()); + } + + @Test + public void testSystemPropOverridesAppProp() throws Exception { + TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); + + String value = config.getStringPropDef(); + assertEquals("def_value", value); + + System.setProperty("cuba.test.stringPropDef", "new_value"); + value = config.getStringPropDef(); + assertEquals("new_value", value); + } + + @Test + public void testNotFoundGetterForProperty() { + try { + TestConfig config = AppBeans.get(Configuration.class).getConfig(TestConfig.class); + config.setStringNotFoundGetProp("problem"); + fail("Exception is not thrown for property without getter"); + } catch (Exception e) { + //it's OK + } + } + + private void cleanup() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Query query = em.createQuery("select c from sys$Config c where c.name like ?1"); + query.setParameter(1, "cuba.test.%"); + List list = query.getResultList(); + for (Config config : list) { + em.remove(config); + } + tx.commit(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/CubaTestCase.java b/modules/core/test/com/haulmont/cuba/core/CubaTestCase.java index d9ce3d0727..1956bad7ce 100644 --- a/modules/core/test/com/haulmont/cuba/core/CubaTestCase.java +++ b/modules/core/test/com/haulmont/cuba/core/CubaTestCase.java @@ -1,159 +1,159 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.PasswordEncryption; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestContext; -import com.haulmont.cuba.testsupport.TestDataSource; -import junit.framework.TestCase; -import org.apache.commons.lang.StringUtils; - -import java.util.*; - -/** - * DEPRECATED. Use TestContainer and JUnit4 test annotations: - *

- *     {@literal@}ClassRule
- *     public static TestContainer cont = TestContainer.Common.INSTANCE;
- *
- *     {@literal@}Test
- *     public void testSomething() {
- *     }
- * 
- * - */ -@Deprecated -public abstract class CubaTestCase extends TestCase { - - protected static boolean initialized; - - protected static TestContainer cont; - - static { - String property = System.getProperty("logback.configurationFile"); - if (StringUtils.isBlank(property)) { - System.setProperty("logback.configurationFile", "test-logback.xml"); - } - } - - protected Persistence persistence; - protected Metadata metadata; - protected PasswordEncryption passwordEncryption; - - private class CommonTestContainer extends TestContainer { - @Override - public void before() throws Throwable { - super.before(); - } - - @Override - public void after() { - super.after(); - } - - @Override - public void cleanupContext() { - super.cleanupContext(); - } - - @Override - public void setupContext() { - super.setupContext(); - } - - @Override - protected void initDataSources() { - try { - CubaTestCase.this.initDataSources(); - } catch (Exception e) { - throw new RuntimeException("Error initializing datasource", e); - } - } - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - try { - if (!initialized) { - System.setProperty("cuba.unitTestMode", "true"); - cont = new CommonTestContainer(); - cont.setAppComponents(getTestAppComponents()); - cont.setAppPropertiesFiles(getTestAppProperties()); - cont.setSpringConfig(getTestSpringConfig()); - ((CommonTestContainer) cont).before(); - initialized = true; - } - - ((CommonTestContainer) cont).setupContext(); - - persistence = AppBeans.get(Persistence.class); - metadata = AppBeans.get(Metadata.class); - passwordEncryption = AppBeans.get(PasswordEncryption.class); - } catch (Throwable throwable) { - if (throwable instanceof Exception) - throw (Exception) throwable; - else - throw new RuntimeException(throwable); - } - } - - @Override - protected void tearDown() throws Exception { - TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); - ((CommonTestContainer) cont).cleanupContext(); - super.tearDown(); - } - - protected void initDataSources() throws Exception { - Class.forName("org.hsqldb.jdbc.JDBCDriver"); - TestDataSource ds = new TestDataSource("jdbc:hsqldb:hsql://localhost/cubadb", "sa", ""); - TestContext.getInstance().bind(AppContext.getProperty("cuba.dataSourceJndiName"), ds); - } - - protected List getTestAppComponents() { - return Collections.emptyList(); - } - - protected List getTestAppProperties() { - String[] files = { - "cuba-app.properties", - "test-app.properties", - }; - return Arrays.asList(files); - } - - protected String getTestSpringConfig() { - return "test-spring.xml"; - } - - protected void deleteRecord(String table, UUID... ids) { - cont.deleteRecord(table, ids); - } - - protected void deleteRecord(String table, String primaryKeyCol, UUID... ids) { - cont.deleteRecord(table, primaryKeyCol, ids); - } - - protected EntityManager entityManager() { - return persistence.getEntityManager(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.PasswordEncryption; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestContext; +import com.haulmont.cuba.testsupport.TestDataSource; +import junit.framework.TestCase; +import org.apache.commons.lang.StringUtils; + +import java.util.*; + +/** + * DEPRECATED. Use TestContainer and JUnit4 test annotations: + *
+ *     {@literal@}ClassRule
+ *     public static TestContainer cont = TestContainer.Common.INSTANCE;
+ *
+ *     {@literal@}Test
+ *     public void testSomething() {
+ *     }
+ * 
+ * + */ +@Deprecated +public abstract class CubaTestCase extends TestCase { + + protected static boolean initialized; + + protected static TestContainer cont; + + static { + String property = System.getProperty("logback.configurationFile"); + if (StringUtils.isBlank(property)) { + System.setProperty("logback.configurationFile", "test-logback.xml"); + } + } + + protected Persistence persistence; + protected Metadata metadata; + protected PasswordEncryption passwordEncryption; + + private class CommonTestContainer extends TestContainer { + @Override + public void before() throws Throwable { + super.before(); + } + + @Override + public void after() { + super.after(); + } + + @Override + public void cleanupContext() { + super.cleanupContext(); + } + + @Override + public void setupContext() { + super.setupContext(); + } + + @Override + protected void initDataSources() { + try { + CubaTestCase.this.initDataSources(); + } catch (Exception e) { + throw new RuntimeException("Error initializing datasource", e); + } + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + try { + if (!initialized) { + System.setProperty("cuba.unitTestMode", "true"); + cont = new CommonTestContainer(); + cont.setAppComponents(getTestAppComponents()); + cont.setAppPropertiesFiles(getTestAppProperties()); + cont.setSpringConfig(getTestSpringConfig()); + ((CommonTestContainer) cont).before(); + initialized = true; + } + + ((CommonTestContainer) cont).setupContext(); + + persistence = AppBeans.get(Persistence.class); + metadata = AppBeans.get(Metadata.class); + passwordEncryption = AppBeans.get(PasswordEncryption.class); + } catch (Throwable throwable) { + if (throwable instanceof Exception) + throw (Exception) throwable; + else + throw new RuntimeException(throwable); + } + } + + @Override + protected void tearDown() throws Exception { + TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); + ((CommonTestContainer) cont).cleanupContext(); + super.tearDown(); + } + + protected void initDataSources() throws Exception { + Class.forName("org.hsqldb.jdbc.JDBCDriver"); + TestDataSource ds = new TestDataSource("jdbc:hsqldb:hsql://localhost/cubadb", "sa", ""); + TestContext.getInstance().bind(AppContext.getProperty("cuba.dataSourceJndiName"), ds); + } + + protected List getTestAppComponents() { + return Collections.emptyList(); + } + + protected List getTestAppProperties() { + String[] files = { + "cuba-app.properties", + "test-app.properties", + }; + return Arrays.asList(files); + } + + protected String getTestSpringConfig() { + return "test-spring.xml"; + } + + protected void deleteRecord(String table, UUID... ids) { + cont.deleteRecord(table, ids); + } + + protected void deleteRecord(String table, String primaryKeyCol, UUID... ids) { + cont.deleteRecord(table, primaryKeyCol, ids); + } + + protected EntityManager entityManager() { + return persistence.getEntityManager(); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/DataManagerCommitTest.java b/modules/core/test/com/haulmont/cuba/core/DataManagerCommitTest.java index 0037d7cecb..02c5c540f2 100644 --- a/modules/core/test/com/haulmont/cuba/core/DataManagerCommitTest.java +++ b/modules/core/test/com/haulmont/cuba/core/DataManagerCommitTest.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.Role; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserRole; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestSupport; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.UUID; - -import static org.junit.Assert.*; - -public class DataManagerCommitTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private DataManager dataManager; - private UUID userId; - private UUID groupId = UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"); - private UUID userRoleId; - private View view; - - @Before - public void setUp() throws Exception { - dataManager = AppBeans.get(DataManager.class); - - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, groupId); - Role role = em.find(Role.class, UUID.fromString("0c018061-b26f-4de2-a5be-dff348347f93")); - - User user = new User(); - userId = user.getId(); - user.setName("testUser"); - user.setLogin("login" + userId); - user.setPassword("000"); - user.setGroup(group); - em.persist(user); - - UserRole userRole = new UserRole(); - userRoleId = userRole.getId(); - userRole.setRole(role); - userRole.setUser(user); - em.persist(userRole); - - tx.commit(); - } - - view = new View(User.class, true) - .addProperty("login") - .addProperty("loginLowerCase") - .addProperty("name") - .addProperty("password") - .addProperty("group", new View(Group.class).addProperty("name")) - .addProperty("userRoles", new View(UserRole.class)); - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER_ROLE", userRoleId); - cont.deleteRecord("SEC_USER", userId); - } - - @Test - public void testViewAfterCommit() throws Exception { - LoadContext loadContext = LoadContext.create(User.class).setId(userId).setView(view); - User user = dataManager.load(loadContext); - assertNotNull(user); - user = TestSupport.reserialize(user); - assertEquals(groupId, user.getGroup().getId()); - assertEquals(1, user.getUserRoles().size()); - assertEquals(userRoleId, user.getUserRoles().get(0).getId()); - - Integer version = user.getVersion(); - user.setName("testUser-changed"); - user = dataManager.commit(user, view); - assertNotNull(user); - - //do check loaded before serialization - assertTrue(PersistenceHelper.isLoaded(user, "group")); - assertTrue(PersistenceHelper.isLoaded(user, "userRoles")); - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); - //do second check to make sure isLoaded did not affect attribute fetch status - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); - - user = TestSupport.reserialize(user); - - assertTrue(PersistenceHelper.isDetached(user)); - assertTrue(!PersistenceHelper.isNew(user)); - assertTrue(!PersistenceHelper.isManaged(user)); - - assertEquals(version + 1, (int) user.getVersion()); - assertEquals("testUser-changed", user.getName()); - assertEquals(groupId, user.getGroup().getId()); - assertEquals(1, user.getUserRoles().size()); - assertEquals(userRoleId, user.getUserRoles().get(0).getId()); - - //do check loaded after serialization - assertTrue(PersistenceHelper.isLoaded(user, "group")); - assertTrue(PersistenceHelper.isLoaded(user, "userRoles")); - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); - //do second check to make sure isLoaded did not affect attribute fetch status - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.Role; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserRole; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestSupport; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.UUID; + +import static org.junit.Assert.*; + +public class DataManagerCommitTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private DataManager dataManager; + private UUID userId; + private UUID groupId = UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"); + private UUID userRoleId; + private View view; + + @Before + public void setUp() throws Exception { + dataManager = AppBeans.get(DataManager.class); + + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, groupId); + Role role = em.find(Role.class, UUID.fromString("0c018061-b26f-4de2-a5be-dff348347f93")); + + User user = new User(); + userId = user.getId(); + user.setName("testUser"); + user.setLogin("login" + userId); + user.setPassword("000"); + user.setGroup(group); + em.persist(user); + + UserRole userRole = new UserRole(); + userRoleId = userRole.getId(); + userRole.setRole(role); + userRole.setUser(user); + em.persist(userRole); + + tx.commit(); + } + + view = new View(User.class, true) + .addProperty("login") + .addProperty("loginLowerCase") + .addProperty("name") + .addProperty("password") + .addProperty("group", new View(Group.class).addProperty("name")) + .addProperty("userRoles", new View(UserRole.class)); + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER_ROLE", userRoleId); + cont.deleteRecord("SEC_USER", userId); + } + + @Test + public void testViewAfterCommit() throws Exception { + LoadContext loadContext = LoadContext.create(User.class).setId(userId).setView(view); + User user = dataManager.load(loadContext); + assertNotNull(user); + user = TestSupport.reserialize(user); + assertEquals(groupId, user.getGroup().getId()); + assertEquals(1, user.getUserRoles().size()); + assertEquals(userRoleId, user.getUserRoles().get(0).getId()); + + Integer version = user.getVersion(); + user.setName("testUser-changed"); + user = dataManager.commit(user, view); + assertNotNull(user); + + //do check loaded before serialization + assertTrue(PersistenceHelper.isLoaded(user, "group")); + assertTrue(PersistenceHelper.isLoaded(user, "userRoles")); + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); + //do second check to make sure isLoaded did not affect attribute fetch status + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); + + user = TestSupport.reserialize(user); + + assertTrue(PersistenceHelper.isDetached(user)); + assertTrue(!PersistenceHelper.isNew(user)); + assertTrue(!PersistenceHelper.isManaged(user)); + + assertEquals(version + 1, (int) user.getVersion()); + assertEquals("testUser-changed", user.getName()); + assertEquals(groupId, user.getGroup().getId()); + assertEquals(1, user.getUserRoles().size()); + assertEquals(userRoleId, user.getUserRoles().get(0).getId()); + + //do check loaded after serialization + assertTrue(PersistenceHelper.isLoaded(user, "group")); + assertTrue(PersistenceHelper.isLoaded(user, "userRoles")); + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); + //do second check to make sure isLoaded did not affect attribute fetch status + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions")); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/DataManagerTest.java b/modules/core/test/com/haulmont/cuba/core/DataManagerTest.java index 7022603dec..319d596d65 100644 --- a/modules/core/test/com/haulmont/cuba/core/DataManagerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/DataManagerTest.java @@ -1,309 +1,309 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import javax.persistence.TemporalType; -import java.util.*; - -import static org.junit.Assert.*; - -public class DataManagerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - protected DataManager dataManager; - - @Before - public void setUp() throws Exception { - dataManager = AppBeans.get(DataManager.class); - - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - runner.update("delete from SYS_SERVER"); - } - - @Test - public void test() { - Server server = new Server(); - UUID id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class).setId(id); - - server = dataManager.load(loadContext); - assertEquals("localhost", server.getName()); - - server.setName("krivopustov"); - dataManager.commit(new CommitContext(Collections.singleton(server))); - } - - @Test - public void testLoad() { - Server server = new Server(); - UUID id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class).setId(id); - - server = dataManager.load(loadContext); - assertEquals("localhost", server.getName()); - } - - @Test - public void testLoadList() { - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class); - loadContext.setQueryString("select s from " + PersistenceHelper.getEntityName(Server.class) + " s"); - - List list = dataManager.loadList(loadContext); - assertTrue(list.size() > 0); - } - - @Test - public void testLoadListById() { - Server server = new Server(); - UUID id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class).setId(id); - - List list = dataManager.loadList(loadContext); - assertTrue(list.size() == 1); - } - - @Test - public void testAssociatedResult() throws Exception { - LoadContext loadContext = LoadContext.create(Group.class); - loadContext.setQueryString("select u.group from sec$User u where u.id = :userId") - .setParameter("userId", UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); - - List groups = dataManager.loadList(loadContext); - assertEquals(1, groups.size()); - } - - @Test - public void testLoadListCaseInsensitive() { - Server server = new Server(); - server.setName("LocalHost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class); - loadContext.setQueryString("select s from sys$Server s where s.name like :name") - .setParameter("name", "(?i)%loc%host%"); - - List list = dataManager.loadList(loadContext); - assertTrue(list.size() > 0); - } - - @Test - public void testLoadListCaseInsensitiveLower() { - Server server = new Server(); - server.setName("LocalHost"); - server.setRunning(true); - - DataManager dataManager = AppBeans.get(DataManager.NAME); - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class); - loadContext.setQueryString("select s from sys$Server s where s.name like :name") - .setParameter("name", "(?i)%localhost%"); - - List list = dataManager.loadList(loadContext); - assertTrue(list.size() > 0); - } - - @Test - public void testUnexistingQueryParameters() throws Exception { - LoadContext loadContext = LoadContext.create(User.class).setQuery( - LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("name", "admin")); - - try { - dataManager.loadList(loadContext); - fail("DataService must throw exception for nonexistent parameters"); - } catch (Exception e) { - // ok - } - - loadContext = LoadContext.create(User.class).setQuery( - LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); - List list = dataManager.loadList(loadContext); - assertEquals(1, list.size()); - } - - @Test - public void testGetCount() throws Exception { - LoadContext loadContext = LoadContext.create(User.class).setQuery( - LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); - - long count = dataManager.getCount(loadContext); - assertEquals(1, count); - - loadContext.getQuery().setParameter("login", "cc1aa09f-c5d5-4bd1-896c-cb774d2e2898"); - count = dataManager.getCount(loadContext); - assertEquals(0, count); - } - - @Test - public void testTemporalType() throws Exception { - Date nextYear = DateUtils.addYears(AppBeans.get(TimeSource.class).currentTimestamp(), 1); - LoadContext loadContext = LoadContext.create(User.class).setQuery( - LoadContext.createQuery("select u from sec$User u where u.createTs = :ts") - .setParameter("ts", nextYear, TemporalType.DATE)); - - List users = dataManager.loadList(loadContext); - assertTrue(users.isEmpty()); - } - - @Test - public void testExtendedLoadContext() throws Exception { - LoadContext loadContext = new MyLoadContext<>(User.class, "test").setQuery( - LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); - - long count = dataManager.getCount(loadContext); - assertEquals(1, count); - - } - - @Test - public void testReloadWithDynamicAttributes() { - Server server = new Server(); - UUID id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - - dataManager.commit(new CommitContext(Collections.singleton(server))); - - LoadContext loadContext = LoadContext.create(Server.class).setId(id).setLoadDynamicAttributes(true); - server = dataManager.load(loadContext); - assertNotNull(server.getDynamicAttributes()); - server = dataManager.reload(server, View.LOCAL); - assertNotNull(server.getDynamicAttributes()); - - loadContext = LoadContext.create(Server.class).setId(id).setLoadDynamicAttributes(false); - server = dataManager.load(loadContext); - assertNull(server.getDynamicAttributes()); - - loadContext = LoadContext.create(Server.class).setLoadDynamicAttributes(true); - loadContext.setQueryString("select s from sys$Server s where s.id = :id") - .setParameter("id", id); - List resultList = dataManager.loadList(loadContext); - assertNotNull(resultList.get(0).getDynamicAttributes()); - } - - @Test - public void testDataManagerLoadOneRecord() { - Server server1 = new Server(); - server1.setName("app1"); - server1.setRunning(false); - - Server server2 = new Server(); - server2.setName("app2"); - server2.setRunning(false); - - dataManager.commit(new CommitContext(server1, server2)); - - LoadContext lc = new LoadContext<>(Server.class); - lc.setQueryString("select s from sys$Server s order by s.name") - .setMaxResults(1); - - Server latest = dataManager.load(lc); - assertEquals(server1, latest); - } - - @Test - public void testNonEntityResults() throws Exception { - // fails on aggregates - LoadContext context = LoadContext.create(Server.class).setQuery(LoadContext.createQuery("select count(s) from sys$Server s")); - try { - dataManager.load(context); - fail(); - } catch (Exception e) { - assertTrue(e instanceof DevelopmentException); - } - - // fails on single attributes - context = LoadContext.create(Server.class).setQuery(LoadContext.createQuery("select s.name from sys$Server s")); - try { - dataManager.load(context); - fail(); - } catch (Exception e) { - assertTrue(e instanceof DevelopmentException); - } - } - - @Test - public void testDiscardCommitted() throws Exception { - Server server = new Server(); - server.setName("localhost"); - CommitContext commitContext = new CommitContext(server); - commitContext.setDiscardCommitted(true); - - Set committed = dataManager.commit(commitContext); - assertTrue(committed.isEmpty()); - - Server saved = dataManager.load(LoadContext.create(Server.class).setId(server.getId())); - assertNotNull(saved); - } - - public static class MyLoadContext extends LoadContext { - - private String info; - - public MyLoadContext() { - } - - public MyLoadContext(Class javaClass, String info) { - super(javaClass); - this.info = info; - } - - @Override - public MyLoadContext copy() { - MyLoadContext copy = (MyLoadContext) super.copy(); - copy.info = info; - return copy; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import javax.persistence.TemporalType; +import java.util.*; + +import static org.junit.Assert.*; + +public class DataManagerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + protected DataManager dataManager; + + @Before + public void setUp() throws Exception { + dataManager = AppBeans.get(DataManager.class); + + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + runner.update("delete from SYS_SERVER"); + } + + @Test + public void test() { + Server server = new Server(); + UUID id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class).setId(id); + + server = dataManager.load(loadContext); + assertEquals("localhost", server.getName()); + + server.setName("krivopustov"); + dataManager.commit(new CommitContext(Collections.singleton(server))); + } + + @Test + public void testLoad() { + Server server = new Server(); + UUID id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class).setId(id); + + server = dataManager.load(loadContext); + assertEquals("localhost", server.getName()); + } + + @Test + public void testLoadList() { + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class); + loadContext.setQueryString("select s from " + PersistenceHelper.getEntityName(Server.class) + " s"); + + List list = dataManager.loadList(loadContext); + assertTrue(list.size() > 0); + } + + @Test + public void testLoadListById() { + Server server = new Server(); + UUID id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class).setId(id); + + List list = dataManager.loadList(loadContext); + assertTrue(list.size() == 1); + } + + @Test + public void testAssociatedResult() throws Exception { + LoadContext loadContext = LoadContext.create(Group.class); + loadContext.setQueryString("select u.group from sec$User u where u.id = :userId") + .setParameter("userId", UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); + + List groups = dataManager.loadList(loadContext); + assertEquals(1, groups.size()); + } + + @Test + public void testLoadListCaseInsensitive() { + Server server = new Server(); + server.setName("LocalHost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class); + loadContext.setQueryString("select s from sys$Server s where s.name like :name") + .setParameter("name", "(?i)%loc%host%"); + + List list = dataManager.loadList(loadContext); + assertTrue(list.size() > 0); + } + + @Test + public void testLoadListCaseInsensitiveLower() { + Server server = new Server(); + server.setName("LocalHost"); + server.setRunning(true); + + DataManager dataManager = AppBeans.get(DataManager.NAME); + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class); + loadContext.setQueryString("select s from sys$Server s where s.name like :name") + .setParameter("name", "(?i)%localhost%"); + + List list = dataManager.loadList(loadContext); + assertTrue(list.size() > 0); + } + + @Test + public void testUnexistingQueryParameters() throws Exception { + LoadContext loadContext = LoadContext.create(User.class).setQuery( + LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("name", "admin")); + + try { + dataManager.loadList(loadContext); + fail("DataService must throw exception for nonexistent parameters"); + } catch (Exception e) { + // ok + } + + loadContext = LoadContext.create(User.class).setQuery( + LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); + List list = dataManager.loadList(loadContext); + assertEquals(1, list.size()); + } + + @Test + public void testGetCount() throws Exception { + LoadContext loadContext = LoadContext.create(User.class).setQuery( + LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); + + long count = dataManager.getCount(loadContext); + assertEquals(1, count); + + loadContext.getQuery().setParameter("login", "cc1aa09f-c5d5-4bd1-896c-cb774d2e2898"); + count = dataManager.getCount(loadContext); + assertEquals(0, count); + } + + @Test + public void testTemporalType() throws Exception { + Date nextYear = DateUtils.addYears(AppBeans.get(TimeSource.class).currentTimestamp(), 1); + LoadContext loadContext = LoadContext.create(User.class).setQuery( + LoadContext.createQuery("select u from sec$User u where u.createTs = :ts") + .setParameter("ts", nextYear, TemporalType.DATE)); + + List users = dataManager.loadList(loadContext); + assertTrue(users.isEmpty()); + } + + @Test + public void testExtendedLoadContext() throws Exception { + LoadContext loadContext = new MyLoadContext<>(User.class, "test").setQuery( + LoadContext.createQuery("select u from sec$User u where u.login = :login").setParameter("login", "admin")); + + long count = dataManager.getCount(loadContext); + assertEquals(1, count); + + } + + @Test + public void testReloadWithDynamicAttributes() { + Server server = new Server(); + UUID id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + + dataManager.commit(new CommitContext(Collections.singleton(server))); + + LoadContext loadContext = LoadContext.create(Server.class).setId(id).setLoadDynamicAttributes(true); + server = dataManager.load(loadContext); + assertNotNull(server.getDynamicAttributes()); + server = dataManager.reload(server, View.LOCAL); + assertNotNull(server.getDynamicAttributes()); + + loadContext = LoadContext.create(Server.class).setId(id).setLoadDynamicAttributes(false); + server = dataManager.load(loadContext); + assertNull(server.getDynamicAttributes()); + + loadContext = LoadContext.create(Server.class).setLoadDynamicAttributes(true); + loadContext.setQueryString("select s from sys$Server s where s.id = :id") + .setParameter("id", id); + List resultList = dataManager.loadList(loadContext); + assertNotNull(resultList.get(0).getDynamicAttributes()); + } + + @Test + public void testDataManagerLoadOneRecord() { + Server server1 = new Server(); + server1.setName("app1"); + server1.setRunning(false); + + Server server2 = new Server(); + server2.setName("app2"); + server2.setRunning(false); + + dataManager.commit(new CommitContext(server1, server2)); + + LoadContext lc = new LoadContext<>(Server.class); + lc.setQueryString("select s from sys$Server s order by s.name") + .setMaxResults(1); + + Server latest = dataManager.load(lc); + assertEquals(server1, latest); + } + + @Test + public void testNonEntityResults() throws Exception { + // fails on aggregates + LoadContext context = LoadContext.create(Server.class).setQuery(LoadContext.createQuery("select count(s) from sys$Server s")); + try { + dataManager.load(context); + fail(); + } catch (Exception e) { + assertTrue(e instanceof DevelopmentException); + } + + // fails on single attributes + context = LoadContext.create(Server.class).setQuery(LoadContext.createQuery("select s.name from sys$Server s")); + try { + dataManager.load(context); + fail(); + } catch (Exception e) { + assertTrue(e instanceof DevelopmentException); + } + } + + @Test + public void testDiscardCommitted() throws Exception { + Server server = new Server(); + server.setName("localhost"); + CommitContext commitContext = new CommitContext(server); + commitContext.setDiscardCommitted(true); + + Set committed = dataManager.commit(commitContext); + assertTrue(committed.isEmpty()); + + Server saved = dataManager.load(LoadContext.create(Server.class).setId(server.getId())); + assertNotNull(saved); + } + + public static class MyLoadContext extends LoadContext { + + private String info; + + public MyLoadContext() { + } + + public MyLoadContext(Class javaClass, String info) { + super(javaClass); + this.info = info; + } + + @Override + public MyLoadContext copy() { + MyLoadContext copy = (MyLoadContext) super.copy(); + copy.info = info; + return copy; + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/EclipseLinkQueriesTest.java b/modules/core/test/com/haulmont/cuba/core/EclipseLinkQueriesTest.java index 3e74d1f03d..c02c2971b3 100644 --- a/modules/core/test/com/haulmont/cuba/core/EclipseLinkQueriesTest.java +++ b/modules/core/test/com/haulmont/cuba/core/EclipseLinkQueriesTest.java @@ -1,171 +1,171 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.global.FetchMode; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.Constraint; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.List; -import java.util.UUID; - -import static com.haulmont.cuba.testsupport.TestSupport.reserialize; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class EclipseLinkQueriesTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - private User user1; - private User user2; - private Group rootGroup; - private Group group; - - @Before - public void setUp() throws Exception { - cont.persistence().createTransaction().execute(em -> { - rootGroup = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); - - user1 = cont.metadata().create(User.class); - user1.setName("testUser"); - user1.setLogin("testLogin"); - user1.setGroup(rootGroup); - em.persist(user1); - - group = cont.metadata().create(Group.class); - group.setParent(rootGroup); - group.setName("testGroup" + group.getId()); - em.persist(group); - - user2 = cont.metadata().create(User.class); - user2.setName("testUser2"); - user2.setLogin("testLogin2"); - user2.setGroup(group); - user2.setGroup(rootGroup); - em.persist(user2); - - return null; - }); - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", group.getId()); - cont.deleteRecord(user1, user2, group); - } - - // cross join, view has ToMany reference - @Test - public void testCrossJoinWithToManyView() throws Exception { - List result; - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.entityManager(); - View view = new View(Group.class).addProperty("constraints"); - TypedQuery query = em.createQuery("select g from sec$Group g, sec$User u where u.group = g", Group.class); - query.setView(view); - result = query.getResultList(); - tx.commit(); - } - for (Group group : result) { - group = reserialize(group); - group.getConstraints().size(); - } - } - - // cross join, view with the reference to the parent entity - @Test - public void testCrossJoinViewParentReference() throws Exception { - List result; - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.entityManager(); - View view = new View(Group.class).addProperty("parent"); - TypedQuery query = em.createQuery("select g from sec$Group g, sec$User u where u.group = g", Group.class); - query.setView(view); - result = query.getResultList(); - tx.commit(); - } - for (Group g : result) { - g = reserialize(g); - if (g.equals(rootGroup)) - assertNull(g.getParent()); - else if (g.equals(group)) - assertEquals(rootGroup, g.getParent()); - } - } - - // join on, view contains ToMany attribute - @Test - public void testJoinOnWithToManyView() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.entityManager(); - View view = new View(Group.class).addProperty("constraints"); - TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); - query.setView(view); - List result = query.getResultList(); - tx.commit(); - } - } - - // join on, view contains parent attribute - @Test - public void testJoinOnWithParentReference() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.entityManager(); - View view = new View(Group.class).addProperty("parent"); - TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); - query.setView(view); - List result = query.getResultList(); - tx.commit(); - } - } - - // join on, view contains ToMany attribute, fetch = JOIN - @Test - public void testJoinOnWithToManyView2() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.entityManager(); - View view = new View(Group.class).addProperty("constraints", new View(Constraint.class, View.LOCAL), FetchMode.JOIN); - TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); - query.setView(view); - List result = query.getResultList(); - tx.commit(); - } - } - - @Test - public void testSeveralEntriesInSelectClause() { - Object resultList = cont.persistence().createTransaction().execute((em) -> { - return em.createQuery("select u.group, u.login from sec$User u where u.name like :mask") - .setParameter("mask", "%ser") - .getResultList(); - }); - List list = (List) resultList; - Object[] row = list.get(0); - - assertEquals(UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"), ((Group) row[0]).getId()); - assertEquals("testLogin", row[1]); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.global.FetchMode; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.Constraint; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +import static com.haulmont.cuba.testsupport.TestSupport.reserialize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class EclipseLinkQueriesTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + private User user1; + private User user2; + private Group rootGroup; + private Group group; + + @Before + public void setUp() throws Exception { + cont.persistence().createTransaction().execute(em -> { + rootGroup = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); + + user1 = cont.metadata().create(User.class); + user1.setName("testUser"); + user1.setLogin("testLogin"); + user1.setGroup(rootGroup); + em.persist(user1); + + group = cont.metadata().create(Group.class); + group.setParent(rootGroup); + group.setName("testGroup" + group.getId()); + em.persist(group); + + user2 = cont.metadata().create(User.class); + user2.setName("testUser2"); + user2.setLogin("testLogin2"); + user2.setGroup(group); + user2.setGroup(rootGroup); + em.persist(user2); + + return null; + }); + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", group.getId()); + cont.deleteRecord(user1, user2, group); + } + + // cross join, view has ToMany reference + @Test + public void testCrossJoinWithToManyView() throws Exception { + List result; + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.entityManager(); + View view = new View(Group.class).addProperty("constraints"); + TypedQuery query = em.createQuery("select g from sec$Group g, sec$User u where u.group = g", Group.class); + query.setView(view); + result = query.getResultList(); + tx.commit(); + } + for (Group group : result) { + group = reserialize(group); + group.getConstraints().size(); + } + } + + // cross join, view with the reference to the parent entity + @Test + public void testCrossJoinViewParentReference() throws Exception { + List result; + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.entityManager(); + View view = new View(Group.class).addProperty("parent"); + TypedQuery query = em.createQuery("select g from sec$Group g, sec$User u where u.group = g", Group.class); + query.setView(view); + result = query.getResultList(); + tx.commit(); + } + for (Group g : result) { + g = reserialize(g); + if (g.equals(rootGroup)) + assertNull(g.getParent()); + else if (g.equals(group)) + assertEquals(rootGroup, g.getParent()); + } + } + + // join on, view contains ToMany attribute + @Test + public void testJoinOnWithToManyView() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.entityManager(); + View view = new View(Group.class).addProperty("constraints"); + TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); + query.setView(view); + List result = query.getResultList(); + tx.commit(); + } + } + + // join on, view contains parent attribute + @Test + public void testJoinOnWithParentReference() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.entityManager(); + View view = new View(Group.class).addProperty("parent"); + TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); + query.setView(view); + List result = query.getResultList(); + tx.commit(); + } + } + + // join on, view contains ToMany attribute, fetch = JOIN + @Test + public void testJoinOnWithToManyView2() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.entityManager(); + View view = new View(Group.class).addProperty("constraints", new View(Constraint.class, View.LOCAL), FetchMode.JOIN); + TypedQuery query = em.createQuery("select g from sec$Group g join sys$QueryResult qr on qr.entityId = g.id where qr.queryKey = 1", Group.class); + query.setView(view); + List result = query.getResultList(); + tx.commit(); + } + } + + @Test + public void testSeveralEntriesInSelectClause() { + Object resultList = cont.persistence().createTransaction().execute((em) -> { + return em.createQuery("select u.group, u.login from sec$User u where u.name like :mask") + .setParameter("mask", "%ser") + .getResultList(); + }); + List list = (List) resultList; + Object[] row = list.get(0); + + assertEquals(UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"), ((Group) row[0]).getId()); + assertEquals("testLogin", row[1]); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/EntityListenerTest.java b/modules/core/test/com/haulmont/cuba/core/EntityListenerTest.java index 61c82ca33b..5a966ee999 100644 --- a/modules/core/test/com/haulmont/cuba/core/EntityListenerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/EntityListenerTest.java @@ -1,307 +1,307 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.listener.*; -import com.haulmont.cuba.core.sys.listener.EntityListenerManager; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestSupport; -import org.apache.commons.collections4.CollectionUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Date; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class EntityListenerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private Metadata metadata; - private Persistence persistence; - - private TestListenerBean listenerBean; - private TestDetachAttachListener detachAttachListener; - - private EntityListenerManager entityListenerManager; - - @Before - public void setUp() throws Exception { - persistence = cont.persistence(); - metadata = cont.metadata(); - - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - runner.update("delete from SYS_SERVER"); - - listenerBean = AppBeans.get("cuba_TestListenerBean"); - listenerBean.events.clear(); - - detachAttachListener = AppBeans.get("cuba_TestDetachAttachListener"); - detachAttachListener.events.clear(); - - TestListener.events.clear(); - TestUserEntityListener.events.clear(); - - entityListenerManager = AppBeans.get(EntityListenerManager.class); - entityListenerManager.addListener(User.class, TestUserEntityListener.class); - entityListenerManager.addListener(Server.class, TestListener.class); - entityListenerManager.addListener(Server.class, "cuba_TestListenerBean"); - entityListenerManager.addListener(Server.class, "cuba_TestDetachAttachListener"); - entityListenerManager.addListener(Server.class, "cuba_TestListenerUsingEntityManager"); - } - - @After - public void tearDown() throws Exception { - entityListenerManager.removeListener(Server.class, "cuba_TestListenerUsingEntityManager"); - entityListenerManager.removeListener(Server.class, "cuba_TestDetachAttachListener"); - entityListenerManager.removeListener(Server.class, "cuba_TestListenerBean"); - entityListenerManager.removeListener(Server.class, TestListener.class); - entityListenerManager.removeListener(User.class, TestUserEntityListener.class); - } - - @Test - public void test() { - UUID id, id1; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - Server server1 = new Server(); - id1 = server1.getId(); - server1.setName("otherhost"); - server1.setRunning(true); - em.persist(server1); - - tx.commitRetaining(); - - assertEquals(2, TestListener.events.size()); - assertTrue(CollectionUtils.isEqualCollection( - Arrays.asList("onAfterInsert: " + id, "onAfterInsert: " + id1), - TestListener.events - )); - TestListener.events.clear(); - - assertEquals(2, listenerBean.events.size()); - assertTrue(CollectionUtils.isEqualCollection( - Arrays.asList("onAfterInsert: " + id, "onAfterInsert: " + id1), - listenerBean.events - )); - listenerBean.events.clear(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id); - server.setName(server.getName() + " - " + new Date()); - - tx.commitRetaining(); - - assertEquals(1, TestListener.events.size()); - assertEquals("onAfterUpdate: " + id, TestListener.events.get(0)); - TestListener.events.clear(); - - assertEquals(1, listenerBean.events.size()); - assertEquals("onAfterUpdate: " + id, listenerBean.events.get(0)); - listenerBean.events.clear(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id1); - em.remove(server); - - tx.commit(); - - assertEquals(1, TestListener.events.size()); - assertEquals("onAfterDelete: " + id1, TestListener.events.get(0)); - - assertEquals(1, listenerBean.events.size()); - assertEquals("onAfterDelete: " + id1, listenerBean.events.get(0)); - - } finally { - tx.end(); - } - } - - @Test - public void testDetachAttch() throws Exception { - UUID id; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Server server = new Server(); - id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - tx.commitRetaining(); - - assertEquals(1, detachAttachListener.events.size()); - assertEquals("onBeforeDetach: " + id, detachAttachListener.events.get(0)); - detachAttachListener.events.clear(); - - server.setName("somehost"); - em = cont.persistence().getEntityManager(); - em.merge(server); - - assertEquals(1, detachAttachListener.events.size()); - assertEquals("onBeforeAttach: " + id, detachAttachListener.events.get(0)); - detachAttachListener.events.clear(); - - tx.commit(); - - assertEquals(1, detachAttachListener.events.size()); - assertEquals("onBeforeDetach: " + id, detachAttachListener.events.get(0)); - detachAttachListener.events.clear(); - } finally { - tx.end(); - } - } - - @Test - public void testEntityManager() throws Exception { - Server server; - UUID serverId; - Transaction tx = cont.persistence().createTransaction(); - try { - // create - - server = new Server(); - server.setName("server1"); - serverId = server.getId(); - cont.persistence().getEntityManager().persist(server); - - tx.commitRetaining(); - - assertNotNull(server.getData()); - UUID relatedId = UUID.fromString(server.getData()); - FileDescriptor related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); - assertNotNull(related); - assertEquals("Related", related.getName()); - - tx.commitRetaining(); - - // update - - server = cont.persistence().getEntityManager().find(Server.class, serverId); - assertNotNull(server); - server.setName("server1 updated"); - - tx.commitRetaining(); - - related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); - assertNotNull(related); - assertEquals("Related updated", related.getName()); - - tx.commitRetaining(); - - // remove - - server = cont.persistence().getEntityManager().find(Server.class, serverId); - assertNotNull(server); - cont.persistence().getEntityManager().remove(server); - - tx.commitRetaining(); - - related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); - assertNull(related); - - tx.commit(); - } finally { - tx.end(); - } - - } - - @Test - public void testSequenceForSoftDeletedEntity() throws Exception { - User user; - try (Transaction tx = persistence.createTransaction()) { - user = metadata.create(User.class); - user.setGroup(persistence.getEntityManager().find(Group.class, TestSupport.COMPANY_GROUP_ID)); - user.setLogin("user-" + user.getId()); - persistence.getEntityManager().persist(user); - tx.commit(); - } - assertEquals(2, TestUserEntityListener.events.size()); - assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeInsert")); - assertTrue(TestUserEntityListener.events.get(1).contains("onAfterInsert")); - TestUserEntityListener.events.clear(); - - try (Transaction tx = persistence.createTransaction()) { - User u = persistence.getEntityManager().find(User.class, user.getId()); - assertNotNull(u); - u.setName(u.getLogin()); - tx.commit(); - } - assertEquals(2, TestUserEntityListener.events.size()); - assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeUpdate")); - assertTrue(TestUserEntityListener.events.get(1).contains("onAfterUpdate")); - TestUserEntityListener.events.clear(); - - try (Transaction tx = persistence.createTransaction()) { - User u = persistence.getEntityManager().find(User.class, user.getId()); - persistence.getEntityManager().remove(u); - tx.commit(); - } - assertEquals(2, TestUserEntityListener.events.size()); - assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeDelete")); - assertTrue(TestUserEntityListener.events.get(1).contains("onAfterDelete")); - } - - @Test - public void testExceptionInListener() throws Exception { - Server server; - try (Transaction tx = persistence.createTransaction()) { - server = metadata.create(Server.class); - server.setName("localhost"); - persistence.getEntityManager().persist(server); - tx.commit(); - } - entityListenerManager.addListener(Server.class, TestListenerThrowing.class); - try { - try (Transaction tx = persistence.createTransaction()) { - Server s = persistence.getEntityManager().find(Server.class, server.getId()); - s.setName("changed"); - tx.commit(); - fail(); - } catch (Exception e) { - assertTrue(e instanceof IllegalStateException); - assertEquals("test exception", e.getMessage()); - } - } finally { - entityListenerManager.removeListener(Server.class, TestListenerThrowing.class); - cont.deleteRecord(server); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.listener.*; +import com.haulmont.cuba.core.sys.listener.EntityListenerManager; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestSupport; +import org.apache.commons.collections4.CollectionUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class EntityListenerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private Metadata metadata; + private Persistence persistence; + + private TestListenerBean listenerBean; + private TestDetachAttachListener detachAttachListener; + + private EntityListenerManager entityListenerManager; + + @Before + public void setUp() throws Exception { + persistence = cont.persistence(); + metadata = cont.metadata(); + + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + runner.update("delete from SYS_SERVER"); + + listenerBean = AppBeans.get("cuba_TestListenerBean"); + listenerBean.events.clear(); + + detachAttachListener = AppBeans.get("cuba_TestDetachAttachListener"); + detachAttachListener.events.clear(); + + TestListener.events.clear(); + TestUserEntityListener.events.clear(); + + entityListenerManager = AppBeans.get(EntityListenerManager.class); + entityListenerManager.addListener(User.class, TestUserEntityListener.class); + entityListenerManager.addListener(Server.class, TestListener.class); + entityListenerManager.addListener(Server.class, "cuba_TestListenerBean"); + entityListenerManager.addListener(Server.class, "cuba_TestDetachAttachListener"); + entityListenerManager.addListener(Server.class, "cuba_TestListenerUsingEntityManager"); + } + + @After + public void tearDown() throws Exception { + entityListenerManager.removeListener(Server.class, "cuba_TestListenerUsingEntityManager"); + entityListenerManager.removeListener(Server.class, "cuba_TestDetachAttachListener"); + entityListenerManager.removeListener(Server.class, "cuba_TestListenerBean"); + entityListenerManager.removeListener(Server.class, TestListener.class); + entityListenerManager.removeListener(User.class, TestUserEntityListener.class); + } + + @Test + public void test() { + UUID id, id1; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + Server server1 = new Server(); + id1 = server1.getId(); + server1.setName("otherhost"); + server1.setRunning(true); + em.persist(server1); + + tx.commitRetaining(); + + assertEquals(2, TestListener.events.size()); + assertTrue(CollectionUtils.isEqualCollection( + Arrays.asList("onAfterInsert: " + id, "onAfterInsert: " + id1), + TestListener.events + )); + TestListener.events.clear(); + + assertEquals(2, listenerBean.events.size()); + assertTrue(CollectionUtils.isEqualCollection( + Arrays.asList("onAfterInsert: " + id, "onAfterInsert: " + id1), + listenerBean.events + )); + listenerBean.events.clear(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id); + server.setName(server.getName() + " - " + new Date()); + + tx.commitRetaining(); + + assertEquals(1, TestListener.events.size()); + assertEquals("onAfterUpdate: " + id, TestListener.events.get(0)); + TestListener.events.clear(); + + assertEquals(1, listenerBean.events.size()); + assertEquals("onAfterUpdate: " + id, listenerBean.events.get(0)); + listenerBean.events.clear(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id1); + em.remove(server); + + tx.commit(); + + assertEquals(1, TestListener.events.size()); + assertEquals("onAfterDelete: " + id1, TestListener.events.get(0)); + + assertEquals(1, listenerBean.events.size()); + assertEquals("onAfterDelete: " + id1, listenerBean.events.get(0)); + + } finally { + tx.end(); + } + } + + @Test + public void testDetachAttch() throws Exception { + UUID id; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Server server = new Server(); + id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + tx.commitRetaining(); + + assertEquals(1, detachAttachListener.events.size()); + assertEquals("onBeforeDetach: " + id, detachAttachListener.events.get(0)); + detachAttachListener.events.clear(); + + server.setName("somehost"); + em = cont.persistence().getEntityManager(); + em.merge(server); + + assertEquals(1, detachAttachListener.events.size()); + assertEquals("onBeforeAttach: " + id, detachAttachListener.events.get(0)); + detachAttachListener.events.clear(); + + tx.commit(); + + assertEquals(1, detachAttachListener.events.size()); + assertEquals("onBeforeDetach: " + id, detachAttachListener.events.get(0)); + detachAttachListener.events.clear(); + } finally { + tx.end(); + } + } + + @Test + public void testEntityManager() throws Exception { + Server server; + UUID serverId; + Transaction tx = cont.persistence().createTransaction(); + try { + // create + + server = new Server(); + server.setName("server1"); + serverId = server.getId(); + cont.persistence().getEntityManager().persist(server); + + tx.commitRetaining(); + + assertNotNull(server.getData()); + UUID relatedId = UUID.fromString(server.getData()); + FileDescriptor related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); + assertNotNull(related); + assertEquals("Related", related.getName()); + + tx.commitRetaining(); + + // update + + server = cont.persistence().getEntityManager().find(Server.class, serverId); + assertNotNull(server); + server.setName("server1 updated"); + + tx.commitRetaining(); + + related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); + assertNotNull(related); + assertEquals("Related updated", related.getName()); + + tx.commitRetaining(); + + // remove + + server = cont.persistence().getEntityManager().find(Server.class, serverId); + assertNotNull(server); + cont.persistence().getEntityManager().remove(server); + + tx.commitRetaining(); + + related = cont.persistence().getEntityManager().find(FileDescriptor.class, relatedId); + assertNull(related); + + tx.commit(); + } finally { + tx.end(); + } + + } + + @Test + public void testSequenceForSoftDeletedEntity() throws Exception { + User user; + try (Transaction tx = persistence.createTransaction()) { + user = metadata.create(User.class); + user.setGroup(persistence.getEntityManager().find(Group.class, TestSupport.COMPANY_GROUP_ID)); + user.setLogin("user-" + user.getId()); + persistence.getEntityManager().persist(user); + tx.commit(); + } + assertEquals(2, TestUserEntityListener.events.size()); + assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeInsert")); + assertTrue(TestUserEntityListener.events.get(1).contains("onAfterInsert")); + TestUserEntityListener.events.clear(); + + try (Transaction tx = persistence.createTransaction()) { + User u = persistence.getEntityManager().find(User.class, user.getId()); + assertNotNull(u); + u.setName(u.getLogin()); + tx.commit(); + } + assertEquals(2, TestUserEntityListener.events.size()); + assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeUpdate")); + assertTrue(TestUserEntityListener.events.get(1).contains("onAfterUpdate")); + TestUserEntityListener.events.clear(); + + try (Transaction tx = persistence.createTransaction()) { + User u = persistence.getEntityManager().find(User.class, user.getId()); + persistence.getEntityManager().remove(u); + tx.commit(); + } + assertEquals(2, TestUserEntityListener.events.size()); + assertTrue(TestUserEntityListener.events.get(0).contains("onBeforeDelete")); + assertTrue(TestUserEntityListener.events.get(1).contains("onAfterDelete")); + } + + @Test + public void testExceptionInListener() throws Exception { + Server server; + try (Transaction tx = persistence.createTransaction()) { + server = metadata.create(Server.class); + server.setName("localhost"); + persistence.getEntityManager().persist(server); + tx.commit(); + } + entityListenerManager.addListener(Server.class, TestListenerThrowing.class); + try { + try (Transaction tx = persistence.createTransaction()) { + Server s = persistence.getEntityManager().find(Server.class, server.getId()); + s.setName("changed"); + tx.commit(); + fail(); + } catch (Exception e) { + assertTrue(e instanceof IllegalStateException); + assertEquals("test exception", e.getMessage()); + } + } finally { + entityListenerManager.removeListener(Server.class, TestListenerThrowing.class); + cont.deleteRecord(server); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/FolderTest.java b/modules/core/test/com/haulmont/cuba/core/FolderTest.java index d711b5c9c3..92b3b79cb1 100644 --- a/modules/core/test/com/haulmont/cuba/core/FolderTest.java +++ b/modules/core/test/com/haulmont/cuba/core/FolderTest.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.List; - -public class FolderTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void test() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Query q = em.createQuery("select f from sys$Folder f"); - List list = q.getResultList(); - - tx.commit(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.List; + +public class FolderTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void test() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Query q = em.createQuery("select f from sys$Folder f"); + List list = q.getResultList(); + + tx.commit(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/MessagesTest.java b/modules/core/test/com/haulmont/cuba/core/MessagesTest.java index 927ffd4db0..b0d4535b16 100644 --- a/modules/core/test/com/haulmont/cuba/core/MessagesTest.java +++ b/modules/core/test/com/haulmont/cuba/core/MessagesTest.java @@ -1,294 +1,294 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.mp_test.MpTestObj; -import com.haulmont.cuba.core.mp_test.nested.MpTestNestedEnum; -import com.haulmont.cuba.core.mp_test.nested.MpTestNestedObj; -import com.haulmont.cuba.testsupport.TestAppender; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Map; - -import static org.junit.Assert.*; - -public class MessagesTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private final TestAppender appender; - - public MessagesTest() { - appender = new TestAppender(); - appender.start(); - - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - Logger logger = context.getLogger("com.haulmont.cuba.core.sys.AbstractMessages"); - logger.addAppender(appender); - logger.setLevel(Level.TRACE); - } - - @Test - public void test() { - Messages messages = AppBeans.get(Messages.class); - - String msg = messages.getMessage(MpTestNestedObj.class, "key0"); - assertEquals("Message0", msg); - - msg = messages.getMessage(MpTestObj.class, "key1"); - assertEquals("Message1", msg); - - msg = messages.getMessage(MpTestNestedObj.class, "key2"); - assertEquals("Message2", msg); - - // test cache - msg = messages.getMessage(MpTestNestedObj.class, "key0"); - assertEquals("Message0", msg); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested", "key1"); - assertEquals("Message1", msg); - - msg = messages.getMessage("test", "key1"); - assertEquals("key1", msg); - - msg = messages.getMessage(MpTestNestedEnum.ONE); - assertEquals("One", msg); - - msg = messages.getMessage(MpTestNestedObj.InternalEnum.FIRST); - assertEquals("First", msg); - - } - - @Test - public void testInclude() { - Messages messages = AppBeans.get(Messages.class); - - String msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "includedMsg"); - assertEquals("Included Message", msg); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "includedMsgToOverride"); - assertEquals("Overridden Included Message", msg); - } - - @Test - public void testMultiInclude() { - Messages messages = AppBeans.get(Messages.class); - - String msg1 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "oneKey"); - assertEquals(msg1, "OK"); - - String msg2 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "twoKey"); - assertEquals(msg2, "OK"); - - String msg3 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "threeKey"); - assertEquals(msg3, "overridden"); - } - - @Test - public void testCachingDefaultLoc() { - Messages messages = prepareCachingTest(); - - appender.getMessages().clear(); - - String msg = messages.getMessage(MpTestNestedObj.class, "key0"); - assertEquals("Message0", msg); - - assertEquals(4, - Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { - @Override - public boolean apply(@Nullable String input) { - return input != null && input.contains("searchFiles:"); - } - })) - ); - assertEquals(4, - Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { - @Override - public boolean apply(@Nullable String input) { - return input != null && input.contains("searchClasspath:"); - } - })) - ); - - appender.getMessages().clear(); - - msg = messages.getMessage(MpTestNestedObj.class, "key0"); - assertEquals("Message0", msg); - - assertEquals(0, - getSearchMessagesCount() - ); - } - - @Test - public void testCachingFrenchLoc() { - Messages messages = prepareCachingTest(); - - appender.getMessages().clear(); - - String msg = messages.getMessage(MpTestNestedObj.class, "key0", Locale.forLanguageTag("fr")); - assertEquals("Message0 in French", msg); - assertEquals(6, getSearchMessagesCount()); - - appender.getMessages().clear(); - - msg = messages.getMessage(MpTestNestedObj.class, "key0", Locale.forLanguageTag("fr")); - assertEquals("Message0 in French", msg); - assertEquals(0, getSearchMessagesCount()); - } - - private Messages prepareCachingTest() { - Messages messages = AppBeans.get(Messages.class); - messages.clearCache(); - return messages; - } - - @Test - public void testCachingDefaultLocSeveralPacks() { - Messages messages = prepareCachingTest(); - - appender.getMessages().clear(); - - String msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0"); - assertEquals("Message0", msg); - assertEquals(14, getSearchMessagesCount()); - - appender.getMessages().clear(); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0"); - assertEquals("Message0", msg); - assertEquals(0, getSearchMessagesCount()); - } - - @Test - public void testCachingFrenchLocSeveralPacks() { - Messages messages = prepareCachingTest(); - - appender.getMessages().clear(); - - String msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0", - Locale.forLanguageTag("fr")); - assertEquals("Message0 in French", msg); - assertEquals(16, getSearchMessagesCount()); - - appender.getMessages().clear(); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0", - Locale.forLanguageTag("fr")); - assertEquals("Message0 in French", msg); - assertEquals(0, getSearchMessagesCount()); - } - - @Test - public void testFind() throws Exception { - Messages messages = AppBeans.get(Messages.class); - UserSessionSource uss = AppBeans.get(UserSessionSource.class); - - String msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "key0", uss.getLocale()); - assertEquals("Message0", msg); - - msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", uss.getLocale()); - assertNull(msg); - - msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "key0", null); - assertEquals("Message0", msg); - - msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", null); - assertNull(msg); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", uss.getLocale()); - assertEquals("non-existing-message", msg); - } - - @Test - public void testMainMessagePack() throws Exception { - Messages messages = AppBeans.get(Messages.class); - - String msg; - - msg = messages.getMainMessage("trueString", Locale.forLanguageTag("en")); - assertEquals("True", msg); - - msg = messages.getMessage("com.haulmont.cuba.something", "trueString", Locale.forLanguageTag("en")); - assertEquals("True", msg); - - appender.getMessages().clear(); - msg = messages.getMessage("com.haulmont.cuba.something", "trueString", Locale.forLanguageTag("en")); - assertEquals("True", msg); - assertEquals(0, getSearchMessagesCount()); - } - - /** - * Test hierarchy of country/language/default message packs. - *

- * messages.properties:
- * commonMsg=Common Message
- * languageMsg=Language Message
- * countryMsg=Country Message
- *

- * messages_fr.properties:
- * languageMsg=Language Message fr
- * countryMsg=Country Message fr
- *

- * messages_fr_CA.properties:
- * countryMsg=Country Message fr CA
- */ - @Test - public void testLanguageAndCountry() throws Exception { - Messages messages = AppBeans.get(Messages.class); - - Map availableLocales = AppBeans.get(Configuration.class).getConfig(GlobalConfig.class).getAvailableLocales(); - assertTrue(availableLocales.containsValue(Locale.forLanguageTag("fr"))); - assertTrue(availableLocales.containsValue(Locale.forLanguageTag("fr-CA"))); - - boolean localeLanguageOnly = messages.getTools().useLocaleLanguageOnly(); - assertFalse(localeLanguageOnly); - - String msg; - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "commonMsg", Locale.forLanguageTag("fr-CA")); - assertEquals("Common Message", msg); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "languageMsg", Locale.forLanguageTag("fr-CA")); - assertEquals("Language Message fr", msg); - - msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "countryMsg", Locale.forLanguageTag("fr-CA")); - assertEquals("Country Message fr CA", msg); - } - - private int getSearchMessagesCount() { - return Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { - @Override - public boolean apply(@Nullable String input) { - return input != null && (input.contains("searchFiles:") || input.contains("searchClasspath:")); - } - })); - } - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.mp_test.MpTestObj; +import com.haulmont.cuba.core.mp_test.nested.MpTestNestedEnum; +import com.haulmont.cuba.core.mp_test.nested.MpTestNestedObj; +import com.haulmont.cuba.testsupport.TestAppender; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.Map; + +import static org.junit.Assert.*; + +public class MessagesTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private final TestAppender appender; + + public MessagesTest() { + appender = new TestAppender(); + appender.start(); + + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + Logger logger = context.getLogger("com.haulmont.cuba.core.sys.AbstractMessages"); + logger.addAppender(appender); + logger.setLevel(Level.TRACE); + } + + @Test + public void test() { + Messages messages = AppBeans.get(Messages.class); + + String msg = messages.getMessage(MpTestNestedObj.class, "key0"); + assertEquals("Message0", msg); + + msg = messages.getMessage(MpTestObj.class, "key1"); + assertEquals("Message1", msg); + + msg = messages.getMessage(MpTestNestedObj.class, "key2"); + assertEquals("Message2", msg); + + // test cache + msg = messages.getMessage(MpTestNestedObj.class, "key0"); + assertEquals("Message0", msg); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested", "key1"); + assertEquals("Message1", msg); + + msg = messages.getMessage("test", "key1"); + assertEquals("key1", msg); + + msg = messages.getMessage(MpTestNestedEnum.ONE); + assertEquals("One", msg); + + msg = messages.getMessage(MpTestNestedObj.InternalEnum.FIRST); + assertEquals("First", msg); + + } + + @Test + public void testInclude() { + Messages messages = AppBeans.get(Messages.class); + + String msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "includedMsg"); + assertEquals("Included Message", msg); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "includedMsgToOverride"); + assertEquals("Overridden Included Message", msg); + } + + @Test + public void testMultiInclude() { + Messages messages = AppBeans.get(Messages.class); + + String msg1 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "oneKey"); + assertEquals(msg1, "OK"); + + String msg2 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "twoKey"); + assertEquals(msg2, "OK"); + + String msg3 = messages.getMessage("com.haulmont.cuba.core.mp_test.includes", "threeKey"); + assertEquals(msg3, "overridden"); + } + + @Test + public void testCachingDefaultLoc() { + Messages messages = prepareCachingTest(); + + appender.getMessages().clear(); + + String msg = messages.getMessage(MpTestNestedObj.class, "key0"); + assertEquals("Message0", msg); + + assertEquals(4, + Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { + @Override + public boolean apply(@Nullable String input) { + return input != null && input.contains("searchFiles:"); + } + })) + ); + assertEquals(4, + Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { + @Override + public boolean apply(@Nullable String input) { + return input != null && input.contains("searchClasspath:"); + } + })) + ); + + appender.getMessages().clear(); + + msg = messages.getMessage(MpTestNestedObj.class, "key0"); + assertEquals("Message0", msg); + + assertEquals(0, + getSearchMessagesCount() + ); + } + + @Test + public void testCachingFrenchLoc() { + Messages messages = prepareCachingTest(); + + appender.getMessages().clear(); + + String msg = messages.getMessage(MpTestNestedObj.class, "key0", Locale.forLanguageTag("fr")); + assertEquals("Message0 in French", msg); + assertEquals(6, getSearchMessagesCount()); + + appender.getMessages().clear(); + + msg = messages.getMessage(MpTestNestedObj.class, "key0", Locale.forLanguageTag("fr")); + assertEquals("Message0 in French", msg); + assertEquals(0, getSearchMessagesCount()); + } + + private Messages prepareCachingTest() { + Messages messages = AppBeans.get(Messages.class); + messages.clearCache(); + return messages; + } + + @Test + public void testCachingDefaultLocSeveralPacks() { + Messages messages = prepareCachingTest(); + + appender.getMessages().clear(); + + String msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0"); + assertEquals("Message0", msg); + assertEquals(14, getSearchMessagesCount()); + + appender.getMessages().clear(); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0"); + assertEquals("Message0", msg); + assertEquals(0, getSearchMessagesCount()); + } + + @Test + public void testCachingFrenchLocSeveralPacks() { + Messages messages = prepareCachingTest(); + + appender.getMessages().clear(); + + String msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0", + Locale.forLanguageTag("fr")); + assertEquals("Message0 in French", msg); + assertEquals(16, getSearchMessagesCount()); + + appender.getMessages().clear(); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested com.haulmont.cuba.core.mp_test", "key0", + Locale.forLanguageTag("fr")); + assertEquals("Message0 in French", msg); + assertEquals(0, getSearchMessagesCount()); + } + + @Test + public void testFind() throws Exception { + Messages messages = AppBeans.get(Messages.class); + UserSessionSource uss = AppBeans.get(UserSessionSource.class); + + String msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "key0", uss.getLocale()); + assertEquals("Message0", msg); + + msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", uss.getLocale()); + assertNull(msg); + + msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "key0", null); + assertEquals("Message0", msg); + + msg = messages.findMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", null); + assertNull(msg); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test.nested", "non-existing-message", uss.getLocale()); + assertEquals("non-existing-message", msg); + } + + @Test + public void testMainMessagePack() throws Exception { + Messages messages = AppBeans.get(Messages.class); + + String msg; + + msg = messages.getMainMessage("trueString", Locale.forLanguageTag("en")); + assertEquals("True", msg); + + msg = messages.getMessage("com.haulmont.cuba.something", "trueString", Locale.forLanguageTag("en")); + assertEquals("True", msg); + + appender.getMessages().clear(); + msg = messages.getMessage("com.haulmont.cuba.something", "trueString", Locale.forLanguageTag("en")); + assertEquals("True", msg); + assertEquals(0, getSearchMessagesCount()); + } + + /** + * Test hierarchy of country/language/default message packs. + *

+ * messages.properties:
+ * commonMsg=Common Message
+ * languageMsg=Language Message
+ * countryMsg=Country Message
+ *

+ * messages_fr.properties:
+ * languageMsg=Language Message fr
+ * countryMsg=Country Message fr
+ *

+ * messages_fr_CA.properties:
+ * countryMsg=Country Message fr CA
+ */ + @Test + public void testLanguageAndCountry() throws Exception { + Messages messages = AppBeans.get(Messages.class); + + Map availableLocales = AppBeans.get(Configuration.class).getConfig(GlobalConfig.class).getAvailableLocales(); + assertTrue(availableLocales.containsValue(Locale.forLanguageTag("fr"))); + assertTrue(availableLocales.containsValue(Locale.forLanguageTag("fr-CA"))); + + boolean localeLanguageOnly = messages.getTools().useLocaleLanguageOnly(); + assertFalse(localeLanguageOnly); + + String msg; + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "commonMsg", Locale.forLanguageTag("fr-CA")); + assertEquals("Common Message", msg); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "languageMsg", Locale.forLanguageTag("fr-CA")); + assertEquals("Language Message fr", msg); + + msg = messages.getMessage("com.haulmont.cuba.core.mp_test", "countryMsg", Locale.forLanguageTag("fr-CA")); + assertEquals("Country Message fr CA", msg); + } + + private int getSearchMessagesCount() { + return Iterables.size(Iterables.filter(appender.getMessages(), new Predicate() { + @Override + public boolean apply(@Nullable String input) { + return input != null && (input.contains("searchFiles:") || input.contains("searchClasspath:")); + } + })); + } + +} diff --git a/modules/core/test/com/haulmont/cuba/core/MetadataTest.java b/modules/core/test/com/haulmont/cuba/core/MetadataTest.java index 9764d419fd..2890ad40b3 100644 --- a/modules/core/test/com/haulmont/cuba/core/MetadataTest.java +++ b/modules/core/test/com/haulmont/cuba/core/MetadataTest.java @@ -1,125 +1,125 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaModel; -import com.haulmont.chile.core.model.Session; -import com.haulmont.chile.core.model.utils.PrintUtils; -import com.haulmont.cuba.core.entity.AbstractNotPersistentEntity; -import com.haulmont.cuba.core.entity.Folder; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.LockInfo; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.testmodel.TestNotPersistentEntity; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.Collection; - -import static org.junit.Assert.*; - -public class MetadataTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private Metadata metadata; - - @Before - public void setUp() throws Exception { - metadata = cont.metadata(); - } - - @Test - public void test() { - Session session = AppBeans.get(Metadata.class).getSession(); - assertNotNull(session); - - Collection models = session.getModels(); - for (MetaModel model : models) { - System.out.println("Model: " + model.getName()); - System.out.println(PrintUtils.printClassHierarchy(model)); - } - } - - @Test - public void testPersistentAndTransientEntities() throws Exception { - MetadataTools metadataTools = cont.metadata().getTools(); - - assertTrue(metadataTools.isPersistent(User.class)); - assertFalse(metadataTools.isTransient(User.class)); - - assertFalse(metadataTools.isPersistent(LockInfo.class)); - assertTrue(metadataTools.isTransient(LockInfo.class)); - - assertFalse(metadataTools.isPersistent(TestNotPersistentEntity.class)); - assertTrue(metadataTools.isNotPersistent(TestNotPersistentEntity.class)); - } - - @Test - public void testPersistentAndTransientProperties() throws Exception { - MetadataTools tools = cont.metadata().getTools(); - - // User - MetaClass metaClass = cont.metadata().getSession().getClassNN(User.class); - assertTrue(tools.isPersistent(metaClass.getPropertyNN("login"))); - assertTrue(tools.isPersistent(metaClass.getPropertyNN("group"))); - assertTrue(tools.isPersistent(metaClass.getPropertyNN("userRoles"))); - - // EntityLogItem - metaClass = cont.metadata().getSession().getClassNN(EntityLogItem.class); - assertTrue(tools.isPersistent(metaClass.getPropertyNN("user"))); - assertFalse(tools.isPersistent(metaClass.getPropertyNN("attributes"))); - assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("attributes"))); - - // Folder - metaClass = cont.metadata().getSession().getClassNN(Folder.class); - assertTrue(tools.isPersistent(metaClass.getPropertyNN("name"))); - assertTrue(tools.isNotPersistent(new Folder(), "itemStyle")); - - // UserSessionEntity - metaClass = cont.metadata().getSession().getClassNN(UserSessionEntity.class); - assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("login"))); - - // TestTransientEntity - metaClass = cont.metadata().getSession().getClassNN(TestNotPersistentEntity.class); - assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("name"))); - assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("info"))); - assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("embeddedRef"))); - assertFalse(tools.isEmbedded(metaClass.getPropertyNN("embeddedRef"))); - } - - @Test - public void testSystemLevel() throws Exception { - MetadataTools tools = metadata.getTools(); - - assertTrue(tools.isSystemLevel(metadata.getClassNN(UserRole.class))); - - assertTrue(tools.isSystemLevel(metadata.getClassNN(AbstractNotPersistentEntity.class))); - assertFalse(tools.isSystemLevel(metadata.getClassNN(TestNotPersistentEntity.class))); - - MetaClass metaClass = metadata.getClassNN(User.class); - assertTrue(tools.isSystemLevel(metaClass.getPropertyNN("password"))); - - assertTrue(tools.isSystemLevel(metadata.getClassNN(SearchFolder.class))); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaModel; +import com.haulmont.chile.core.model.Session; +import com.haulmont.chile.core.model.utils.PrintUtils; +import com.haulmont.cuba.core.entity.AbstractNotPersistentEntity; +import com.haulmont.cuba.core.entity.Folder; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.LockInfo; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.testmodel.TestNotPersistentEntity; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.Collection; + +import static org.junit.Assert.*; + +public class MetadataTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private Metadata metadata; + + @Before + public void setUp() throws Exception { + metadata = cont.metadata(); + } + + @Test + public void test() { + Session session = AppBeans.get(Metadata.class).getSession(); + assertNotNull(session); + + Collection models = session.getModels(); + for (MetaModel model : models) { + System.out.println("Model: " + model.getName()); + System.out.println(PrintUtils.printClassHierarchy(model)); + } + } + + @Test + public void testPersistentAndTransientEntities() throws Exception { + MetadataTools metadataTools = cont.metadata().getTools(); + + assertTrue(metadataTools.isPersistent(User.class)); + assertFalse(metadataTools.isTransient(User.class)); + + assertFalse(metadataTools.isPersistent(LockInfo.class)); + assertTrue(metadataTools.isTransient(LockInfo.class)); + + assertFalse(metadataTools.isPersistent(TestNotPersistentEntity.class)); + assertTrue(metadataTools.isNotPersistent(TestNotPersistentEntity.class)); + } + + @Test + public void testPersistentAndTransientProperties() throws Exception { + MetadataTools tools = cont.metadata().getTools(); + + // User + MetaClass metaClass = cont.metadata().getSession().getClassNN(User.class); + assertTrue(tools.isPersistent(metaClass.getPropertyNN("login"))); + assertTrue(tools.isPersistent(metaClass.getPropertyNN("group"))); + assertTrue(tools.isPersistent(metaClass.getPropertyNN("userRoles"))); + + // EntityLogItem + metaClass = cont.metadata().getSession().getClassNN(EntityLogItem.class); + assertTrue(tools.isPersistent(metaClass.getPropertyNN("user"))); + assertFalse(tools.isPersistent(metaClass.getPropertyNN("attributes"))); + assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("attributes"))); + + // Folder + metaClass = cont.metadata().getSession().getClassNN(Folder.class); + assertTrue(tools.isPersistent(metaClass.getPropertyNN("name"))); + assertTrue(tools.isNotPersistent(new Folder(), "itemStyle")); + + // UserSessionEntity + metaClass = cont.metadata().getSession().getClassNN(UserSessionEntity.class); + assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("login"))); + + // TestTransientEntity + metaClass = cont.metadata().getSession().getClassNN(TestNotPersistentEntity.class); + assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("name"))); + assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("info"))); + assertTrue(tools.isNotPersistent(metaClass.getPropertyNN("embeddedRef"))); + assertFalse(tools.isEmbedded(metaClass.getPropertyNN("embeddedRef"))); + } + + @Test + public void testSystemLevel() throws Exception { + MetadataTools tools = metadata.getTools(); + + assertTrue(tools.isSystemLevel(metadata.getClassNN(UserRole.class))); + + assertTrue(tools.isSystemLevel(metadata.getClassNN(AbstractNotPersistentEntity.class))); + assertFalse(tools.isSystemLevel(metadata.getClassNN(TestNotPersistentEntity.class))); + + MetaClass metaClass = metadata.getClassNN(User.class); + assertTrue(tools.isSystemLevel(metaClass.getPropertyNN("password"))); + + assertTrue(tools.isSystemLevel(metadata.getClassNN(SearchFolder.class))); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/NamePatternTest.java b/modules/core/test/com/haulmont/cuba/core/NamePatternTest.java index 238b0d9e3c..6b29a54146 100644 --- a/modules/core/test/com/haulmont/cuba/core/NamePatternTest.java +++ b/modules/core/test/com/haulmont/cuba/core/NamePatternTest.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class NamePatternTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void test() { - Server server = new Server(); - server.setName("orion"); - server.setRunning(false); - - String instanceName = ((Instance) server).getInstanceName(); - - assertEquals(InstanceUtils.getInstanceName((Instance) server), instanceName); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class NamePatternTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void test() { + Server server = new Server(); + server.setName("orion"); + server.setRunning(false); + + String instanceName = ((Instance) server).getInstanceName(); + + assertEquals(InstanceUtils.getInstanceName((Instance) server), instanceName); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/OrmBehaviorTest.java b/modules/core/test/com/haulmont/cuba/core/OrmBehaviorTest.java index 66a0f0476d..241acf9c61 100644 --- a/modules/core/test/com/haulmont/cuba/core/OrmBehaviorTest.java +++ b/modules/core/test/com/haulmont/cuba/core/OrmBehaviorTest.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.ClassRule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.UUID; - -import static com.haulmont.cuba.testsupport.TestSupport.reserialize; -import static org.junit.Assert.assertEquals; - -public class OrmBehaviorTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID userId, groupId; - - private Logger log = LoggerFactory.getLogger(OrmBehaviorTest.class); - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER", userId); - cont.deleteRecord("SEC_GROUP", groupId); - } - - /* - * Test that persist with un-managed attribute works (it didn't work in OpenJPA 2.2+ and worked in OpenJPA pre-2.2) - */ - @Test - public void testPersistWithUnManagedAttribute() throws Exception { - Group group = new Group(); - groupId = group.getId(); - group.setName("Old Name"); - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager().persist(group); - tx.commit(); - } finally { - tx.end(); - } - - // Let's imagine that this entity was loaded with MyBatis - Group g = new Group(); - g.setId(groupId); - g.setName("Old Name"); - - User user = new User(); - userId = user.getId(); - user.setLogin("typednativesqlquery"); - user.setGroup(g); - user.setName("Test"); - - tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager().persist(user); - tx.commitRetaining(); - - user = cont.persistence().getEntityManager().find(User.class, userId, - new View(User.class).addProperty("group")); - tx.commit(); - } finally { - tx.end(); - } - - user = reserialize(user); - assertEquals(groupId, user.getGroup().getId()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.UUID; + +import static com.haulmont.cuba.testsupport.TestSupport.reserialize; +import static org.junit.Assert.assertEquals; + +public class OrmBehaviorTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID userId, groupId; + + private Logger log = LoggerFactory.getLogger(OrmBehaviorTest.class); + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER", userId); + cont.deleteRecord("SEC_GROUP", groupId); + } + + /* + * Test that persist with un-managed attribute works (it didn't work in OpenJPA 2.2+ and worked in OpenJPA pre-2.2) + */ + @Test + public void testPersistWithUnManagedAttribute() throws Exception { + Group group = new Group(); + groupId = group.getId(); + group.setName("Old Name"); + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager().persist(group); + tx.commit(); + } finally { + tx.end(); + } + + // Let's imagine that this entity was loaded with MyBatis + Group g = new Group(); + g.setId(groupId); + g.setName("Old Name"); + + User user = new User(); + userId = user.getId(); + user.setLogin("typednativesqlquery"); + user.setGroup(g); + user.setName("Test"); + + tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager().persist(user); + tx.commitRetaining(); + + user = cont.persistence().getEntityManager().find(User.class, userId, + new View(User.class).addProperty("group")); + tx.commit(); + } finally { + tx.end(); + } + + user = reserialize(user); + assertEquals(groupId, user.getGroup().getId()); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/PersistenceAttributeLoadedCheckTest.java b/modules/core/test/com/haulmont/cuba/core/PersistenceAttributeLoadedCheckTest.java index 916b9f4b25..5f3c7ba346 100644 --- a/modules/core/test/com/haulmont/cuba/core/PersistenceAttributeLoadedCheckTest.java +++ b/modules/core/test/com/haulmont/cuba/core/PersistenceAttributeLoadedCheckTest.java @@ -1,142 +1,142 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.entity.ScheduledTask; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserRole; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestSupport; -import org.junit.*; - -import java.util.UUID; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class PersistenceAttributeLoadedCheckTest { - @ClassRule - public static final TestContainer cont = TestContainer.Common.INSTANCE; - - private DataManager dataManager; - private Persistence persistence; - private UUID taskId; - private UUID userId; - private UUID groupId = UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"); - private View taskView; - private View userView; - - @Before - public void setUp() throws Exception { - dataManager = AppBeans.get(DataManager.class); - persistence = AppBeans.get(Persistence.class); - - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - - ScheduledTask task = new ScheduledTask(); - task.setBeanName("BeanName"); - task.setMethodName("MethodName"); - taskId = task.getId(); - - User user = new User(); - userId = user.getId(); - user.setName("testUser"); - user.setLogin("login" + userId); - user.setPassword("000"); - user.setGroup(em.find(Group.class, groupId)); - em.persist(user); - - em.persist(task); - em.persist(user); - tx.commit(); - } - - taskView = new View(ScheduledTask.class, true) - .addProperty("beanName"); - - userView = new View(User.class, true) - .addProperty("login") - .addProperty("loginLowerCase") - .addProperty("name") - .addProperty("password") - .addProperty("group", new View(Group.class).addProperty("name")) - .addProperty("userRoles", new View(UserRole.class)); - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER", userId); - cont.deleteRecord("SYS_SCHEDULED_TASK", taskId); - } - - @Test - public void testIsLoadedLogic() throws Exception { - LoadContext userContext = LoadContext.create(User.class).setId(userId).setView(userView); - LoadContext taskContext = LoadContext.create(ScheduledTask.class).setId(taskId).setView(taskView); - User user = dataManager.load(userContext); - ScheduledTask task = dataManager.load(taskContext); - - assertNotNull(user); - assertNotNull(task); - - assertTrue(PersistenceHelper.isLoaded(user, "group"));//if attribute is in the view - it should be loaded - assertTrue(PersistenceHelper.isLoaded(user, "userRoles"));//if attribute is in the view - it should be loaded - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions"));//if attribute is not in the view - it should not be loaded - try { - PersistenceHelper.isLoaded(user, "notExistingAttribute"); - Assert.fail("Should throw an exception for not existing attribute"); - } catch (Exception ignored) { - } - - assertTrue(PersistenceHelper.isLoaded(task, "beanName"));//if attribute is in the view - it should be loaded - assertTrue(!PersistenceHelper.isLoaded(task, "methodName"));//if attribute is not in the view - it should not be loaded - assertTrue(PersistenceHelper.isLoaded(task, "methodParametersString"));//meta properties should be marked as loaded - - user = TestSupport.reserialize(user); - task = TestSupport.reserialize(task); - - assertTrue(PersistenceHelper.isLoaded(user, "group"));//if attribute is in the view - it should be loaded - assertTrue(PersistenceHelper.isLoaded(user, "userRoles"));//if attribute is in the view - it should be loaded - assertTrue(!PersistenceHelper.isLoaded(user, "substitutions"));//if attribute is not in the view - it should not be loaded - try { - PersistenceHelper.isLoaded(user, "notExistingAttribute"); - Assert.fail("Should throw an exception for not existing attribute"); - } catch (Exception ignored) { - } - - assertTrue(PersistenceHelper.isLoaded(task, "beanName"));//if attribute is in the view - it should be loaded - assertTrue(!PersistenceHelper.isLoaded(task, "methodName"));//if attribute is not in the view - it should not be loaded - assertTrue(PersistenceHelper.isLoaded(task, "methodParametersString"));//meta properties should be marked as loaded - } - - @Test - public void testManagedInstance() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - User user = cont.entityManager().find(User.class, userId); - - assertTrue(PersistenceHelper.isLoaded(user, "name")); - assertFalse(PersistenceHelper.isLoaded(user, "group")); - - tx.commit(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.entity.ScheduledTask; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserRole; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestSupport; +import org.junit.*; + +import java.util.UUID; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class PersistenceAttributeLoadedCheckTest { + @ClassRule + public static final TestContainer cont = TestContainer.Common.INSTANCE; + + private DataManager dataManager; + private Persistence persistence; + private UUID taskId; + private UUID userId; + private UUID groupId = UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"); + private View taskView; + private View userView; + + @Before + public void setUp() throws Exception { + dataManager = AppBeans.get(DataManager.class); + persistence = AppBeans.get(Persistence.class); + + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + + ScheduledTask task = new ScheduledTask(); + task.setBeanName("BeanName"); + task.setMethodName("MethodName"); + taskId = task.getId(); + + User user = new User(); + userId = user.getId(); + user.setName("testUser"); + user.setLogin("login" + userId); + user.setPassword("000"); + user.setGroup(em.find(Group.class, groupId)); + em.persist(user); + + em.persist(task); + em.persist(user); + tx.commit(); + } + + taskView = new View(ScheduledTask.class, true) + .addProperty("beanName"); + + userView = new View(User.class, true) + .addProperty("login") + .addProperty("loginLowerCase") + .addProperty("name") + .addProperty("password") + .addProperty("group", new View(Group.class).addProperty("name")) + .addProperty("userRoles", new View(UserRole.class)); + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER", userId); + cont.deleteRecord("SYS_SCHEDULED_TASK", taskId); + } + + @Test + public void testIsLoadedLogic() throws Exception { + LoadContext userContext = LoadContext.create(User.class).setId(userId).setView(userView); + LoadContext taskContext = LoadContext.create(ScheduledTask.class).setId(taskId).setView(taskView); + User user = dataManager.load(userContext); + ScheduledTask task = dataManager.load(taskContext); + + assertNotNull(user); + assertNotNull(task); + + assertTrue(PersistenceHelper.isLoaded(user, "group"));//if attribute is in the view - it should be loaded + assertTrue(PersistenceHelper.isLoaded(user, "userRoles"));//if attribute is in the view - it should be loaded + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions"));//if attribute is not in the view - it should not be loaded + try { + PersistenceHelper.isLoaded(user, "notExistingAttribute"); + Assert.fail("Should throw an exception for not existing attribute"); + } catch (Exception ignored) { + } + + assertTrue(PersistenceHelper.isLoaded(task, "beanName"));//if attribute is in the view - it should be loaded + assertTrue(!PersistenceHelper.isLoaded(task, "methodName"));//if attribute is not in the view - it should not be loaded + assertTrue(PersistenceHelper.isLoaded(task, "methodParametersString"));//meta properties should be marked as loaded + + user = TestSupport.reserialize(user); + task = TestSupport.reserialize(task); + + assertTrue(PersistenceHelper.isLoaded(user, "group"));//if attribute is in the view - it should be loaded + assertTrue(PersistenceHelper.isLoaded(user, "userRoles"));//if attribute is in the view - it should be loaded + assertTrue(!PersistenceHelper.isLoaded(user, "substitutions"));//if attribute is not in the view - it should not be loaded + try { + PersistenceHelper.isLoaded(user, "notExistingAttribute"); + Assert.fail("Should throw an exception for not existing attribute"); + } catch (Exception ignored) { + } + + assertTrue(PersistenceHelper.isLoaded(task, "beanName"));//if attribute is in the view - it should be loaded + assertTrue(!PersistenceHelper.isLoaded(task, "methodName"));//if attribute is not in the view - it should not be loaded + assertTrue(PersistenceHelper.isLoaded(task, "methodParametersString"));//meta properties should be marked as loaded + } + + @Test + public void testManagedInstance() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + User user = cont.entityManager().find(User.class, userId); + + assertTrue(PersistenceHelper.isLoaded(user, "name")); + assertFalse(PersistenceHelper.isLoaded(user, "group")); + + tx.commit(); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/PersistenceTest.java b/modules/core/test/com/haulmont/cuba/core/PersistenceTest.java index c6428b3406..3104743203 100644 --- a/modules/core/test/com/haulmont/cuba/core/PersistenceTest.java +++ b/modules/core/test/com/haulmont/cuba/core/PersistenceTest.java @@ -1,309 +1,309 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import javax.annotation.Nullable; -import java.util.Set; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class PersistenceTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID userId; - - @Before - public void setUp() throws Exception { - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - runner.update("delete from SYS_SERVER"); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = new User(); - userId = user.getId(); - user.setName("testUser"); - user.setLogin("testLogin"); - user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); - em.persist(user); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER", userId); - } - - private void raiseException() { - throw new RuntimeException("test_ex"); - } - - @Test - public void testLoadByCombinedView() throws Exception { - User user; - Transaction tx = cont.persistence().createTransaction(); - try { - // load by single view - - EntityManager em = cont.persistence().getEntityManager(); - - user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), - new View(User.class, false).addProperty("login").setLoadPartialEntities(true)); - - assertTrue(cont.persistence().getTools().isLoaded(user, "login")); - assertFalse(cont.persistence().getTools().isLoaded(user, "name")); - - tx.commitRetaining(); - - // load by combined view - - em = cont.persistence().getEntityManager(); - - user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), - new View(User.class, false).addProperty("login").setLoadPartialEntities(true), - new View(User.class, false).addProperty("name").setLoadPartialEntities(true) - ); - - assertTrue(cont.persistence().getTools().isLoaded(user, "login")); - assertTrue(cont.persistence().getTools().isLoaded(user, "name")); - - tx.commitRetaining(); - - // load by complex combined view - - em = cont.persistence().getEntityManager(); - - user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), - new View(User.class, false).addProperty("login").setLoadPartialEntities(true), - new View(User.class, false).addProperty("group", new View(Group.class).addProperty("name")).setLoadPartialEntities(true) - ); - - assertTrue(cont.persistence().getTools().isLoaded(user, "login")); - assertFalse(cont.persistence().getTools().isLoaded(user, "name")); - assertTrue(cont.persistence().getTools().isLoaded(user, "group")); - assertTrue(cont.persistence().getTools().isLoaded(user.getGroup(), "name")); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testMergeNotLoaded() throws Exception { - User user; - Group group; - - Transaction tx = cont.persistence().createTransaction(); - try { - User transientUser = new User(); - transientUser.setId(userId); - transientUser.setName("testUser1"); - - EntityManager em = cont.persistence().getEntityManager(); - em.merge(transientUser); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - user = em.find(User.class, userId); - assertNotNull(user); - group = user.getGroup(); - } finally { - tx.end(); - } - - assertEquals(userId, user.getId()); - assertEquals("testUser1", user.getName()); - assertEquals("testLogin", user.getLogin()); - assertNotNull(group); - } - - @Test - public void testDirtyFields() throws Exception { - PersistenceTools persistenceTools = cont.persistence().getTools(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - UUID id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - assertTrue(persistenceTools.isDirty(server, "name", "running")); - assertNull(persistenceTools.getOldValue(server, "data")); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id); - assertNotNull(server); - server.setData("testData"); - - assertTrue(persistenceTools.isDirty(server)); - - Set dirtyFields = persistenceTools.getDirtyFields(server); - assertTrue(dirtyFields.contains("data")); - assertTrue(persistenceTools.isDirty(server, "data")); - assertNull(persistenceTools.getOldValue(server, "data")); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id); - assertNotNull(server); - - server.setData("testData1"); - assertEquals("testData", persistenceTools.getOldValue(server, "data")); - - tx.commit(); - } finally { - tx.end(); - } - } - - /** - * OpenJPA silently ignores setting null in nullable=false attribute. - */ - @Test - public void testNonNullAttribute() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - User user = em.find(User.class, userId); - assertNotNull(user); - user.setLogin(null); - user.setName(null); - tx.commitRetaining(); - fail(); - -// Old OpenJPA behaviour -// em = cont.persistence().getEntityManager(); -// user = em.find(User.class, userId); -// assertNotNull(user); -// assertNotNull(user.getLogin()); // null was not saved -// assertNull(user.getName()); // null was saved - - tx.commit(); - } catch (Exception e) { - assertTrue(e.getMessage().contains("NOT NULL check constraint")); - } finally { - tx.end(); - } - - } - - @Test - public void testFind() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - User user = cont.entityManager().find(User.class, userId); - assertNotNull(user); - - tx.commit(); - } - } - - @Test - public void testRepeatingReloadNoView() throws Exception { - cont.persistence().runInTransaction((em) -> { - User u = loadUserByName(em, null); - - u.setLanguage("ru"); - - u = loadUserByName(em, null); - - assertEquals("ru", u.getLanguage()); - }); - - User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); - assertEquals("ru", changedUser.getLanguage()); - } - - @Test - public void testLostChangeOnReloadWithView1() throws Exception { - cont.persistence().runInTransaction((em) -> { - User u = loadUserByName(em, View.LOCAL); - - u.setLanguage("en"); - - u = loadUserByName(em, View.LOCAL); - - assertEquals("en", u.getLanguage()); - }); - } - - @Test - public void testLostChangeOnReloadWithView2() throws Exception { - cont.persistence().runInTransaction((em) -> { - User u = loadUserByName(em, View.LOCAL); - - u.setLanguage("fr"); - - u = loadUserByName(em, View.LOCAL); - }); - - User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); - assertEquals("fr", changedUser.getLanguage()); - } - - @Test - public void testLostChangesOnEmReload() throws Exception { - User user = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); - - cont.persistence().runInTransaction((em) -> { - User u = em.merge(user); - u.setEmail("abc@example.com"); - - u = em.reload(u, View.LOCAL); - }); - - User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); - assertEquals("abc@example.com", changedUser.getEmail()); - } - - private User loadUserByName(EntityManager em, @Nullable String viewName) { - TypedQuery q = em.createQuery("select u from sec$User u where u.name = :name", User.class) - .setParameter("name", "testUser"); - - if (viewName != null) { - q.setViewName(viewName); - } - return q.getFirstResult(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import javax.annotation.Nullable; +import java.util.Set; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class PersistenceTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID userId; + + @Before + public void setUp() throws Exception { + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + runner.update("delete from SYS_SERVER"); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = new User(); + userId = user.getId(); + user.setName("testUser"); + user.setLogin("testLogin"); + user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); + em.persist(user); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER", userId); + } + + private void raiseException() { + throw new RuntimeException("test_ex"); + } + + @Test + public void testLoadByCombinedView() throws Exception { + User user; + Transaction tx = cont.persistence().createTransaction(); + try { + // load by single view + + EntityManager em = cont.persistence().getEntityManager(); + + user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), + new View(User.class, false).addProperty("login").setLoadPartialEntities(true)); + + assertTrue(cont.persistence().getTools().isLoaded(user, "login")); + assertFalse(cont.persistence().getTools().isLoaded(user, "name")); + + tx.commitRetaining(); + + // load by combined view + + em = cont.persistence().getEntityManager(); + + user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), + new View(User.class, false).addProperty("login").setLoadPartialEntities(true), + new View(User.class, false).addProperty("name").setLoadPartialEntities(true) + ); + + assertTrue(cont.persistence().getTools().isLoaded(user, "login")); + assertTrue(cont.persistence().getTools().isLoaded(user, "name")); + + tx.commitRetaining(); + + // load by complex combined view + + em = cont.persistence().getEntityManager(); + + user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), + new View(User.class, false).addProperty("login").setLoadPartialEntities(true), + new View(User.class, false).addProperty("group", new View(Group.class).addProperty("name")).setLoadPartialEntities(true) + ); + + assertTrue(cont.persistence().getTools().isLoaded(user, "login")); + assertFalse(cont.persistence().getTools().isLoaded(user, "name")); + assertTrue(cont.persistence().getTools().isLoaded(user, "group")); + assertTrue(cont.persistence().getTools().isLoaded(user.getGroup(), "name")); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testMergeNotLoaded() throws Exception { + User user; + Group group; + + Transaction tx = cont.persistence().createTransaction(); + try { + User transientUser = new User(); + transientUser.setId(userId); + transientUser.setName("testUser1"); + + EntityManager em = cont.persistence().getEntityManager(); + em.merge(transientUser); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + user = em.find(User.class, userId); + assertNotNull(user); + group = user.getGroup(); + } finally { + tx.end(); + } + + assertEquals(userId, user.getId()); + assertEquals("testUser1", user.getName()); + assertEquals("testLogin", user.getLogin()); + assertNotNull(group); + } + + @Test + public void testDirtyFields() throws Exception { + PersistenceTools persistenceTools = cont.persistence().getTools(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + UUID id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + assertTrue(persistenceTools.isDirty(server, "name", "running")); + assertNull(persistenceTools.getOldValue(server, "data")); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id); + assertNotNull(server); + server.setData("testData"); + + assertTrue(persistenceTools.isDirty(server)); + + Set dirtyFields = persistenceTools.getDirtyFields(server); + assertTrue(dirtyFields.contains("data")); + assertTrue(persistenceTools.isDirty(server, "data")); + assertNull(persistenceTools.getOldValue(server, "data")); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id); + assertNotNull(server); + + server.setData("testData1"); + assertEquals("testData", persistenceTools.getOldValue(server, "data")); + + tx.commit(); + } finally { + tx.end(); + } + } + + /** + * OpenJPA silently ignores setting null in nullable=false attribute. + */ + @Test + public void testNonNullAttribute() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + User user = em.find(User.class, userId); + assertNotNull(user); + user.setLogin(null); + user.setName(null); + tx.commitRetaining(); + fail(); + +// Old OpenJPA behaviour +// em = cont.persistence().getEntityManager(); +// user = em.find(User.class, userId); +// assertNotNull(user); +// assertNotNull(user.getLogin()); // null was not saved +// assertNull(user.getName()); // null was saved + + tx.commit(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("NOT NULL check constraint")); + } finally { + tx.end(); + } + + } + + @Test + public void testFind() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + User user = cont.entityManager().find(User.class, userId); + assertNotNull(user); + + tx.commit(); + } + } + + @Test + public void testRepeatingReloadNoView() throws Exception { + cont.persistence().runInTransaction((em) -> { + User u = loadUserByName(em, null); + + u.setLanguage("ru"); + + u = loadUserByName(em, null); + + assertEquals("ru", u.getLanguage()); + }); + + User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); + assertEquals("ru", changedUser.getLanguage()); + } + + @Test + public void testLostChangeOnReloadWithView1() throws Exception { + cont.persistence().runInTransaction((em) -> { + User u = loadUserByName(em, View.LOCAL); + + u.setLanguage("en"); + + u = loadUserByName(em, View.LOCAL); + + assertEquals("en", u.getLanguage()); + }); + } + + @Test + public void testLostChangeOnReloadWithView2() throws Exception { + cont.persistence().runInTransaction((em) -> { + User u = loadUserByName(em, View.LOCAL); + + u.setLanguage("fr"); + + u = loadUserByName(em, View.LOCAL); + }); + + User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); + assertEquals("fr", changedUser.getLanguage()); + } + + @Test + public void testLostChangesOnEmReload() throws Exception { + User user = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); + + cont.persistence().runInTransaction((em) -> { + User u = em.merge(user); + u.setEmail("abc@example.com"); + + u = em.reload(u, View.LOCAL); + }); + + User changedUser = cont.persistence().callInTransaction((em) -> em.find(User.class, userId)); + assertEquals("abc@example.com", changedUser.getEmail()); + } + + private User loadUserByName(EntityManager em, @Nullable String viewName) { + TypedQuery q = em.createQuery("select u from sec$User u where u.name = :name", User.class) + .setParameter("name", "testUser"); + + if (viewName != null) { + q.setViewName(viewName); + } + return q.getFirstResult(); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/QueryTest.java b/modules/core/test/com/haulmont/cuba/core/QueryTest.java index 2af1aaad53..bb7607f806 100644 --- a/modules/core/test/com/haulmont/cuba/core/QueryTest.java +++ b/modules/core/test/com/haulmont/cuba/core/QueryTest.java @@ -1,593 +1,593 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.haulmont.cuba.core.sys.QueryImpl; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.Role; -import com.haulmont.cuba.security.entity.RoleType; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import javax.persistence.FlushModeType; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class QueryTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID userId; - private UUID user2Id; - private UUID groupId; - - @Before - public void setUp() throws Exception { - - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - - User user = new User(); - userId = user.getId(); - user.setName("testUser"); - user.setLogin("testLogin"); - user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); - em.persist(user); - - user = new User(); - user2Id = user.getId(); - user.setName("testUser2"); - user.setLogin("testLogin2"); - user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); - em.persist(user); - - Group group = new Group(); - groupId = group.getId(); - group.setName("testGroup"); - em.persist(group); - - tx.commit(); - } - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER", userId, user2Id); - cont.deleteRecord("SEC_GROUP", groupId); - } - - @Test - public void test() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); - - Query query = em.createQuery("select r from sec$UserRole r where r.user.id = :user"); - query.setParameter("user", user); - List list = query.getResultList(); - - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNullParam() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createQuery("select r from sec$UserRole r where r.deleteTs = :dts"); - query.setParameter("dts", null); - List list = query.getResultList(); - - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testUpdate() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, groupId); - - Query query = em.createQuery("update sec$User u set u.group = :group where u.id = :userId"); - query.setParameter("userId", userId); - query.setParameter("group", group, false); - query.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - -// This test doesn't pass for some unclarified reason. -// -// public void testFlushBeforeUpdate() { -// Transaction tx = cont.persistence().createTransaction(); -// try { -// EntityManager em = cont.persistence().getEntityManager(); -// -// Group group = em.find(Group.class, groupId); -// User user = em.find(User.class, userId); -// assertNotNull(user); -// user.setName("newName"); -// -// Query query = em.createQuery("update sec$User u set u.group = :group where u.id = :userId"); -// query.setParameter("userId", userId); -// query.setParameter("group", group, false); -// query.executeUpdate(); -// -// tx.commit(); -// } finally { -// tx.end(); -// } -// -// tx = cont.persistence().createTransaction(); -// try { -// EntityManager em = cont.persistence().getEntityManager(); -// User user = em.find(User.class, userId); -// assertNotNull(user); -// assertEquals(groupId, user.getGroup().getId()); -// assertEquals("newName", user.getName()); -// -// tx.commit(); -// } finally { -// tx.end(); -// } -// } - - @Test - public void testAssociatedResult() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createQuery("select u.group from sec$User u where u.id = :userId"); - query.setParameter("userId", userId); - List list = query.getResultList(); - - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testIgnoreChanges() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - TypedQuery query; - List list; - - query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); - query.setParameter(1, "testUser"); - list = query.getResultList(); - assertEquals(1, list.size()); - User user = list.get(0); - - user.setName("newName"); - - query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); - query.setParameter(1, "testUser"); - list = query.getResultList(); - assertEquals(1, list.size()); - User user1 = list.get(0); - - assertTrue(user1 == user); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testFlushModeAuto() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - - TypedQuery query; - List list; - - query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); - query.setParameter(1, "testUser"); - list = query.getResultList(); - assertEquals(1, list.size()); - User user = list.get(0); - - user.setName("newName"); - - query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); - query.setParameter(1, "newName"); - query.setFlushMode(FlushModeType.AUTO); - list = query.getResultList(); - assertEquals(1, list.size()); - User user1 = list.get(0); - - assertTrue(user1 == user); - - tx.commit(); - } - } - - @Test - public void testNativeQueryIgnoreChanges() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - TypedQuery query; - List list; - - query = em.createNativeQuery("select * from SEC_USER where NAME = ?1", User.class); - query.setParameter(1, "testUser"); - list = query.getResultList(); - assertEquals(1, list.size()); - User user = list.get(0); - - user.setName("newName"); - - query = em.createNativeQuery("select * from SEC_USER where NAME = ?1", User.class); - query.setParameter(1, "testUser"); - list = query.getResultList(); - assertEquals(1, list.size()); - User user1 = list.get(0); - - assertTrue(user1 == user); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNativeQuerySelect() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createNativeQuery("select ID, LOGIN from SEC_USER where NAME = ?1"); - query.setParameter(1, "testUser"); - List list = query.getResultList(); - assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof Object[]); - Object[] row = (Object[]) list.get(0); - assertEquals(userId.toString(), row[0]); - assertEquals("testLogin", row[1]); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNativeQueryFlushBeforeUpdate() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, groupId); - User user = em.find(User.class, userId); - assertNotNull(user); - user.setName("newName"); - - Query query = em.createNativeQuery("update SEC_USER set GROUP_ID = ?1 where ID = ?2"); - query.setParameter(1, group.getId().toString()); - query.setParameter(2, userId.toString()); - query.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - User user = em.find(User.class, userId); - assertNotNull(user); - assertEquals(groupId, user.getGroup().getId()); - assertEquals("newName", user.getName()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testCaseInsensitiveSearch() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - TypedQuery query = cont.persistence().getEntityManager().createQuery( - "select u from sec$User u where u.name like :name", User.class); - query.setParameter("name", "(?i)%user%"); - List list = query.getResultList(); - tx.commit(); - - Iterables.find(list, new Predicate() { - @Override - public boolean apply(User input) { - return input.getId().equals(userId); - } - }); - } finally { - tx.end(); - } - - } - - @Test - public void testListParameter() throws Exception { - try (Transaction tx = cont.persistence().createTransaction()) { - TypedQuery query = cont.persistence().getEntityManager().createQuery( - "select u from sec$User u where u.id in :ids order by u.createTs", User.class); - query.setParameter("ids", Arrays.asList(UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), userId, user2Id)); - List list = query.getResultList(); - assertEquals(3, list.size()); - - tx.commit(); - } - - // Implicit conversion - - User user1, user2, user3; - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - user1 = em.find(User.class, userId); - user2 = em.find(User.class, user2Id); - user3 = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); - - tx.commit(); - } - - try (Transaction tx = cont.persistence().createTransaction()) { - TypedQuery query = cont.persistence().getEntityManager().createQuery( - "select u from sec$User u where u.id in :ids order by u.createTs", User.class); - query.setParameter("ids", Arrays.asList(user1, user2, user3)); - List list = query.getResultList(); - assertEquals(3, list.size()); - - tx.commit(); - } - - // Positional parameters - - try (Transaction tx = cont.persistence().createTransaction()) { - TypedQuery query = cont.persistence().getEntityManager().createQuery( - "select u from sec$User u where u.id in ?1 order by u.createTs", User.class); - query.setParameter(1, Arrays.asList(user1.getId(), user2.getId(), user3.getId())); - List list = query.getResultList(); - assertEquals(3, list.size()); - - tx.commit(); - } - - // Positional parameters with implicit conversion - - try (Transaction tx = cont.persistence().createTransaction()) { - TypedQuery query = cont.persistence().getEntityManager().createQuery( - "select u from sec$User u where u.id in ?1 order by u.createTs", User.class); - query.setParameter(1, Arrays.asList(user1, user2, user3)); - List list = query.getResultList(); - assertEquals(3, list.size()); - - tx.commit(); - } - } - - @Test - public void testEmptyCollectionParameter() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createQuery("select u from sec$User u where u.id in :ids"); - query.setParameter("ids", Collections.emptyList()); - List list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id in (:ids)"); - query.setParameter("ids", Collections.emptyList()); - list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in :ids"); - query.setParameter("ids", Collections.emptyList()); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); - query.setParameter("ids", Collections.emptyList()); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNullCollectionParameter() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createQuery("select u from sec$User u where u.id in :ids"); - query.setParameter("ids", null); - List list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id in (:ids)"); - query.setParameter("ids", null); - list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in :ids"); - query.setParameter("ids", null); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); - query.setParameter("ids", null); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNotExistsCollectionParameter() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query query = em.createQuery("select u from sec$User u where u.id in :ids"); - List list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id in (:ids)"); - list = query.getResultList(); - assertTrue(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in :ids"); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - query = em.createQuery("select u from sec$User u where u.id not in (:ids1) or u.id not in (:ids2)"); - query.setParameter("ids1", null); - list = query.getResultList(); - assertFalse(list.isEmpty()); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testSingleBooleanResult() { - // works - Object[] activeAndName = cont.persistence().callInTransaction((em) -> { - return (Object[]) em.createQuery("select u.active, u.name from sec$User u where u.login = :login") - .setParameter("login", "testLogin") - .getFirstResult(); - }); - assertTrue((Boolean) activeAndName[0]); - assertEquals("testUser", activeAndName[1]); - - //returns null - Boolean active = cont.persistence().callInTransaction((em) -> { - return em.createQuery("select u.active from sec$User u where u.login = :login", Boolean.class) - .setParameter("login", "testLogin") - .getFirstResult(); - }); - assertNotNull(active); - assertTrue(active); - } - - @Test - public void testEnumImplicitConversion() throws Exception { - // explicit enum id value - cont.persistence().runInTransaction(em -> { - TypedQuery query = em.createQuery("select r from sec$Role r where r.type = :roleType", Role.class); - query.setParameter("roleType", 10); - List roles = query.getResultList(); - assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); - }); - - // enum as a positional parameter - cont.persistence().runInTransaction(em -> { - TypedQuery query = em.createQuery("select r from sec$Role r where r.type = ?1", Role.class); - query.setParameter(1, RoleType.SUPER); - List roles = query.getResultList(); - assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); - }); - - // enum as a named parameter - cont.persistence().runInTransaction(em -> { - TypedQuery query = em.createQuery("select r from sec$Role r where r.type = :roleType", Role.class); - query.setParameter("roleType", RoleType.SUPER); - List roles = query.getResultList(); - assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); - }); - - // no implicit conversions - fails - try (Transaction tx = cont.persistence().createTransaction()) { - TypedQuery query = cont.entityManager().createQuery("select r from sec$Role r where r.type = :roleType", Role.class); - query.setParameter("roleType", RoleType.SUPER, false); - List roles = null; - try { - roles = query.getResultList(); - fail(); - } catch (Exception e) { - // ok - } - } - } - - @Test - public void testNestedEntityGroupBy() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - em.createQuery("select ur.role, count(ur.id) from sec$UserRole ur group by ur.role") - .getResultList(); - tx.commit(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.haulmont.cuba.core.sys.QueryImpl; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.Role; +import com.haulmont.cuba.security.entity.RoleType; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import javax.persistence.FlushModeType; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class QueryTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID userId; + private UUID user2Id; + private UUID groupId; + + @Before + public void setUp() throws Exception { + + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + + User user = new User(); + userId = user.getId(); + user.setName("testUser"); + user.setLogin("testLogin"); + user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); + em.persist(user); + + user = new User(); + user2Id = user.getId(); + user.setName("testUser2"); + user.setLogin("testLogin2"); + user.setGroup(em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93"))); + em.persist(user); + + Group group = new Group(); + groupId = group.getId(); + group.setName("testGroup"); + em.persist(group); + + tx.commit(); + } + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER", userId, user2Id); + cont.deleteRecord("SEC_GROUP", groupId); + } + + @Test + public void test() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); + + Query query = em.createQuery("select r from sec$UserRole r where r.user.id = :user"); + query.setParameter("user", user); + List list = query.getResultList(); + + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNullParam() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createQuery("select r from sec$UserRole r where r.deleteTs = :dts"); + query.setParameter("dts", null); + List list = query.getResultList(); + + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testUpdate() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, groupId); + + Query query = em.createQuery("update sec$User u set u.group = :group where u.id = :userId"); + query.setParameter("userId", userId); + query.setParameter("group", group, false); + query.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + +// This test doesn't pass for some unclarified reason. +// +// public void testFlushBeforeUpdate() { +// Transaction tx = cont.persistence().createTransaction(); +// try { +// EntityManager em = cont.persistence().getEntityManager(); +// +// Group group = em.find(Group.class, groupId); +// User user = em.find(User.class, userId); +// assertNotNull(user); +// user.setName("newName"); +// +// Query query = em.createQuery("update sec$User u set u.group = :group where u.id = :userId"); +// query.setParameter("userId", userId); +// query.setParameter("group", group, false); +// query.executeUpdate(); +// +// tx.commit(); +// } finally { +// tx.end(); +// } +// +// tx = cont.persistence().createTransaction(); +// try { +// EntityManager em = cont.persistence().getEntityManager(); +// User user = em.find(User.class, userId); +// assertNotNull(user); +// assertEquals(groupId, user.getGroup().getId()); +// assertEquals("newName", user.getName()); +// +// tx.commit(); +// } finally { +// tx.end(); +// } +// } + + @Test + public void testAssociatedResult() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createQuery("select u.group from sec$User u where u.id = :userId"); + query.setParameter("userId", userId); + List list = query.getResultList(); + + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testIgnoreChanges() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + TypedQuery query; + List list; + + query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); + query.setParameter(1, "testUser"); + list = query.getResultList(); + assertEquals(1, list.size()); + User user = list.get(0); + + user.setName("newName"); + + query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); + query.setParameter(1, "testUser"); + list = query.getResultList(); + assertEquals(1, list.size()); + User user1 = list.get(0); + + assertTrue(user1 == user); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testFlushModeAuto() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + + TypedQuery query; + List list; + + query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); + query.setParameter(1, "testUser"); + list = query.getResultList(); + assertEquals(1, list.size()); + User user = list.get(0); + + user.setName("newName"); + + query = em.createQuery("select u from sec$User u where u.name = ?1", User.class); + query.setParameter(1, "newName"); + query.setFlushMode(FlushModeType.AUTO); + list = query.getResultList(); + assertEquals(1, list.size()); + User user1 = list.get(0); + + assertTrue(user1 == user); + + tx.commit(); + } + } + + @Test + public void testNativeQueryIgnoreChanges() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + TypedQuery query; + List list; + + query = em.createNativeQuery("select * from SEC_USER where NAME = ?1", User.class); + query.setParameter(1, "testUser"); + list = query.getResultList(); + assertEquals(1, list.size()); + User user = list.get(0); + + user.setName("newName"); + + query = em.createNativeQuery("select * from SEC_USER where NAME = ?1", User.class); + query.setParameter(1, "testUser"); + list = query.getResultList(); + assertEquals(1, list.size()); + User user1 = list.get(0); + + assertTrue(user1 == user); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNativeQuerySelect() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createNativeQuery("select ID, LOGIN from SEC_USER where NAME = ?1"); + query.setParameter(1, "testUser"); + List list = query.getResultList(); + assertEquals(1, list.size()); + assertTrue(list.get(0) instanceof Object[]); + Object[] row = (Object[]) list.get(0); + assertEquals(userId.toString(), row[0]); + assertEquals("testLogin", row[1]); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNativeQueryFlushBeforeUpdate() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, groupId); + User user = em.find(User.class, userId); + assertNotNull(user); + user.setName("newName"); + + Query query = em.createNativeQuery("update SEC_USER set GROUP_ID = ?1 where ID = ?2"); + query.setParameter(1, group.getId().toString()); + query.setParameter(2, userId.toString()); + query.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + User user = em.find(User.class, userId); + assertNotNull(user); + assertEquals(groupId, user.getGroup().getId()); + assertEquals("newName", user.getName()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testCaseInsensitiveSearch() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + TypedQuery query = cont.persistence().getEntityManager().createQuery( + "select u from sec$User u where u.name like :name", User.class); + query.setParameter("name", "(?i)%user%"); + List list = query.getResultList(); + tx.commit(); + + Iterables.find(list, new Predicate() { + @Override + public boolean apply(User input) { + return input.getId().equals(userId); + } + }); + } finally { + tx.end(); + } + + } + + @Test + public void testListParameter() throws Exception { + try (Transaction tx = cont.persistence().createTransaction()) { + TypedQuery query = cont.persistence().getEntityManager().createQuery( + "select u from sec$User u where u.id in :ids order by u.createTs", User.class); + query.setParameter("ids", Arrays.asList(UUID.fromString("60885987-1b61-4247-94c7-dff348347f93"), userId, user2Id)); + List list = query.getResultList(); + assertEquals(3, list.size()); + + tx.commit(); + } + + // Implicit conversion + + User user1, user2, user3; + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + user1 = em.find(User.class, userId); + user2 = em.find(User.class, user2Id); + user3 = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); + + tx.commit(); + } + + try (Transaction tx = cont.persistence().createTransaction()) { + TypedQuery query = cont.persistence().getEntityManager().createQuery( + "select u from sec$User u where u.id in :ids order by u.createTs", User.class); + query.setParameter("ids", Arrays.asList(user1, user2, user3)); + List list = query.getResultList(); + assertEquals(3, list.size()); + + tx.commit(); + } + + // Positional parameters + + try (Transaction tx = cont.persistence().createTransaction()) { + TypedQuery query = cont.persistence().getEntityManager().createQuery( + "select u from sec$User u where u.id in ?1 order by u.createTs", User.class); + query.setParameter(1, Arrays.asList(user1.getId(), user2.getId(), user3.getId())); + List list = query.getResultList(); + assertEquals(3, list.size()); + + tx.commit(); + } + + // Positional parameters with implicit conversion + + try (Transaction tx = cont.persistence().createTransaction()) { + TypedQuery query = cont.persistence().getEntityManager().createQuery( + "select u from sec$User u where u.id in ?1 order by u.createTs", User.class); + query.setParameter(1, Arrays.asList(user1, user2, user3)); + List list = query.getResultList(); + assertEquals(3, list.size()); + + tx.commit(); + } + } + + @Test + public void testEmptyCollectionParameter() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createQuery("select u from sec$User u where u.id in :ids"); + query.setParameter("ids", Collections.emptyList()); + List list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id in (:ids)"); + query.setParameter("ids", Collections.emptyList()); + list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in :ids"); + query.setParameter("ids", Collections.emptyList()); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); + query.setParameter("ids", Collections.emptyList()); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNullCollectionParameter() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createQuery("select u from sec$User u where u.id in :ids"); + query.setParameter("ids", null); + List list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id in (:ids)"); + query.setParameter("ids", null); + list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in :ids"); + query.setParameter("ids", null); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); + query.setParameter("ids", null); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNotExistsCollectionParameter() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query query = em.createQuery("select u from sec$User u where u.id in :ids"); + List list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id in (:ids)"); + list = query.getResultList(); + assertTrue(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in :ids"); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in (:ids)"); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + query = em.createQuery("select u from sec$User u where u.id not in (:ids1) or u.id not in (:ids2)"); + query.setParameter("ids1", null); + list = query.getResultList(); + assertFalse(list.isEmpty()); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testSingleBooleanResult() { + // works + Object[] activeAndName = cont.persistence().callInTransaction((em) -> { + return (Object[]) em.createQuery("select u.active, u.name from sec$User u where u.login = :login") + .setParameter("login", "testLogin") + .getFirstResult(); + }); + assertTrue((Boolean) activeAndName[0]); + assertEquals("testUser", activeAndName[1]); + + //returns null + Boolean active = cont.persistence().callInTransaction((em) -> { + return em.createQuery("select u.active from sec$User u where u.login = :login", Boolean.class) + .setParameter("login", "testLogin") + .getFirstResult(); + }); + assertNotNull(active); + assertTrue(active); + } + + @Test + public void testEnumImplicitConversion() throws Exception { + // explicit enum id value + cont.persistence().runInTransaction(em -> { + TypedQuery query = em.createQuery("select r from sec$Role r where r.type = :roleType", Role.class); + query.setParameter("roleType", 10); + List roles = query.getResultList(); + assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); + }); + + // enum as a positional parameter + cont.persistence().runInTransaction(em -> { + TypedQuery query = em.createQuery("select r from sec$Role r where r.type = ?1", Role.class); + query.setParameter(1, RoleType.SUPER); + List roles = query.getResultList(); + assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); + }); + + // enum as a named parameter + cont.persistence().runInTransaction(em -> { + TypedQuery query = em.createQuery("select r from sec$Role r where r.type = :roleType", Role.class); + query.setParameter("roleType", RoleType.SUPER); + List roles = query.getResultList(); + assertTrue(roles.stream().anyMatch(role -> role.getName().equals("Administrators"))); + }); + + // no implicit conversions - fails + try (Transaction tx = cont.persistence().createTransaction()) { + TypedQuery query = cont.entityManager().createQuery("select r from sec$Role r where r.type = :roleType", Role.class); + query.setParameter("roleType", RoleType.SUPER, false); + List roles = null; + try { + roles = query.getResultList(); + fail(); + } catch (Exception e) { + // ok + } + } + } + + @Test + public void testNestedEntityGroupBy() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + em.createQuery("select ur.role, count(ur.id) from sec$UserRole ur group by ur.role") + .getResultList(); + tx.commit(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/SpringPersistenceTest.java b/modules/core/test/com/haulmont/cuba/core/SpringPersistenceTest.java index 2c57f8f1a1..67ff024278 100644 --- a/modules/core/test/com/haulmont/cuba/core/SpringPersistenceTest.java +++ b/modules/core/test/com/haulmont/cuba/core/SpringPersistenceTest.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class SpringPersistenceTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void test() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - em.setSoftDeletion(false); - assertFalse(em.isSoftDeletion()); - - nestedMethod(); - nestedTxMethod(); - - em = cont.persistence().getEntityManager(); - assertFalse(em.isSoftDeletion()); - - tx.commit(); - } finally { - tx.end(); - } - } - - private void nestedMethod() { - EntityManager em = cont.persistence().getEntityManager(); - assertFalse(em.isSoftDeletion()); - } - - private void nestedTxMethod() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertTrue(em.isSoftDeletion()); - nestedTxMethod2(); - - tx.commit(); - } finally { - tx.end(); - } - } - - private void nestedTxMethod2() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertTrue(em.isSoftDeletion()); - - tx.commit(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class SpringPersistenceTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void test() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + em.setSoftDeletion(false); + assertFalse(em.isSoftDeletion()); + + nestedMethod(); + nestedTxMethod(); + + em = cont.persistence().getEntityManager(); + assertFalse(em.isSoftDeletion()); + + tx.commit(); + } finally { + tx.end(); + } + } + + private void nestedMethod() { + EntityManager em = cont.persistence().getEntityManager(); + assertFalse(em.isSoftDeletion()); + } + + private void nestedTxMethod() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertTrue(em.isSoftDeletion()); + nestedTxMethod2(); + + tx.commit(); + } finally { + tx.end(); + } + } + + private void nestedTxMethod2() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertTrue(em.isSoftDeletion()); + + tx.commit(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/TransactionTest.java b/modules/core/test/com/haulmont/cuba/core/TransactionTest.java index 9181e380d4..8d0adf0833 100644 --- a/modules/core/test/com/haulmont/cuba/core/TransactionTest.java +++ b/modules/core/test/com/haulmont/cuba/core/TransactionTest.java @@ -1,349 +1,349 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestSupport; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class TransactionTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private static final String TEST_EXCEPTION_MSG = "test exception"; - - private Persistence persistence; - - @Before - public void setUp() throws Exception { - persistence = cont.persistence(); - - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - runner.update("delete from SYS_SERVER"); - } - - @Test - public void testNoTransaction() { - try { - EntityManager em = cont.persistence().getEntityManager(); - fail(); - } catch (Exception e) { - assertTrue(e instanceof IllegalStateException); - } - } - - @Test - public void testCommit() { - UUID id; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Server server = em.find(Server.class, id); - assertEquals(id, server.getId()); - server.setRunning(false); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testCommitRetaining() { - UUID id; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id); - assertEquals(id, server.getId()); - server.setRunning(false); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testRollback() { - try { - __testRollback(); - fail(); - } catch (Exception e) { - assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); - } - } - - private void __testRollback() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - throwException(); - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testRollbackAndCatch() { - try { - __testRollbackAndCatch(); - fail(); - } catch (Exception e) { - assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); - } - } - - private void __testRollbackAndCatch() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - throwException(); - tx.commit(); - } catch (RuntimeException e) { - System.out.println("Caught exception: " + e.getMessage()); - throw e; - } finally { - tx.end(); - } - } - - @Test - public void testCommitRetainingAndRollback() { - try { - __testCommitRetainingAndRollback(); - fail(); - } catch (Exception e) { - assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); - } - } - - private void __testCommitRetainingAndRollback() { - UUID id; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - assertNotNull(em); - Server server = new Server(); - id = server.getId(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - server = em.find(Server.class, id); - assertEquals(id, server.getId()); - server.setRunning(false); - - throwException(); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNestedRollback() { - try { - Transaction tx = cont.persistence().createTransaction(); - try { - - Transaction tx1 = cont.persistence().getTransaction(); - try { - throwException(); - fail(); - tx1.commit(); - } catch (RuntimeException e) { - assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); - } finally { - tx1.end(); - } - - tx.commit(); - fail(); - } finally { - tx.end(); - } - } catch (Exception e) { - assertTrue(true); - } - } - - @Test - public void testSuspend() { - Transaction tx = cont.persistence().getTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - Transaction tx1 = cont.persistence().createTransaction(); - try { - EntityManager em1 = cont.persistence().getEntityManager(); - assertTrue(em != em1); - - Query query = em1.createQuery("select s from sys$Server s"); - List list = query.getResultList(); - assertNotNull(list); - - tx1.commit(); - } finally { - tx1.end(); - } - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testSuspendRollback() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - - Transaction tx1 = cont.persistence().createTransaction(); - try { - EntityManager em1 = cont.persistence().getEntityManager(); - assertTrue(em != em1); - Server server1 = em1.find(Server.class, server.getId()); - assertNull(server1); - throwException(); - tx1.commit(); - } catch (Exception e) { - // - } finally { - tx1.end(); - } - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testRunInTransaction() throws Exception { - UUID id = cont.persistence().callInTransaction(em -> { - assertNotNull(em); - Server server = new Server(); - server.setName("localhost"); - server.setRunning(true); - em.persist(server); - return server.getId(); - }); - - cont.persistence().runInTransaction(em -> { - Server server = em.find(Server.class, id); - assertNotNull(server); - assertEquals(id, server.getId()); - server.setRunning(false); - }); - - } - - @Test - public void testReadOnly() throws Exception { - try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { - TypedQuery query = persistence.getEntityManager().createQuery("select u from sec$User u where u.id = ?1", User.class); - query.setParameter(1, TestSupport.ADMIN_USER_ID); - User result = query.getSingleResult(); - tx.commit(); - } - - // read-only transaction cannot be committed if it contains changed entities - UUID id = persistence.callInTransaction(em -> { - Server server = new Server(); - server.setName("localhost"); - em.persist(server); - return server.getId(); - }); - try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { - TypedQuery query = persistence.getEntityManager().createQuery("select e from sys$Server e where e.id = ?1", Server.class); - query.setParameter(1, id); - Server server = query.getSingleResult(); - server.setName("changed"); - try { - tx.commit(); - fail(); - } catch (IllegalStateException e) { - // ok - } - } - } - - private void throwException() { - throw new RuntimeException(TEST_EXCEPTION_MSG); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestSupport; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class TransactionTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private static final String TEST_EXCEPTION_MSG = "test exception"; + + private Persistence persistence; + + @Before + public void setUp() throws Exception { + persistence = cont.persistence(); + + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + runner.update("delete from SYS_SERVER"); + } + + @Test + public void testNoTransaction() { + try { + EntityManager em = cont.persistence().getEntityManager(); + fail(); + } catch (Exception e) { + assertTrue(e instanceof IllegalStateException); + } + } + + @Test + public void testCommit() { + UUID id; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Server server = em.find(Server.class, id); + assertEquals(id, server.getId()); + server.setRunning(false); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testCommitRetaining() { + UUID id; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id); + assertEquals(id, server.getId()); + server.setRunning(false); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testRollback() { + try { + __testRollback(); + fail(); + } catch (Exception e) { + assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); + } + } + + private void __testRollback() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + throwException(); + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testRollbackAndCatch() { + try { + __testRollbackAndCatch(); + fail(); + } catch (Exception e) { + assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); + } + } + + private void __testRollbackAndCatch() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + throwException(); + tx.commit(); + } catch (RuntimeException e) { + System.out.println("Caught exception: " + e.getMessage()); + throw e; + } finally { + tx.end(); + } + } + + @Test + public void testCommitRetainingAndRollback() { + try { + __testCommitRetainingAndRollback(); + fail(); + } catch (Exception e) { + assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); + } + } + + private void __testCommitRetainingAndRollback() { + UUID id; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + assertNotNull(em); + Server server = new Server(); + id = server.getId(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + server = em.find(Server.class, id); + assertEquals(id, server.getId()); + server.setRunning(false); + + throwException(); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNestedRollback() { + try { + Transaction tx = cont.persistence().createTransaction(); + try { + + Transaction tx1 = cont.persistence().getTransaction(); + try { + throwException(); + fail(); + tx1.commit(); + } catch (RuntimeException e) { + assertEquals(TEST_EXCEPTION_MSG, e.getMessage()); + } finally { + tx1.end(); + } + + tx.commit(); + fail(); + } finally { + tx.end(); + } + } catch (Exception e) { + assertTrue(true); + } + } + + @Test + public void testSuspend() { + Transaction tx = cont.persistence().getTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + Transaction tx1 = cont.persistence().createTransaction(); + try { + EntityManager em1 = cont.persistence().getEntityManager(); + assertTrue(em != em1); + + Query query = em1.createQuery("select s from sys$Server s"); + List list = query.getResultList(); + assertNotNull(list); + + tx1.commit(); + } finally { + tx1.end(); + } + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testSuspendRollback() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + + Transaction tx1 = cont.persistence().createTransaction(); + try { + EntityManager em1 = cont.persistence().getEntityManager(); + assertTrue(em != em1); + Server server1 = em1.find(Server.class, server.getId()); + assertNull(server1); + throwException(); + tx1.commit(); + } catch (Exception e) { + // + } finally { + tx1.end(); + } + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testRunInTransaction() throws Exception { + UUID id = cont.persistence().callInTransaction(em -> { + assertNotNull(em); + Server server = new Server(); + server.setName("localhost"); + server.setRunning(true); + em.persist(server); + return server.getId(); + }); + + cont.persistence().runInTransaction(em -> { + Server server = em.find(Server.class, id); + assertNotNull(server); + assertEquals(id, server.getId()); + server.setRunning(false); + }); + + } + + @Test + public void testReadOnly() throws Exception { + try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { + TypedQuery query = persistence.getEntityManager().createQuery("select u from sec$User u where u.id = ?1", User.class); + query.setParameter(1, TestSupport.ADMIN_USER_ID); + User result = query.getSingleResult(); + tx.commit(); + } + + // read-only transaction cannot be committed if it contains changed entities + UUID id = persistence.callInTransaction(em -> { + Server server = new Server(); + server.setName("localhost"); + em.persist(server); + return server.getId(); + }); + try (Transaction tx = persistence.createTransaction(new TransactionParams().setReadOnly(true))) { + TypedQuery query = persistence.getEntityManager().createQuery("select e from sys$Server e where e.id = ?1", Server.class); + query.setParameter(1, id); + Server server = query.getSingleResult(); + server.setName("changed"); + try { + tx.commit(); + fail(); + } catch (IllegalStateException e) { + // ok + } + } + } + + private void throwException() { + throw new RuntimeException(TEST_EXCEPTION_MSG); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/TypedNativeQueryTest.java b/modules/core/test/com/haulmont/cuba/core/TypedNativeQueryTest.java index 7f25e88c5f..be82e0b381 100644 --- a/modules/core/test/com/haulmont/cuba/core/TypedNativeQueryTest.java +++ b/modules/core/test/com/haulmont/cuba/core/TypedNativeQueryTest.java @@ -1,165 +1,165 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestSupport; -import org.junit.After; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.UUID; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -public class TypedNativeQueryTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID groupId, userId; - - @After - public void tearDown() throws Exception { - if (userId != null) { - cont.deleteRecord("SEC_USER", userId); - } - if (groupId != null) { - cont.deleteRecord("SEC_GROUP", groupId); - } - } - - /* - * Test that entity which is loaded by native typed query, is MANAGED, - * by changing loaded entity attribute. - */ - @Test - public void testTypedNativeQueryByChangingAttribute() { - Group group = new Group(); - groupId = group.getId(); - group.setName("Old Name"); - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager().persist(group); - tx.commit(); - } finally { - tx.end(); - } - - // load with native query, change attribute - String nativeQuery = "select ID, VERSION, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, NAME from SEC_GROUP where ID = ?"; - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); - q.setParameter(1, group.getId().toString()); - - Group g = q.getResultList().get(0); - - g.setName("New Name"); - tx.commit(); - } finally { - tx.end(); - } - - // load again, check - Group g2; - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - g2 = em.find(Group.class, group.getId()); - - assertNotNull(g2); - assertEquals("New Name", g2.getName()); - - tx.commit(); - } finally { - tx.end(); - } - } - - /* - * Test that entity which is loaded by native typed query, - * is MANAGED, by persisting another entity linked to it. - */ - @Test - public void testTypedNativeQueryByPersistingAnotherEntity() { - Group group = new Group(); - groupId = group.getId(); - group.setName("Old Name"); - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager().persist(group); - tx.commit(); - } finally { - tx.end(); - } - - String nativeQuery = "select ID, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, VERSION, NAME from SEC_GROUP where ID = ?"; - tx = cont.persistence().createTransaction(); - Group g; - try { - EntityManager em = cont.persistence().getEntityManager(); - - TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); - q.setParameter(1, group.getId().toString()); - g = q.getResultList().get(0); - tx.commit(); - } finally { - tx.end(); - } - - User user = new User(); - userId = user.getId(); - user.setLogin("typednativesqlquery"); - user.setGroup(g); - user.setName("Test"); - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - em.persist(user); - tx.commit(); - } finally { - tx.end(); - } - // gets persisted without error - } - - @Test - public void testAssigningView() throws Exception { - String nativeQuery = "select ID, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, VERSION, NAME from SEC_GROUP where ID = ?"; - - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); - q.setParameter(1, TestSupport.COMPANY_GROUP_ID.toString()); - try { - q.setView(Group.class, "group.browse"); - fail(); - } catch (UnsupportedOperationException e) { - // ok - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestSupport; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.UUID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class TypedNativeQueryTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID groupId, userId; + + @After + public void tearDown() throws Exception { + if (userId != null) { + cont.deleteRecord("SEC_USER", userId); + } + if (groupId != null) { + cont.deleteRecord("SEC_GROUP", groupId); + } + } + + /* + * Test that entity which is loaded by native typed query, is MANAGED, + * by changing loaded entity attribute. + */ + @Test + public void testTypedNativeQueryByChangingAttribute() { + Group group = new Group(); + groupId = group.getId(); + group.setName("Old Name"); + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager().persist(group); + tx.commit(); + } finally { + tx.end(); + } + + // load with native query, change attribute + String nativeQuery = "select ID, VERSION, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, NAME from SEC_GROUP where ID = ?"; + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); + q.setParameter(1, group.getId().toString()); + + Group g = q.getResultList().get(0); + + g.setName("New Name"); + tx.commit(); + } finally { + tx.end(); + } + + // load again, check + Group g2; + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + g2 = em.find(Group.class, group.getId()); + + assertNotNull(g2); + assertEquals("New Name", g2.getName()); + + tx.commit(); + } finally { + tx.end(); + } + } + + /* + * Test that entity which is loaded by native typed query, + * is MANAGED, by persisting another entity linked to it. + */ + @Test + public void testTypedNativeQueryByPersistingAnotherEntity() { + Group group = new Group(); + groupId = group.getId(); + group.setName("Old Name"); + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager().persist(group); + tx.commit(); + } finally { + tx.end(); + } + + String nativeQuery = "select ID, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, VERSION, NAME from SEC_GROUP where ID = ?"; + tx = cont.persistence().createTransaction(); + Group g; + try { + EntityManager em = cont.persistence().getEntityManager(); + + TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); + q.setParameter(1, group.getId().toString()); + g = q.getResultList().get(0); + tx.commit(); + } finally { + tx.end(); + } + + User user = new User(); + userId = user.getId(); + user.setLogin("typednativesqlquery"); + user.setGroup(g); + user.setName("Test"); + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + em.persist(user); + tx.commit(); + } finally { + tx.end(); + } + // gets persisted without error + } + + @Test + public void testAssigningView() throws Exception { + String nativeQuery = "select ID, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, VERSION, NAME from SEC_GROUP where ID = ?"; + + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + TypedQuery q = em.createNativeQuery(nativeQuery, Group.class); + q.setParameter(1, TestSupport.COMPANY_GROUP_ID.toString()); + try { + q.setView(Group.class, "group.browse"); + fail(); + } catch (UnsupportedOperationException e) { + // ok + } + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/UniqueNumbersTest.java b/modules/core/test/com/haulmont/cuba/core/UniqueNumbersTest.java index 8509ff8158..fab406699e 100644 --- a/modules/core/test/com/haulmont/cuba/core/UniqueNumbersTest.java +++ b/modules/core/test/com/haulmont/cuba/core/UniqueNumbersTest.java @@ -1,184 +1,184 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.haulmont.cuba.core.app.UniqueNumbersAPI; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.testsupport.TestContainer; -import org.apache.commons.lang.StringUtils; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class UniqueNumbersTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - String[] seqNames = {"t1", "t2", "t3", "t4"}; - AtomicInteger finishedThreads = new AtomicInteger(); - AtomicInteger exceptionCnt = new AtomicInteger(); - - @Test - public void test() { - UniqueNumbersAPI mBean = AppBeans.get(UniqueNumbersAPI.NAME); - long n = mBean.getNextNumber("test1"); - assertTrue(n >= 0); - } - - @Test - public void testSequenceDeletion() throws Exception { - UniqueNumbersAPI uniqueNumbersAPI = AppBeans.get(UniqueNumbersAPI.NAME); - - uniqueNumbersAPI.getCurrentNumber("s1"); - uniqueNumbersAPI.deleteSequence("s1"); - uniqueNumbersAPI.getCurrentNumber("s1"); - } - - @Test - public void testConcurrentModification() throws Exception { - int threadCnt = 8; - ExecutorService executorService = Executors.newFixedThreadPool(threadCnt, - new ThreadFactoryBuilder().setNameFormat("T%d").build()); - - final Action[] actions = {new SleepAction(), new GetNumberAction(), - new SetNumberAction(), new DeleteSequenceAction()}; - - for (int i = 0; i < threadCnt; i++) { - final int finalI = i; - executorService.submit(new Runnable() { - - int runnableNo = finalI; - - @Override - public void run() { - ThreadLocalRandom random = ThreadLocalRandom.current(); - for (int i = 0; i < 10; i++) { - int action = random.nextInt(0, 4); - System.out.println("Runnable " + runnableNo + " iteration " + i + " action " + actions[action]); - try { - int seqN = actions[action].perform(runnableNo); - actions[action].success(runnableNo, seqN); - } catch (Exception e) { - if (e instanceof IllegalStateException && StringUtils.contains(e.getMessage(), "Attempt to delete")) { - System.err.println(e.getMessage()); - continue; - } - System.err.println(e.getMessage()); - exceptionCnt.incrementAndGet(); - } - } - finishedThreads.incrementAndGet(); - } - }); - } - - while (finishedThreads.get() < threadCnt) { - System.out.println("Waiting..."); - TimeUnit.MILLISECONDS.sleep(200); - } - - assertEquals(exceptionCnt.get(), 0); - } - - protected abstract class Action { - abstract int perform(int threadNumber); - - abstract void success(int threadNumber, int seqN); - } - - protected class SleepAction extends Action { - @Override - public int perform(int threadNumber) { - try { - TimeUnit.MILLISECONDS.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return -1; - } - - @Override - void success(int threadNumber, int seqN) { - System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + " slept 10 ms"); - } - } - - protected class GetNumberAction extends Action { - @Override - public int perform(int threadNumber) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - int nextInt = random.nextInt(0, 3); - UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); - long nextNumber = api.getNextNumber(seqNames[nextInt]); - return nextInt; - } - - @Override - void success(int threadNumber, int seqN) { - System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + - " got number from seq t" + seqN); - } - } - - protected class SetNumberAction extends Action { - - @Override - public int perform(int threadNumber) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - int nextInt = random.nextInt(0, 3); - UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); - int nextNum = random.nextInt(0, 10000); - api.setCurrentNumber(seqNames[nextInt], nextNum); - return nextInt; - } - - @Override - void success(int threadNumber, int seqN) { - System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + - " set number to seq t" + seqN); - } - } - - protected class DeleteSequenceAction extends Action { - - @Override - public int perform(int threadNumber) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - int nextInt = random.nextInt(0, 3); - UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); - api.deleteSequence(seqNames[nextInt]); - return nextInt; - } - - @Override - void success(int threadNumber, int seqN) { - System.out.println("Runnable " + threadNumber + " " + - Thread.currentThread().getName() + " dropped seq t" + seqN); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.haulmont.cuba.core.app.UniqueNumbersAPI; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.testsupport.TestContainer; +import org.apache.commons.lang.StringUtils; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class UniqueNumbersTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + String[] seqNames = {"t1", "t2", "t3", "t4"}; + AtomicInteger finishedThreads = new AtomicInteger(); + AtomicInteger exceptionCnt = new AtomicInteger(); + + @Test + public void test() { + UniqueNumbersAPI mBean = AppBeans.get(UniqueNumbersAPI.NAME); + long n = mBean.getNextNumber("test1"); + assertTrue(n >= 0); + } + + @Test + public void testSequenceDeletion() throws Exception { + UniqueNumbersAPI uniqueNumbersAPI = AppBeans.get(UniqueNumbersAPI.NAME); + + uniqueNumbersAPI.getCurrentNumber("s1"); + uniqueNumbersAPI.deleteSequence("s1"); + uniqueNumbersAPI.getCurrentNumber("s1"); + } + + @Test + public void testConcurrentModification() throws Exception { + int threadCnt = 8; + ExecutorService executorService = Executors.newFixedThreadPool(threadCnt, + new ThreadFactoryBuilder().setNameFormat("T%d").build()); + + final Action[] actions = {new SleepAction(), new GetNumberAction(), + new SetNumberAction(), new DeleteSequenceAction()}; + + for (int i = 0; i < threadCnt; i++) { + final int finalI = i; + executorService.submit(new Runnable() { + + int runnableNo = finalI; + + @Override + public void run() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + for (int i = 0; i < 10; i++) { + int action = random.nextInt(0, 4); + System.out.println("Runnable " + runnableNo + " iteration " + i + " action " + actions[action]); + try { + int seqN = actions[action].perform(runnableNo); + actions[action].success(runnableNo, seqN); + } catch (Exception e) { + if (e instanceof IllegalStateException && StringUtils.contains(e.getMessage(), "Attempt to delete")) { + System.err.println(e.getMessage()); + continue; + } + System.err.println(e.getMessage()); + exceptionCnt.incrementAndGet(); + } + } + finishedThreads.incrementAndGet(); + } + }); + } + + while (finishedThreads.get() < threadCnt) { + System.out.println("Waiting..."); + TimeUnit.MILLISECONDS.sleep(200); + } + + assertEquals(exceptionCnt.get(), 0); + } + + protected abstract class Action { + abstract int perform(int threadNumber); + + abstract void success(int threadNumber, int seqN); + } + + protected class SleepAction extends Action { + @Override + public int perform(int threadNumber) { + try { + TimeUnit.MILLISECONDS.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return -1; + } + + @Override + void success(int threadNumber, int seqN) { + System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + " slept 10 ms"); + } + } + + protected class GetNumberAction extends Action { + @Override + public int perform(int threadNumber) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + int nextInt = random.nextInt(0, 3); + UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); + long nextNumber = api.getNextNumber(seqNames[nextInt]); + return nextInt; + } + + @Override + void success(int threadNumber, int seqN) { + System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + + " got number from seq t" + seqN); + } + } + + protected class SetNumberAction extends Action { + + @Override + public int perform(int threadNumber) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + int nextInt = random.nextInt(0, 3); + UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); + int nextNum = random.nextInt(0, 10000); + api.setCurrentNumber(seqNames[nextInt], nextNum); + return nextInt; + } + + @Override + void success(int threadNumber, int seqN) { + System.out.println("Runnable " + threadNumber + " " + Thread.currentThread().getName() + + " set number to seq t" + seqN); + } + } + + protected class DeleteSequenceAction extends Action { + + @Override + public int perform(int threadNumber) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + int nextInt = random.nextInt(0, 3); + UniqueNumbersAPI api = AppBeans.get(UniqueNumbersAPI.NAME); + api.deleteSequence(seqNames[nextInt]); + return nextInt; + } + + @Override + void success(int threadNumber, int seqN) { + System.out.println("Runnable " + threadNumber + " " + + Thread.currentThread().getName() + " dropped seq t" + seqN); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/UpdateDetachedTest.java b/modules/core/test/com/haulmont/cuba/core/UpdateDetachedTest.java index e0f5c27564..1757bf2bb2 100644 --- a/modules/core/test/com/haulmont/cuba/core/UpdateDetachedTest.java +++ b/modules/core/test/com/haulmont/cuba/core/UpdateDetachedTest.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import com.haulmont.cuba.core.app.DataService; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.Permission; -import com.haulmont.cuba.security.entity.PermissionType; -import com.haulmont.cuba.security.entity.Role; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.Collections; -import java.util.Set; -import java.util.UUID; - -import static com.haulmont.cuba.testsupport.TestSupport.reserialize; -import static org.junit.Assert.*; - -public class UpdateDetachedTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID roleId, role2Id, permissionId; - - @Before - public void setUp() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Role role = new Role(); - roleId = role.getId(); - role.setName("testRole"); - em.persist(role); - - Role role2 = new Role(); - role2Id = role2.getId(); - role2.setName("testRole2"); - em.persist(role2); - - Permission permission = new Permission(); - permissionId = permission.getId(); - permission.setRole(role); - permission.setType(PermissionType.SCREEN); - permission.setTarget("testTarget"); - em.persist(permission); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query q; - q = em.createNativeQuery("delete from SEC_PERMISSION where ID = ?"); - q.setParameter(1, permissionId.toString()); - q.executeUpdate(); - - q = em.createNativeQuery("delete from SEC_ROLE where ID = ? or ID = ?"); - q.setParameter(1, roleId.toString()); - q.setParameter(2, role2Id.toString()); - q.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void test() throws Exception { - Permission p; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - View view = new View(Permission.class) - .addProperty("target") - .addProperty("role", - new View(Role.class) - .addProperty("name") - ); - - p = em.find(Permission.class, permissionId, view); - tx.commitRetaining(); - - assertNotNull(p); - p.setTarget("newTarget"); - - em = cont.persistence().getEntityManager(); - p = em.merge(p); - - tx.commit(); - } finally { - tx.end(); - } - p = reserialize(p); - assertTrue(PersistenceHelper.isDetached(p)); - assertNotNull(p.getRole()); - assertTrue(PersistenceHelper.isDetached(p.getRole())); - assertTrue(PersistenceHelper.isLoaded(p, "role")); - } - - @Test - public void testRollback() { - Permission p = null; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - View view = new View(Permission.class) - .addProperty("target") - .addProperty("role", - new View(Role.class) - .addProperty("name") - ); - - p = em.find(Permission.class, permissionId, view); - tx.commitRetaining(); - - p.setTarget("newTarget"); - - em = cont.persistence().getEntityManager(); - p = em.merge(p); - - throwException(); - tx.commit(); - } catch (RuntimeException e) { - // ok - } finally { - tx.end(); - assertNotNull(p); -// assertNull(((PersistenceCapable) p).pcGetDetachedState()); - } - } - - private void throwException() { - throw new RuntimeException(); - } - - @Test - public void testDataService() throws Exception { - Permission p; - DataService ds = AppBeans.get(DataService.NAME); - - LoadContext ctx = new LoadContext<>(Permission.class); - ctx.setId(permissionId); - ctx.setView(new View(Permission.class) - .addProperty("target") - .addProperty("role", - new View(Role.class) - .addProperty("name") - ) - ); - p = ds.load(ctx); - - assertNotNull(p); - p.setTarget("newTarget"); - - CommitContext commitCtx = new CommitContext(Collections.singleton(p)); - Set entities = ds.commit(commitCtx); - - Permission result = null; - for (Entity entity : entities) { - if (entity.equals(p)) - result = (Permission) entity; - } - result = reserialize(result); - assertTrue(PersistenceHelper.isDetached(result)); - assertNotNull(result.getRole()); - assertTrue(PersistenceHelper.isDetached(result.getRole())); - assertTrue(PersistenceHelper.isLoaded(result, "role")); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import com.haulmont.cuba.core.app.DataService; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.Permission; +import com.haulmont.cuba.security.entity.PermissionType; +import com.haulmont.cuba.security.entity.Role; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.Collections; +import java.util.Set; +import java.util.UUID; + +import static com.haulmont.cuba.testsupport.TestSupport.reserialize; +import static org.junit.Assert.*; + +public class UpdateDetachedTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID roleId, role2Id, permissionId; + + @Before + public void setUp() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Role role = new Role(); + roleId = role.getId(); + role.setName("testRole"); + em.persist(role); + + Role role2 = new Role(); + role2Id = role2.getId(); + role2.setName("testRole2"); + em.persist(role2); + + Permission permission = new Permission(); + permissionId = permission.getId(); + permission.setRole(role); + permission.setType(PermissionType.SCREEN); + permission.setTarget("testTarget"); + em.persist(permission); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query q; + q = em.createNativeQuery("delete from SEC_PERMISSION where ID = ?"); + q.setParameter(1, permissionId.toString()); + q.executeUpdate(); + + q = em.createNativeQuery("delete from SEC_ROLE where ID = ? or ID = ?"); + q.setParameter(1, roleId.toString()); + q.setParameter(2, role2Id.toString()); + q.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void test() throws Exception { + Permission p; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + View view = new View(Permission.class) + .addProperty("target") + .addProperty("role", + new View(Role.class) + .addProperty("name") + ); + + p = em.find(Permission.class, permissionId, view); + tx.commitRetaining(); + + assertNotNull(p); + p.setTarget("newTarget"); + + em = cont.persistence().getEntityManager(); + p = em.merge(p); + + tx.commit(); + } finally { + tx.end(); + } + p = reserialize(p); + assertTrue(PersistenceHelper.isDetached(p)); + assertNotNull(p.getRole()); + assertTrue(PersistenceHelper.isDetached(p.getRole())); + assertTrue(PersistenceHelper.isLoaded(p, "role")); + } + + @Test + public void testRollback() { + Permission p = null; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + View view = new View(Permission.class) + .addProperty("target") + .addProperty("role", + new View(Role.class) + .addProperty("name") + ); + + p = em.find(Permission.class, permissionId, view); + tx.commitRetaining(); + + p.setTarget("newTarget"); + + em = cont.persistence().getEntityManager(); + p = em.merge(p); + + throwException(); + tx.commit(); + } catch (RuntimeException e) { + // ok + } finally { + tx.end(); + assertNotNull(p); +// assertNull(((PersistenceCapable) p).pcGetDetachedState()); + } + } + + private void throwException() { + throw new RuntimeException(); + } + + @Test + public void testDataService() throws Exception { + Permission p; + DataService ds = AppBeans.get(DataService.NAME); + + LoadContext ctx = new LoadContext<>(Permission.class); + ctx.setId(permissionId); + ctx.setView(new View(Permission.class) + .addProperty("target") + .addProperty("role", + new View(Role.class) + .addProperty("name") + ) + ); + p = ds.load(ctx); + + assertNotNull(p); + p.setTarget("newTarget"); + + CommitContext commitCtx = new CommitContext(Collections.singleton(p)); + Set entities = ds.commit(commitCtx); + + Permission result = null; + for (Entity entity : entities) { + if (entity.equals(p)) + result = (Permission) entity; + } + result = reserialize(result); + assertTrue(PersistenceHelper.isDetached(result)); + assertNotNull(result.getRole()); + assertTrue(PersistenceHelper.isDetached(result.getRole())); + assertTrue(PersistenceHelper.isLoaded(result, "role")); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/ViewTest.java b/modules/core/test/com/haulmont/cuba/core/ViewTest.java index 073b594d60..ac8ac2426d 100644 --- a/modules/core/test/com/haulmont/cuba/core/ViewTest.java +++ b/modules/core/test/com/haulmont/cuba/core/ViewTest.java @@ -1,558 +1,558 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.bali.db.ResultSetHandler; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.testmodel.multiplelinks.LinkEntity; -import com.haulmont.cuba.testmodel.multiplelinks.MultiLinkEntity; -import com.haulmont.cuba.testmodel.selfinherited.ChildEntity; -import com.haulmont.cuba.testmodel.selfinherited.RootEntity; -import com.haulmont.cuba.testmodel.selfinherited.RootEntityDetail; -import com.haulmont.cuba.testsupport.TestContainer; -import org.eclipse.persistence.queries.FetchGroupTracker; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.slf4j.LoggerFactory; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; -import java.util.UUID; - -import static com.haulmont.cuba.testsupport.TestSupport.assertFail; -import static com.haulmont.cuba.testsupport.TestSupport.reserialize; -import static org.junit.Assert.*; - -public class ViewTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private TimeSource timeSource; - - private UUID userId; - private RootEntity rootEntity; - private ChildEntity childEntity; - private MultiLinkEntity multiLinkEntity; - private LinkEntity linkEntity1, linkEntity2, linkEntity3; - private Persistence persistence; - private Metadata metadata; - - @Before - public void setUp() throws Exception { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - context.getLogger("com.haulmont.cuba.core.sys.FetchGroupManager").setLevel(Level.TRACE); - - persistence = cont.persistence(); - metadata = cont.metadata(); - timeSource = AppBeans.get(TimeSource.NAME); - - Transaction tx = persistence.createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); - - User user = new User(); - userId = user.getId(); - user.setName("testUser"); - user.setLogin("login" + userId); - user.setPassword("000"); - user.setGroup(group); - em.persist(user); - - childEntity = metadata.create(ChildEntity.class); - childEntity.setName("childEntityName"); - childEntity.setDescription("childEntityDescription"); - em.persist(childEntity); - - rootEntity = metadata.create(RootEntity.class); - rootEntity.setDescription("rootEntityDescription"); - rootEntity.setEntity(childEntity); - em.persist(rootEntity); - - RootEntityDetail detail1 = metadata.create(RootEntityDetail.class); - detail1.setInfo("detail1"); - detail1.setMaster(childEntity); - em.persist(detail1); - - RootEntityDetail detail2 = metadata.create(RootEntityDetail.class); - detail2.setInfo("detail2"); - detail2.setMaster(childEntity); - em.persist(detail2); - - linkEntity1 = metadata.create(LinkEntity.class); - linkEntity1.setName("A"); - em.persist(linkEntity1); - - linkEntity2 = metadata.create(LinkEntity.class); - linkEntity2.setName("B"); - em.persist(linkEntity2); - - linkEntity3 = metadata.create(LinkEntity.class); - linkEntity3.setName("C"); - em.persist(linkEntity3); - - multiLinkEntity = metadata.create(MultiLinkEntity.class); - multiLinkEntity.setA(linkEntity1); - multiLinkEntity.setB(linkEntity2); - multiLinkEntity.setC(linkEntity3); - em.persist(multiLinkEntity); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - context.getLogger("com.haulmont.cuba.core.sys.FetchGroupManager").setLevel(Level.DEBUG); - - cont.deleteRecord("SEC_USER", userId); - cont.deleteRecord("TEST_ROOT_ENTITY_DETAIL"); - cont.deleteRecord("TEST_CHILD_ENTITY"); - cont.deleteRecord("TEST_ROOT_ENTITY"); - cont.deleteRecord("TEST_MULTI_LINK_ENTITY"); - cont.deleteRecord("TEST_LINK_ENTITY"); - } - - @Test - public void testQuery() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Query q = em.createQuery("select u from sec$User u where u.id = ?1"); - q.setParameter(1, userId); - - View view = new View(User.class) - .addProperty("name") - .addProperty("login") - .addProperty("group", - new View(Group.class) - .addProperty("name") - ) - .setLoadPartialEntities(true); - q.setView(view); - - User user = (User) q.getSingleResult(); - - tx.commit(); - user = reserialize(user); - - try { - user.getPassword(); - fail(); - } catch (Exception ignored) { - } - assertNotNull(user.getGroup().getName()); - } finally { - tx.end(); - } - } - - @Test - public void testEntityManager() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - View view = new View(User.class) - .addProperty("name") - .addProperty("login") - .addProperty("group", - new View(Group.class) - .addProperty("name") - ).setLoadPartialEntities(true); - - User user = em.find(User.class, userId, view); - - tx.commit(); - user = reserialize(user); - - try { - user.getPassword(); - fail(); - } catch (Exception ignored) { - } - assertNotNull(user.getGroup().getName()); - assertNotNull(user.getCreateTs()); - assertNotNull(user.getGroup().getCreateTs()); - } finally { - tx.end(); - } - } - - @Test - public void testViewWithoutSystemProperties() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - View view = new View(User.class, false) - .addProperty("name") - .addProperty("login") - .addProperty("group", - new View(Group.class, false) - .addProperty("name") - ).setLoadPartialEntities(true); - - User user = em.find(User.class, userId, view); - - tx.commit(); - user = reserialize(user); - - try { - user.getPassword(); - fail(); - } catch (Exception ignored) { - } - try { - user.getCreateTs(); - fail(); - } catch (Exception ignored) { - } - assertNotNull(user.getGroup().getName()); - try { - user.getGroup().getCreateTs(); - fail(); - } catch (Exception ignored) { - } - } finally { - tx.end(); - } - } - - @Test - public void testViewWithoutSystemProperties_update() throws Exception { - - View view = new View(User.class, false) - .addProperty("name") - .addProperty("login") - .addProperty("loginLowerCase") - .addProperty("group", - new View(Group.class, false) - .addProperty("name") - ); - view.setLoadPartialEntities(true); - - try (Transaction tx = cont.persistence().createTransaction()) { - // First stage: change managed - - long ts = timeSource.currentTimeMillis(); - Thread.sleep(200); - - EntityManager em = cont.persistence().getEntityManager(); - User user = em.find(User.class, userId, view); - - assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); - - user.setName(new Date().toString()); - - tx.commitRetaining(); - - assertTrue(getCurrentUpdateTs() > ts); - - // Second stage: change detached - - ts = timeSource.currentTimeMillis(); - Thread.sleep(1000); - - em = cont.persistence().getEntityManager(); - user = em.find(User.class, userId, view); - - tx.commitRetaining(); - - assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); - - user.setName(new Date().toString()); - em = cont.persistence().getEntityManager(); - em.merge(user); - - tx.commit(); - - assertTrue(getCurrentUpdateTs() > ts); - } - - // test _minimal - try (Transaction tx = cont.persistence().createTransaction()) { - long ts = timeSource.currentTimeMillis(); - Thread.sleep(1000); - - View minimalView = cont.metadata().getViewRepository().getView(User.class, View.MINIMAL); - minimalView.setLoadPartialEntities(true); - - EntityManager em = cont.persistence().getEntityManager(); - User user = em.find(User.class, userId, minimalView); - - tx.commitRetaining(); - - assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); - - user.setName(new Date().toString()); - em = cont.persistence().getEntityManager(); - em.merge(user); - - tx.commit(); - - assertTrue(getCurrentUpdateTs() > ts); - - tx.commit(); - } - - // test DataManager - long ts = timeSource.currentTimeMillis(); - Thread.sleep(1000); - - DataManager dataManager = AppBeans.get(DataManager.class).secure(); - User user = dataManager.load(LoadContext.create(User.class).setId(userId).setView(view)); - - assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); - - user.setName(new Date().toString()); - dataManager.commit(user); - - assertTrue(getCurrentUpdateTs() > ts); - } - - /* - * Pre 6.0: Test that entity which is loaded with view, can lazily fetch not-loaded attributes until transaction ends. - * - * 6.0: Not loaded (unfetched) attributes cannot be loaded lazily. Otherwise, previously loaded reference attributes are lost. - */ - @Test - public void testLazyLoadAfterLoadWithView() throws Exception { - View view = new View(User.class, false) - .addProperty("name") - .addProperty("group", new View(Group.class) - .addProperty("name")) - .setLoadPartialEntities(true); - - User user; - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - user = em.find(User.class, userId, view); - tx.commit(); - } finally { - tx.end(); - } - - user = reserialize(user); - assertNotNull(user.getGroup().getName()); - - // login is not loaded after transaction is finished - try { - user.getLogin(); - fail(); - } catch (Exception ignored) { - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - user = em.find(User.class, userId, view); - assertNotNull(user); - - // field is loaded lazily but the object becomes not partial and references loaded by previous view are cleared - user.getLogin(); - - tx.commit(); - } finally { - tx.end(); - } - user = reserialize(user); - assertFail(user::getGroup); - } - - - @Test - public void testLazyProperty() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Query q = em.createQuery("select u from sec$User u where u.id = ?1"); - q.setParameter(1, userId); - - View userRoleView = new View(UserRole.class).addProperty("role", new View(Role.class).addProperty("name")); - View view = new View(User.class) - .addProperty("name") - .addProperty("login") - .addProperty("userRoles", userRoleView, true) - .addProperty("group", - new View(Group.class) - .addProperty("name") - ).setLoadPartialEntities(true); - q.setView(view); - - User user = (User) q.getSingleResult(); - - tx.commit(); - user = reserialize(user); - - user.getUserRoles().size(); - - try { - user.getPassword(); - fail(); - } catch (Exception ignored) { - } - assertNotNull(user.getGroup().getName()); - } finally { - tx.end(); - } - } - - private long getCurrentUpdateTs() { - String sql = "select UPDATE_TS from SEC_USER where ID = '" + userId.toString() + "'"; - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - try { - return runner.query(sql, new ResultSetHandler() { - @Override - public Long handle(ResultSet rs) throws SQLException { - rs.next(); - return rs.getTimestamp("UPDATE_TS").getTime(); - } - }); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - @Test - public void testNoTransientPropertiesInLocalView() throws Exception { - View view = cont.metadata().getViewRepository().getView(EntitySnapshot.class, View.LOCAL); - ViewProperty prop = view.getProperty("label"); - assertNull(prop); - } - - @Test - public void testViewCopy() throws Exception { - ViewRepository viewRepository = cont.metadata().getViewRepository(); - View view = viewRepository.getView(User.class, View.LOCAL); - view.addProperty("group", viewRepository.getView(Group.class, View.MINIMAL)); - - assertNotNull(view.getProperty("group")); - assertNull(viewRepository.getView(User.class, View.LOCAL).getProperty("group")); - } - - @Test - public void testFetchGroupIsAbsentIfViewIsFull() throws Exception { - ViewRepository viewRepository = cont.metadata().getViewRepository(); - View view = viewRepository.getView(User.class, View.LOCAL); - view.addProperty("group", new View(Group.class) - .addProperty("name")) - .addProperty("userRoles", new View(UserRole.class) - .addProperty("role", new View(Role.class) - .addProperty("name"))) - .addProperty("substitutions", new View(UserSubstitution.class) - .addProperty("startDate") - .addProperty("substitutedUser", new View(User.class) - .addProperty("login") - .addProperty("name"))); - - User u; - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - u = em.find(User.class, userId, view); - tx.commit(); - } - assertNotNull(u); - assertTrue(PersistenceHelper.isLoaded(u, "login")); - assertTrue(PersistenceHelper.isLoaded(u, "group")); - assertTrue(PersistenceHelper.isLoaded(u, "userRoles")); - assertTrue(PersistenceHelper.isLoaded(u, "substitutions")); - - assertTrue(u instanceof FetchGroupTracker); - assertNull(((FetchGroupTracker) u)._persistence_getFetchGroup()); - } - - @Test - public void testSelfReferenceInView() { - ViewRepository viewRepository = cont.metadata().getViewRepository(); - View view = viewRepository.getView(RootEntity.class, View.LOCAL); - view.addProperty("entity", new View(ChildEntity.class) - .addProperty("name").addProperty("description"), FetchMode.AUTO); - RootEntity e; - try (Transaction tx = cont.persistence().createTransaction()) { - EntityManager em = cont.persistence().getEntityManager(); - e = em.find(RootEntity.class, rootEntity.getId(), view); - tx.commit(); - } - assertNotNull(e); - assertNotNull(e.getEntity()); - assertEquals("rootEntityDescription", e.getDescription()); - assertEquals("childEntityDescription", e.getEntity().getDescription()); - assertEquals("childEntityName", e.getEntity().getName()); - } - - @Test - public void testNestedCollectionInJoinedInheritance() throws Exception { - View childEntityView = new View(ChildEntity.class, false) - .addProperty("description") - .addProperty("name") - .addProperty("details", new View(RootEntityDetail.class, false) - .addProperty("info")); - childEntityView.setLoadPartialEntities(true); - - ChildEntity loaded; - try (Transaction tx = persistence.createTransaction()) { - EntityManager em = persistence.getEntityManager(); - TypedQuery query = em.createQuery("select e from test$ChildEntity e where e.id = ?1", ChildEntity.class); - query.setParameter(1, childEntity.getId()); - query.setView(childEntityView); - loaded = query.getSingleResult(); - tx.commit(); - } - assertEquals(childEntity, loaded); - assertNotNull(loaded.getDetails()); - assertEquals(2, loaded.getDetails().size()); - } - - @Test - public void testMultiLinkInEntity() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - View linkView = new View(LinkEntity.class).addProperty("name"); - View view = new View(MultiLinkEntity.class) - .addProperty("a", linkView) - .addProperty("b", linkView) - .addProperty("c", linkView) - .setLoadPartialEntities(true); - - MultiLinkEntity reloadEntity = em.find(MultiLinkEntity.class, multiLinkEntity.getId(), view); - - tx.commit(); - reloadEntity = reserialize(reloadEntity); - assertEquals("A", reloadEntity.getA().getName()); - assertEquals("B", reloadEntity.getB().getName()); - assertEquals("C", reloadEntity.getC().getName()); - } finally { - tx.end(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.bali.db.ResultSetHandler; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.testmodel.multiplelinks.LinkEntity; +import com.haulmont.cuba.testmodel.multiplelinks.MultiLinkEntity; +import com.haulmont.cuba.testmodel.selfinherited.ChildEntity; +import com.haulmont.cuba.testmodel.selfinherited.RootEntity; +import com.haulmont.cuba.testmodel.selfinherited.RootEntityDetail; +import com.haulmont.cuba.testsupport.TestContainer; +import org.eclipse.persistence.queries.FetchGroupTracker; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Date; +import java.util.UUID; + +import static com.haulmont.cuba.testsupport.TestSupport.assertFail; +import static com.haulmont.cuba.testsupport.TestSupport.reserialize; +import static org.junit.Assert.*; + +public class ViewTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private TimeSource timeSource; + + private UUID userId; + private RootEntity rootEntity; + private ChildEntity childEntity; + private MultiLinkEntity multiLinkEntity; + private LinkEntity linkEntity1, linkEntity2, linkEntity3; + private Persistence persistence; + private Metadata metadata; + + @Before + public void setUp() throws Exception { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.getLogger("com.haulmont.cuba.core.sys.FetchGroupManager").setLevel(Level.TRACE); + + persistence = cont.persistence(); + metadata = cont.metadata(); + timeSource = AppBeans.get(TimeSource.NAME); + + Transaction tx = persistence.createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); + + User user = new User(); + userId = user.getId(); + user.setName("testUser"); + user.setLogin("login" + userId); + user.setPassword("000"); + user.setGroup(group); + em.persist(user); + + childEntity = metadata.create(ChildEntity.class); + childEntity.setName("childEntityName"); + childEntity.setDescription("childEntityDescription"); + em.persist(childEntity); + + rootEntity = metadata.create(RootEntity.class); + rootEntity.setDescription("rootEntityDescription"); + rootEntity.setEntity(childEntity); + em.persist(rootEntity); + + RootEntityDetail detail1 = metadata.create(RootEntityDetail.class); + detail1.setInfo("detail1"); + detail1.setMaster(childEntity); + em.persist(detail1); + + RootEntityDetail detail2 = metadata.create(RootEntityDetail.class); + detail2.setInfo("detail2"); + detail2.setMaster(childEntity); + em.persist(detail2); + + linkEntity1 = metadata.create(LinkEntity.class); + linkEntity1.setName("A"); + em.persist(linkEntity1); + + linkEntity2 = metadata.create(LinkEntity.class); + linkEntity2.setName("B"); + em.persist(linkEntity2); + + linkEntity3 = metadata.create(LinkEntity.class); + linkEntity3.setName("C"); + em.persist(linkEntity3); + + multiLinkEntity = metadata.create(MultiLinkEntity.class); + multiLinkEntity.setA(linkEntity1); + multiLinkEntity.setB(linkEntity2); + multiLinkEntity.setC(linkEntity3); + em.persist(multiLinkEntity); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.getLogger("com.haulmont.cuba.core.sys.FetchGroupManager").setLevel(Level.DEBUG); + + cont.deleteRecord("SEC_USER", userId); + cont.deleteRecord("TEST_ROOT_ENTITY_DETAIL"); + cont.deleteRecord("TEST_CHILD_ENTITY"); + cont.deleteRecord("TEST_ROOT_ENTITY"); + cont.deleteRecord("TEST_MULTI_LINK_ENTITY"); + cont.deleteRecord("TEST_LINK_ENTITY"); + } + + @Test + public void testQuery() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Query q = em.createQuery("select u from sec$User u where u.id = ?1"); + q.setParameter(1, userId); + + View view = new View(User.class) + .addProperty("name") + .addProperty("login") + .addProperty("group", + new View(Group.class) + .addProperty("name") + ) + .setLoadPartialEntities(true); + q.setView(view); + + User user = (User) q.getSingleResult(); + + tx.commit(); + user = reserialize(user); + + try { + user.getPassword(); + fail(); + } catch (Exception ignored) { + } + assertNotNull(user.getGroup().getName()); + } finally { + tx.end(); + } + } + + @Test + public void testEntityManager() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + View view = new View(User.class) + .addProperty("name") + .addProperty("login") + .addProperty("group", + new View(Group.class) + .addProperty("name") + ).setLoadPartialEntities(true); + + User user = em.find(User.class, userId, view); + + tx.commit(); + user = reserialize(user); + + try { + user.getPassword(); + fail(); + } catch (Exception ignored) { + } + assertNotNull(user.getGroup().getName()); + assertNotNull(user.getCreateTs()); + assertNotNull(user.getGroup().getCreateTs()); + } finally { + tx.end(); + } + } + + @Test + public void testViewWithoutSystemProperties() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + View view = new View(User.class, false) + .addProperty("name") + .addProperty("login") + .addProperty("group", + new View(Group.class, false) + .addProperty("name") + ).setLoadPartialEntities(true); + + User user = em.find(User.class, userId, view); + + tx.commit(); + user = reserialize(user); + + try { + user.getPassword(); + fail(); + } catch (Exception ignored) { + } + try { + user.getCreateTs(); + fail(); + } catch (Exception ignored) { + } + assertNotNull(user.getGroup().getName()); + try { + user.getGroup().getCreateTs(); + fail(); + } catch (Exception ignored) { + } + } finally { + tx.end(); + } + } + + @Test + public void testViewWithoutSystemProperties_update() throws Exception { + + View view = new View(User.class, false) + .addProperty("name") + .addProperty("login") + .addProperty("loginLowerCase") + .addProperty("group", + new View(Group.class, false) + .addProperty("name") + ); + view.setLoadPartialEntities(true); + + try (Transaction tx = cont.persistence().createTransaction()) { + // First stage: change managed + + long ts = timeSource.currentTimeMillis(); + Thread.sleep(200); + + EntityManager em = cont.persistence().getEntityManager(); + User user = em.find(User.class, userId, view); + + assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); + + user.setName(new Date().toString()); + + tx.commitRetaining(); + + assertTrue(getCurrentUpdateTs() > ts); + + // Second stage: change detached + + ts = timeSource.currentTimeMillis(); + Thread.sleep(1000); + + em = cont.persistence().getEntityManager(); + user = em.find(User.class, userId, view); + + tx.commitRetaining(); + + assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); + + user.setName(new Date().toString()); + em = cont.persistence().getEntityManager(); + em.merge(user); + + tx.commit(); + + assertTrue(getCurrentUpdateTs() > ts); + } + + // test _minimal + try (Transaction tx = cont.persistence().createTransaction()) { + long ts = timeSource.currentTimeMillis(); + Thread.sleep(1000); + + View minimalView = cont.metadata().getViewRepository().getView(User.class, View.MINIMAL); + minimalView.setLoadPartialEntities(true); + + EntityManager em = cont.persistence().getEntityManager(); + User user = em.find(User.class, userId, minimalView); + + tx.commitRetaining(); + + assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); + + user.setName(new Date().toString()); + em = cont.persistence().getEntityManager(); + em.merge(user); + + tx.commit(); + + assertTrue(getCurrentUpdateTs() > ts); + + tx.commit(); + } + + // test DataManager + long ts = timeSource.currentTimeMillis(); + Thread.sleep(1000); + + DataManager dataManager = AppBeans.get(DataManager.class).secure(); + User user = dataManager.load(LoadContext.create(User.class).setId(userId).setView(view)); + + assertFalse(PersistenceHelper.isLoaded(user, "updateTs")); + + user.setName(new Date().toString()); + dataManager.commit(user); + + assertTrue(getCurrentUpdateTs() > ts); + } + + /* + * Pre 6.0: Test that entity which is loaded with view, can lazily fetch not-loaded attributes until transaction ends. + * + * 6.0: Not loaded (unfetched) attributes cannot be loaded lazily. Otherwise, previously loaded reference attributes are lost. + */ + @Test + public void testLazyLoadAfterLoadWithView() throws Exception { + View view = new View(User.class, false) + .addProperty("name") + .addProperty("group", new View(Group.class) + .addProperty("name")) + .setLoadPartialEntities(true); + + User user; + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + user = em.find(User.class, userId, view); + tx.commit(); + } finally { + tx.end(); + } + + user = reserialize(user); + assertNotNull(user.getGroup().getName()); + + // login is not loaded after transaction is finished + try { + user.getLogin(); + fail(); + } catch (Exception ignored) { + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + user = em.find(User.class, userId, view); + assertNotNull(user); + + // field is loaded lazily but the object becomes not partial and references loaded by previous view are cleared + user.getLogin(); + + tx.commit(); + } finally { + tx.end(); + } + user = reserialize(user); + assertFail(user::getGroup); + } + + + @Test + public void testLazyProperty() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Query q = em.createQuery("select u from sec$User u where u.id = ?1"); + q.setParameter(1, userId); + + View userRoleView = new View(UserRole.class).addProperty("role", new View(Role.class).addProperty("name")); + View view = new View(User.class) + .addProperty("name") + .addProperty("login") + .addProperty("userRoles", userRoleView, true) + .addProperty("group", + new View(Group.class) + .addProperty("name") + ).setLoadPartialEntities(true); + q.setView(view); + + User user = (User) q.getSingleResult(); + + tx.commit(); + user = reserialize(user); + + user.getUserRoles().size(); + + try { + user.getPassword(); + fail(); + } catch (Exception ignored) { + } + assertNotNull(user.getGroup().getName()); + } finally { + tx.end(); + } + } + + private long getCurrentUpdateTs() { + String sql = "select UPDATE_TS from SEC_USER where ID = '" + userId.toString() + "'"; + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + try { + return runner.query(sql, new ResultSetHandler() { + @Override + public Long handle(ResultSet rs) throws SQLException { + rs.next(); + return rs.getTimestamp("UPDATE_TS").getTime(); + } + }); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Test + public void testNoTransientPropertiesInLocalView() throws Exception { + View view = cont.metadata().getViewRepository().getView(EntitySnapshot.class, View.LOCAL); + ViewProperty prop = view.getProperty("label"); + assertNull(prop); + } + + @Test + public void testViewCopy() throws Exception { + ViewRepository viewRepository = cont.metadata().getViewRepository(); + View view = viewRepository.getView(User.class, View.LOCAL); + view.addProperty("group", viewRepository.getView(Group.class, View.MINIMAL)); + + assertNotNull(view.getProperty("group")); + assertNull(viewRepository.getView(User.class, View.LOCAL).getProperty("group")); + } + + @Test + public void testFetchGroupIsAbsentIfViewIsFull() throws Exception { + ViewRepository viewRepository = cont.metadata().getViewRepository(); + View view = viewRepository.getView(User.class, View.LOCAL); + view.addProperty("group", new View(Group.class) + .addProperty("name")) + .addProperty("userRoles", new View(UserRole.class) + .addProperty("role", new View(Role.class) + .addProperty("name"))) + .addProperty("substitutions", new View(UserSubstitution.class) + .addProperty("startDate") + .addProperty("substitutedUser", new View(User.class) + .addProperty("login") + .addProperty("name"))); + + User u; + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + u = em.find(User.class, userId, view); + tx.commit(); + } + assertNotNull(u); + assertTrue(PersistenceHelper.isLoaded(u, "login")); + assertTrue(PersistenceHelper.isLoaded(u, "group")); + assertTrue(PersistenceHelper.isLoaded(u, "userRoles")); + assertTrue(PersistenceHelper.isLoaded(u, "substitutions")); + + assertTrue(u instanceof FetchGroupTracker); + assertNull(((FetchGroupTracker) u)._persistence_getFetchGroup()); + } + + @Test + public void testSelfReferenceInView() { + ViewRepository viewRepository = cont.metadata().getViewRepository(); + View view = viewRepository.getView(RootEntity.class, View.LOCAL); + view.addProperty("entity", new View(ChildEntity.class) + .addProperty("name").addProperty("description"), FetchMode.AUTO); + RootEntity e; + try (Transaction tx = cont.persistence().createTransaction()) { + EntityManager em = cont.persistence().getEntityManager(); + e = em.find(RootEntity.class, rootEntity.getId(), view); + tx.commit(); + } + assertNotNull(e); + assertNotNull(e.getEntity()); + assertEquals("rootEntityDescription", e.getDescription()); + assertEquals("childEntityDescription", e.getEntity().getDescription()); + assertEquals("childEntityName", e.getEntity().getName()); + } + + @Test + public void testNestedCollectionInJoinedInheritance() throws Exception { + View childEntityView = new View(ChildEntity.class, false) + .addProperty("description") + .addProperty("name") + .addProperty("details", new View(RootEntityDetail.class, false) + .addProperty("info")); + childEntityView.setLoadPartialEntities(true); + + ChildEntity loaded; + try (Transaction tx = persistence.createTransaction()) { + EntityManager em = persistence.getEntityManager(); + TypedQuery query = em.createQuery("select e from test$ChildEntity e where e.id = ?1", ChildEntity.class); + query.setParameter(1, childEntity.getId()); + query.setView(childEntityView); + loaded = query.getSingleResult(); + tx.commit(); + } + assertEquals(childEntity, loaded); + assertNotNull(loaded.getDetails()); + assertEquals(2, loaded.getDetails().size()); + } + + @Test + public void testMultiLinkInEntity() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + View linkView = new View(LinkEntity.class).addProperty("name"); + View view = new View(MultiLinkEntity.class) + .addProperty("a", linkView) + .addProperty("b", linkView) + .addProperty("c", linkView) + .setLoadPartialEntities(true); + + MultiLinkEntity reloadEntity = em.find(MultiLinkEntity.class, multiLinkEntity.getId(), view); + + tx.commit(); + reloadEntity = reserialize(reloadEntity); + assertEquals("A", reloadEntity.getA().getName()); + assertEquals("B", reloadEntity.getB().getName()); + assertEquals("C", reloadEntity.getC().getName()); + } finally { + tx.end(); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/app/EmailerTest.java b/modules/core/test/com/haulmont/cuba/core/app/EmailerTest.java index 5954ce9b15..07e5bc148f 100644 --- a/modules/core/test/com/haulmont/cuba/core/app/EmailerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/app/EmailerTest.java @@ -1,649 +1,649 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.google.common.collect.Lists; -import com.haulmont.cuba.core.entity.SendingAttachment; -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.CubaMailSender; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestMailSender; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import javax.mail.Address; -import javax.mail.MessagingException; -import javax.mail.Part; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.*; - -import static org.junit.Assert.*; - -public class EmailerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private EmailerAPI emailer; - private TestMailSender testMailSender; - private TimeSource timeSource; - private DataManager dataManager; - - private EmailerConfig emailerConfig; - - @Before - public void setUp() throws Exception { - emailer = AppBeans.get(EmailerAPI.NAME); - testMailSender = AppBeans.get(CubaMailSender.NAME); - timeSource = AppBeans.get(TimeSource.NAME); - dataManager = AppBeans.get(DataManager.class); - - emailerConfig = AppBeans.get(Configuration.class).getConfig(EmailerConfig.class); - emailerConfig.setDelayCallCount(0); - - // send pending emails which might be in the queue - emailer.processQueuedEmails(); - testMailSender.clearBuffer(); - } - - @Test - public void testSynchronous() throws Exception { - doTestSynchronous(false); - } - - @Test - public void testSynchronousFS() throws Exception { - doTestSynchronous(true); - } - - /* - * Test single recipient, text body, subject. - */ - private void doTestSynchronous(boolean useFs) throws Exception { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - EmailInfo myInfo = new EmailInfo("testemail@example.com", "Test Email", "Test Body"); - emailer.sendEmail(myInfo); - - assertEquals(1, testMailSender.getBufferSize()); - MimeMessage msg = testMailSender.fetchSentEmail(); - - assertEquals(1, msg.getAllRecipients().length); - assertEquals("testemail@example.com", msg.getAllRecipients()[0].toString()); - - assertEquals("Test Email", msg.getSubject()); - assertEquals("Test Body", getBody(msg)); - assertTrue(getBodyContentType(msg).startsWith("text/plain;")); - } - - /* - * Test sendEmail() with parameter list. - */ - @Test - public void testSimpleParamList() throws Exception { - testMailSender.clearBuffer(); - - emailer.sendEmail("myemail@example.com", "Test Email", "Test Body 2"); - - assertEquals(1, testMailSender.getBufferSize()); - MimeMessage msg = testMailSender.fetchSentEmail(); - - assertEquals(1, msg.getAllRecipients().length); - assertEquals("myemail@example.com", msg.getAllRecipients()[0].toString()); - - assertEquals("Test Email", msg.getSubject()); - assertEquals("Test Body 2", getBody(msg)); - assertTrue(getBodyContentType(msg).startsWith("text/plain;")); - } - - @Test - public void testAsynchronous() throws Exception { - doTestAsynchronous(false); - } - - @Test - public void testAsynchronousFS() throws Exception { - doTestAsynchronous(true); - } - - private void doTestAsynchronous(boolean useFs) throws Exception { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - String body = "Test Email Body"; - EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); - List messages = emailer.sendEmailAsync(myInfo); - assertEquals(1, messages.size()); - - // not sent yet - assertTrue(testMailSender.isEmpty()); - SendingMessage sendingMsg = reload(messages.get(0)); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - // run scheduler - emailer.processQueuedEmails(); - - // check - assertEquals(1, testMailSender.getBufferSize()); - MimeMessage msg = testMailSender.fetchSentEmail(); - - assertEquals(1, msg.getAllRecipients().length); - assertEquals("recipient@example.com", msg.getAllRecipients()[0].toString()); - - assertEquals("Test", msg.getSubject()); - assertEquals(body, getBody(msg)); - assertTrue(getBodyContentType(msg).startsWith("text/plain;")); - - sendingMsg = reload(messages.get(0)); - assertEquals(SendingStatus.SENT, sendingMsg.getStatus()); - } - - @Test - public void testHtmlContent() throws Exception { - testMailSender.clearBuffer(); - - String body = "Hi"; - EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); - emailer.sendEmail(myInfo); - - assertEquals(1, testMailSender.getBufferSize()); - MimeMessage msg = testMailSender.fetchSentEmail(); - - assertTrue(getBodyContentType(msg).startsWith("text/html;")); - } - - @Test - public void testImplicitFromAddress() throws Exception { - EmailInfo myInfo; - - // synchronous - emailerConfig.setFromAddress("implicit@example.com"); - myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); - emailer.sendEmail(myInfo); - assertEquals("implicit@example.com", testMailSender.fetchSentEmail().getFrom()[0].toString()); - - // asynchronous - emailerConfig.setFromAddress("implicit2@example.com"); - myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); - emailer.sendEmailAsync(myInfo); - - emailer.processQueuedEmails(); - assertEquals("implicit2@example.com", testMailSender.fetchSentEmail().getFrom()[0].toString()); - } - - @Test - public void testExplicitFromAddress() throws Exception { - EmailInfo myInfo; - MimeMessage msg; - - // synchronous - myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); - myInfo.setFrom("explicit@example.com"); - emailer.sendEmail(myInfo); - msg = testMailSender.fetchSentEmail(); - assertEquals("explicit@example.com", msg.getFrom()[0].toString()); - - // asynchronous - myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); - myInfo.setFrom("explicit2@example.com"); - emailer.sendEmailAsync(myInfo); - - emailer.processQueuedEmails(); - msg = testMailSender.fetchSentEmail(); - assertEquals("explicit2@example.com", msg.getFrom()[0].toString()); - } - - @Test - public void testSynchronousFail() throws Exception { - testMailSender.clearBuffer(); - - testMailSender.failPlease(); - try { - emailer.sendEmail("myemail@example.com", "Test Email", "Test Body 2"); - fail("Must fail with EmailException"); - } catch (EmailException e) { - assertEquals(1, e.getFailedAddresses().size()); - assertEquals("myemail@example.com", e.getFailedAddresses().get(0)); - assertTrue(testMailSender.isEmpty()); - } finally { - testMailSender.workNormallyPlease(); - } - } - - @Test - public void testAsynchronousAttemptLimit() throws Exception { - testMailSender.clearBuffer(); - - String body = "Test Email Body"; - EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); - List messages = emailer.sendEmailAsync(myInfo, 2, getDeadlineWhichDoesntMatter()); - assertEquals(1, messages.size()); - - // not sent yet - assertTrue(testMailSender.isEmpty()); - SendingMessage sendingMsg = reload(messages.get(0)); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - // will fail - testMailSender.failPlease(); - try { - // try once - emailer.processQueuedEmails(); - sendingMsg = reload(sendingMsg); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - // try second time - emailer.processQueuedEmails(); - sendingMsg = reload(sendingMsg); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - } finally { - testMailSender.workNormallyPlease(); - } - - // marks as not-sent in the next tick - emailer.processQueuedEmails(); - sendingMsg = reload(sendingMsg); - assertEquals(SendingStatus.NOTSENT, sendingMsg.getStatus()); - assertEquals(2, sendingMsg.getAttemptsCount().intValue()); - } - - @Test - public void testSentFromSecondAttempt() throws Exception { - doTestSentFromSecondAttempt(false); - } - - @Test - public void testSentFromSecondAttemptFS() throws Exception { - doTestSentFromSecondAttempt(true); - } - - private void doTestSentFromSecondAttempt(boolean useFs) { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - String body = "Test Email Body"; - EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); - List messages = emailer.sendEmailAsync(myInfo, 2, getDeadlineWhichDoesntMatter()); - assertEquals(1, messages.size()); - - // not sent yet - assertTrue(testMailSender.isEmpty()); - SendingMessage sendingMsg = reload(messages.get(0)); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - // will fail - testMailSender.failPlease(); - try { - // try once - emailer.processQueuedEmails(); - sendingMsg = reload(sendingMsg); - assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); - - } finally { - testMailSender.workNormallyPlease(); - } - - // success now - emailer.processQueuedEmails(); - sendingMsg = reload(sendingMsg); - assertEquals(SendingStatus.SENT, sendingMsg.getStatus()); - assertEquals(2, sendingMsg.getAttemptsCount().intValue()); - } - - @Test - public void testSeveralRecipients() throws Exception { - doTestSeveralRecipients(false); - } - - @Test - public void testSeveralRecipientsFS() throws Exception { - doTestSeveralRecipients(true); - } - - private void doTestSeveralRecipients(boolean useFs) throws MessagingException { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - String body = "Test Email Body"; - String recipients = "misha@example.com,kolya@example.com;tanya@example.com;"; // 3 recipients - EmailInfo myInfo = new EmailInfo(recipients, "Test", body); - List messages = emailer.sendEmailAsync(myInfo); - assertEquals(3, messages.size()); - - assertTrue(testMailSender.isEmpty()); - emailer.processQueuedEmails(); - - Set recipientSet = new HashSet<>(); - // check - assertEquals(3, testMailSender.getBufferSize()); - for (int i = 0; i < 3; i++) { - MimeMessage msg = testMailSender.fetchSentEmail(); - Address[] msgRecipients = msg.getAllRecipients(); - assertEquals(1, msgRecipients.length); - recipientSet.add(msgRecipients[0].toString()); - } - - assertTrue(recipientSet.contains("misha@example.com")); - assertTrue(recipientSet.contains("kolya@example.com")); - assertTrue(recipientSet.contains("tanya@example.com")); - } - - @Test - public void testSendAllToAdmin() throws Exception { - emailerConfig.setSendAllToAdmin(true); - emailerConfig.setAdminAddress("admin@example.com"); - try { - emailer.sendEmail("michael@example.com", "Test Email 5", "Test Body 5"); - - emailer.sendEmailAsync(new EmailInfo("nikolay@example.com", "Test Email 6", "Test Body 6")); - emailer.processQueuedEmails(); - - for (int i = 0; i < 2; i++) { - MimeMessage msg = testMailSender.fetchSentEmail(); - assertEquals(1, msg.getAllRecipients().length); - assertEquals("admin@example.com", msg.getAllRecipients()[0].toString()); - } - - } finally { - emailerConfig.setSendAllToAdmin(false); - } - } - - @Test - public void testEmailTemplate() throws Exception { - testMailSender.clearBuffer(); - - String templateFileName = "/com/haulmont/cuba/core/app/testEmailTemplate.ftl"; - - Map params = new HashMap<>(); - params.put("userName", "Bob"); - params.put("dateParam", new SimpleDateFormat("dd/MM/yyyy").parse("01/05/2013")); - - EmailInfo info = new EmailInfo("bob@example.com", "Test", null, templateFileName, params); - emailer.sendEmailAsync(info); - emailer.processQueuedEmails(); - - String body = getBody(testMailSender.fetchSentEmail()); - assertEquals("Greetings, Bob! 01-05-2013", body.trim()); - } - - @Test - public void testTextAttachment() throws Exception { - doTestTextAttachment(false); - } - - @Test - public void testTextAttachmentFS() throws Exception { - doTestTextAttachment(true); - } - - private void doTestTextAttachment(boolean useFs) throws IOException, MessagingException { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - String attachmentText = "Test Attachment Text"; - EmailAttachment textAttach = EmailAttachment.createTextAttachment(attachmentText, "ISO-8859-1", "test.txt"); - - EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", textAttach); - emailer.sendEmailAsync(myInfo); - - emailer.processQueuedEmails(); - - MimeMessage msg = testMailSender.fetchSentEmail(); - MimeBodyPart firstAttachment = getFirstAttachment(msg); - - // check content bytes - Object content = firstAttachment.getContent(); - assertTrue(content instanceof InputStream); - byte[] data = IOUtils.toByteArray((InputStream) content); - assertEquals(attachmentText, new String(data, "ISO-8859-1")); - - // disposition - assertEquals(Part.ATTACHMENT, firstAttachment.getDisposition()); - - // charset header - String contentType = firstAttachment.getContentType(); - assertTrue(contentType.toLowerCase().contains("charset=iso-8859-1")); - } - - @Test - public void testInlineImage() throws Exception { - doTestInlineImage(false); - } - - @Test - public void testInlineImageFS() throws Exception { - doTestInlineImage(true); - } - - private void doTestInlineImage(boolean useFs) throws IOException, MessagingException { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - byte[] imageBytes = new byte[]{1, 2, 3, 4, 5}; - String fileName = "logo.png"; - EmailAttachment imageAttach = new EmailAttachment(imageBytes, fileName, "logo"); - - EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", imageAttach); - emailer.sendEmailAsync(myInfo); - - emailer.processQueuedEmails(); - - MimeMessage msg = testMailSender.fetchSentEmail(); - MimeBodyPart attachment = getInlineAttachment(msg); - - // check content bytes - InputStream content = (InputStream) attachment.getContent(); - byte[] data = IOUtils.toByteArray(content); - assertByteArrayEquals(imageBytes, data); - - // disposition - assertEquals(Part.INLINE, attachment.getDisposition()); - - // mime type - String contentType = attachment.getContentType(); - assertTrue(contentType.contains("image/png")); - } - - @Test - public void testPdfAttachment() throws Exception { - doTestPdfAttachment(false); - } - - @Test - public void testPdfAttachmentFS() throws Exception { - doTestPdfAttachment(true); - } - - private void doTestPdfAttachment(boolean useFs) throws IOException, MessagingException { - emailerConfig.setFileStorageUsed(useFs); - testMailSender.clearBuffer(); - - byte[] pdfBytes = new byte[]{1, 2, 3, 4, 6}; - String fileName = "invoice.pdf"; - EmailAttachment pdfAttach = new EmailAttachment(pdfBytes, fileName); - - EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", pdfAttach); - emailer.sendEmailAsync(myInfo); - - emailer.processQueuedEmails(); - - MimeMessage msg = testMailSender.fetchSentEmail(); - MimeBodyPart attachment = getFirstAttachment(msg); - - // check content bytes - InputStream content = (InputStream) attachment.getContent(); - byte[] data = IOUtils.toByteArray(content); - assertByteArrayEquals(pdfBytes, data); - - // disposition - assertEquals(Part.ATTACHMENT, attachment.getDisposition()); - - // mime type - String contentType = attachment.getContentType(); - assertTrue(contentType.contains("application/pdf")); - } - - @Test - public void testLoadBody() throws Exception { - doTestLoadBody(false); - } - - @Test - public void testLoadBodyFS() throws Exception { - doTestLoadBody(true); - } - - private void doTestLoadBody(boolean useFs) throws Exception { - emailerConfig.setFileStorageUsed(useFs); - - String body = "Hi! This is test email. Bye."; - EmailInfo emailInfo = new EmailInfo("test@example.com", "Test", body); - List messages = emailer.sendEmailAsync(emailInfo); - - SendingMessage msg = reload(messages.get(0)); - - String actualBody = emailer.loadContentText(msg); - assertEquals(body, actualBody); - } - - @Test - public void testMigration() throws Exception { - emailerConfig.setFileStorageUsed(false); - - byte[] expectedBytes = new byte[]{1, 2, 3, 4, 6}; - EmailAttachment fileAttachment = new EmailAttachment(expectedBytes, "invoice.pdf"); - - String body = "Hi! This is test email. Bye."; - EmailInfo emailInfo = new EmailInfo("test@example.com", "Test", body); - emailInfo.setAttachments(new EmailAttachment[]{fileAttachment}); - - List messages = emailer.sendEmailAsync(emailInfo); - SendingMessage msg; - SendingAttachment attachment; - - // check DB storage - msg = reload(messages.get(0), "sendingMessage.loadFromQueue"); - attachment = msg.getAttachments().get(0); - - assertNotNull(msg.getContentText()); - assertNull(msg.getContentTextFile()); - assertNotNull(attachment.getContent()); - assertNull(attachment.getContentFile()); - - emailer.migrateEmailsToFileStorage(Lists.newArrayList(msg)); - emailer.migrateAttachmentsToFileStorage(Lists.newArrayList(attachment)); - - // check file storage - msg = reload(msg, "sendingMessage.loadFromQueue"); - attachment = msg.getAttachments().get(0); - - assertNull(msg.getContentText()); - assertNotNull(msg.getContentTextFile()); - assertEquals(body, emailer.loadContentText(msg)); - - assertNull(attachment.getContent()); - assertNotNull(attachment.getContentFile()); - FileStorageAPI fileStorage = AppBeans.get(FileStorageAPI.NAME); - byte[] actualBytes = fileStorage.loadFile(attachment.getContentFile()); - assertByteArrayEquals(expectedBytes, actualBytes); - } - - /* Utility */ - private Date getDeadlineWhichDoesntMatter() { - return DateUtils.addHours(timeSource.currentTimestamp(), 2); - } - - private String getBody(MimeMessage msg) throws Exception { - MimeBodyPart textPart = getTextPart(msg); - return (String) textPart.getContent(); - } - - private String getBodyContentType(MimeMessage msg) throws Exception { - MimeBodyPart textPart = getTextPart(msg); - return textPart.getContentType(); - } - - private MimeBodyPart getTextPart(MimeMessage msg) throws IOException, MessagingException { - assertTrue(msg.getContent() instanceof MimeMultipart); - MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); - - Object content2 = mimeMultipart.getBodyPart(0).getContent(); - assertTrue(content2 instanceof MimeMultipart); - MimeMultipart textBodyPart = (MimeMultipart) content2; - - return (MimeBodyPart) textBodyPart.getBodyPart(0); - } - - private MimeBodyPart getFirstAttachment(MimeMessage msg) throws IOException, MessagingException { - assertTrue(msg.getContent() instanceof MimeMultipart); - MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); - return (MimeBodyPart) mimeMultipart.getBodyPart(1); - } - - private MimeBodyPart getInlineAttachment(MimeMessage msg) throws IOException, MessagingException { - assertTrue(msg.getContent() instanceof MimeMultipart); - MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); - - Object content2 = mimeMultipart.getBodyPart(0).getContent(); - assertTrue(content2 instanceof MimeMultipart); - MimeMultipart textBodyPart = (MimeMultipart) content2; - - return (MimeBodyPart) textBodyPart.getBodyPart(1); - } - - private SendingMessage reload(SendingMessage sendingMessage) { - return reload(sendingMessage, null); - } - - private SendingMessage reload(SendingMessage sendingMessage, String viewName) { - LoadContext loadContext = LoadContext.create(SendingMessage.class).setId(sendingMessage.getId()); - if (viewName != null) - loadContext.setView(viewName); - - return dataManager.load(loadContext); - -// Transaction tx = cont.persistence().createTransaction(); -// try { -// sendingMessage = cont.persistence().getEntityManager().reload(sendingMessage, viewNames); -// tx.commit(); -// } finally { -// tx.end(); -// } -// return sendingMessage; - } - - private void assertByteArrayEquals(byte[] expected, byte[] actual) { - assertEquals(expected.length, actual.length); - for (int i = 0; i < expected.length; i++) { - assertEquals(expected[i], actual[i]); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.google.common.collect.Lists; +import com.haulmont.cuba.core.entity.SendingAttachment; +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.CubaMailSender; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestMailSender; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import javax.mail.Address; +import javax.mail.MessagingException; +import javax.mail.Part; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.*; + +import static org.junit.Assert.*; + +public class EmailerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private EmailerAPI emailer; + private TestMailSender testMailSender; + private TimeSource timeSource; + private DataManager dataManager; + + private EmailerConfig emailerConfig; + + @Before + public void setUp() throws Exception { + emailer = AppBeans.get(EmailerAPI.NAME); + testMailSender = AppBeans.get(CubaMailSender.NAME); + timeSource = AppBeans.get(TimeSource.NAME); + dataManager = AppBeans.get(DataManager.class); + + emailerConfig = AppBeans.get(Configuration.class).getConfig(EmailerConfig.class); + emailerConfig.setDelayCallCount(0); + + // send pending emails which might be in the queue + emailer.processQueuedEmails(); + testMailSender.clearBuffer(); + } + + @Test + public void testSynchronous() throws Exception { + doTestSynchronous(false); + } + + @Test + public void testSynchronousFS() throws Exception { + doTestSynchronous(true); + } + + /* + * Test single recipient, text body, subject. + */ + private void doTestSynchronous(boolean useFs) throws Exception { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + EmailInfo myInfo = new EmailInfo("testemail@example.com", "Test Email", "Test Body"); + emailer.sendEmail(myInfo); + + assertEquals(1, testMailSender.getBufferSize()); + MimeMessage msg = testMailSender.fetchSentEmail(); + + assertEquals(1, msg.getAllRecipients().length); + assertEquals("testemail@example.com", msg.getAllRecipients()[0].toString()); + + assertEquals("Test Email", msg.getSubject()); + assertEquals("Test Body", getBody(msg)); + assertTrue(getBodyContentType(msg).startsWith("text/plain;")); + } + + /* + * Test sendEmail() with parameter list. + */ + @Test + public void testSimpleParamList() throws Exception { + testMailSender.clearBuffer(); + + emailer.sendEmail("myemail@example.com", "Test Email", "Test Body 2"); + + assertEquals(1, testMailSender.getBufferSize()); + MimeMessage msg = testMailSender.fetchSentEmail(); + + assertEquals(1, msg.getAllRecipients().length); + assertEquals("myemail@example.com", msg.getAllRecipients()[0].toString()); + + assertEquals("Test Email", msg.getSubject()); + assertEquals("Test Body 2", getBody(msg)); + assertTrue(getBodyContentType(msg).startsWith("text/plain;")); + } + + @Test + public void testAsynchronous() throws Exception { + doTestAsynchronous(false); + } + + @Test + public void testAsynchronousFS() throws Exception { + doTestAsynchronous(true); + } + + private void doTestAsynchronous(boolean useFs) throws Exception { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + String body = "Test Email Body"; + EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); + List messages = emailer.sendEmailAsync(myInfo); + assertEquals(1, messages.size()); + + // not sent yet + assertTrue(testMailSender.isEmpty()); + SendingMessage sendingMsg = reload(messages.get(0)); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + // run scheduler + emailer.processQueuedEmails(); + + // check + assertEquals(1, testMailSender.getBufferSize()); + MimeMessage msg = testMailSender.fetchSentEmail(); + + assertEquals(1, msg.getAllRecipients().length); + assertEquals("recipient@example.com", msg.getAllRecipients()[0].toString()); + + assertEquals("Test", msg.getSubject()); + assertEquals(body, getBody(msg)); + assertTrue(getBodyContentType(msg).startsWith("text/plain;")); + + sendingMsg = reload(messages.get(0)); + assertEquals(SendingStatus.SENT, sendingMsg.getStatus()); + } + + @Test + public void testHtmlContent() throws Exception { + testMailSender.clearBuffer(); + + String body = "Hi"; + EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); + emailer.sendEmail(myInfo); + + assertEquals(1, testMailSender.getBufferSize()); + MimeMessage msg = testMailSender.fetchSentEmail(); + + assertTrue(getBodyContentType(msg).startsWith("text/html;")); + } + + @Test + public void testImplicitFromAddress() throws Exception { + EmailInfo myInfo; + + // synchronous + emailerConfig.setFromAddress("implicit@example.com"); + myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); + emailer.sendEmail(myInfo); + assertEquals("implicit@example.com", testMailSender.fetchSentEmail().getFrom()[0].toString()); + + // asynchronous + emailerConfig.setFromAddress("implicit2@example.com"); + myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); + emailer.sendEmailAsync(myInfo); + + emailer.processQueuedEmails(); + assertEquals("implicit2@example.com", testMailSender.fetchSentEmail().getFrom()[0].toString()); + } + + @Test + public void testExplicitFromAddress() throws Exception { + EmailInfo myInfo; + MimeMessage msg; + + // synchronous + myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); + myInfo.setFrom("explicit@example.com"); + emailer.sendEmail(myInfo); + msg = testMailSender.fetchSentEmail(); + assertEquals("explicit@example.com", msg.getFrom()[0].toString()); + + // asynchronous + myInfo = new EmailInfo("test@example.com", "Test Email", "Test Body"); + myInfo.setFrom("explicit2@example.com"); + emailer.sendEmailAsync(myInfo); + + emailer.processQueuedEmails(); + msg = testMailSender.fetchSentEmail(); + assertEquals("explicit2@example.com", msg.getFrom()[0].toString()); + } + + @Test + public void testSynchronousFail() throws Exception { + testMailSender.clearBuffer(); + + testMailSender.failPlease(); + try { + emailer.sendEmail("myemail@example.com", "Test Email", "Test Body 2"); + fail("Must fail with EmailException"); + } catch (EmailException e) { + assertEquals(1, e.getFailedAddresses().size()); + assertEquals("myemail@example.com", e.getFailedAddresses().get(0)); + assertTrue(testMailSender.isEmpty()); + } finally { + testMailSender.workNormallyPlease(); + } + } + + @Test + public void testAsynchronousAttemptLimit() throws Exception { + testMailSender.clearBuffer(); + + String body = "Test Email Body"; + EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); + List messages = emailer.sendEmailAsync(myInfo, 2, getDeadlineWhichDoesntMatter()); + assertEquals(1, messages.size()); + + // not sent yet + assertTrue(testMailSender.isEmpty()); + SendingMessage sendingMsg = reload(messages.get(0)); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + // will fail + testMailSender.failPlease(); + try { + // try once + emailer.processQueuedEmails(); + sendingMsg = reload(sendingMsg); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + // try second time + emailer.processQueuedEmails(); + sendingMsg = reload(sendingMsg); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + } finally { + testMailSender.workNormallyPlease(); + } + + // marks as not-sent in the next tick + emailer.processQueuedEmails(); + sendingMsg = reload(sendingMsg); + assertEquals(SendingStatus.NOTSENT, sendingMsg.getStatus()); + assertEquals(2, sendingMsg.getAttemptsCount().intValue()); + } + + @Test + public void testSentFromSecondAttempt() throws Exception { + doTestSentFromSecondAttempt(false); + } + + @Test + public void testSentFromSecondAttemptFS() throws Exception { + doTestSentFromSecondAttempt(true); + } + + private void doTestSentFromSecondAttempt(boolean useFs) { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + String body = "Test Email Body"; + EmailInfo myInfo = new EmailInfo("recipient@example.com", "Test", body); + List messages = emailer.sendEmailAsync(myInfo, 2, getDeadlineWhichDoesntMatter()); + assertEquals(1, messages.size()); + + // not sent yet + assertTrue(testMailSender.isEmpty()); + SendingMessage sendingMsg = reload(messages.get(0)); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + // will fail + testMailSender.failPlease(); + try { + // try once + emailer.processQueuedEmails(); + sendingMsg = reload(sendingMsg); + assertEquals(SendingStatus.QUEUE, sendingMsg.getStatus()); + + } finally { + testMailSender.workNormallyPlease(); + } + + // success now + emailer.processQueuedEmails(); + sendingMsg = reload(sendingMsg); + assertEquals(SendingStatus.SENT, sendingMsg.getStatus()); + assertEquals(2, sendingMsg.getAttemptsCount().intValue()); + } + + @Test + public void testSeveralRecipients() throws Exception { + doTestSeveralRecipients(false); + } + + @Test + public void testSeveralRecipientsFS() throws Exception { + doTestSeveralRecipients(true); + } + + private void doTestSeveralRecipients(boolean useFs) throws MessagingException { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + String body = "Test Email Body"; + String recipients = "misha@example.com,kolya@example.com;tanya@example.com;"; // 3 recipients + EmailInfo myInfo = new EmailInfo(recipients, "Test", body); + List messages = emailer.sendEmailAsync(myInfo); + assertEquals(3, messages.size()); + + assertTrue(testMailSender.isEmpty()); + emailer.processQueuedEmails(); + + Set recipientSet = new HashSet<>(); + // check + assertEquals(3, testMailSender.getBufferSize()); + for (int i = 0; i < 3; i++) { + MimeMessage msg = testMailSender.fetchSentEmail(); + Address[] msgRecipients = msg.getAllRecipients(); + assertEquals(1, msgRecipients.length); + recipientSet.add(msgRecipients[0].toString()); + } + + assertTrue(recipientSet.contains("misha@example.com")); + assertTrue(recipientSet.contains("kolya@example.com")); + assertTrue(recipientSet.contains("tanya@example.com")); + } + + @Test + public void testSendAllToAdmin() throws Exception { + emailerConfig.setSendAllToAdmin(true); + emailerConfig.setAdminAddress("admin@example.com"); + try { + emailer.sendEmail("michael@example.com", "Test Email 5", "Test Body 5"); + + emailer.sendEmailAsync(new EmailInfo("nikolay@example.com", "Test Email 6", "Test Body 6")); + emailer.processQueuedEmails(); + + for (int i = 0; i < 2; i++) { + MimeMessage msg = testMailSender.fetchSentEmail(); + assertEquals(1, msg.getAllRecipients().length); + assertEquals("admin@example.com", msg.getAllRecipients()[0].toString()); + } + + } finally { + emailerConfig.setSendAllToAdmin(false); + } + } + + @Test + public void testEmailTemplate() throws Exception { + testMailSender.clearBuffer(); + + String templateFileName = "/com/haulmont/cuba/core/app/testEmailTemplate.ftl"; + + Map params = new HashMap<>(); + params.put("userName", "Bob"); + params.put("dateParam", new SimpleDateFormat("dd/MM/yyyy").parse("01/05/2013")); + + EmailInfo info = new EmailInfo("bob@example.com", "Test", null, templateFileName, params); + emailer.sendEmailAsync(info); + emailer.processQueuedEmails(); + + String body = getBody(testMailSender.fetchSentEmail()); + assertEquals("Greetings, Bob! 01-05-2013", body.trim()); + } + + @Test + public void testTextAttachment() throws Exception { + doTestTextAttachment(false); + } + + @Test + public void testTextAttachmentFS() throws Exception { + doTestTextAttachment(true); + } + + private void doTestTextAttachment(boolean useFs) throws IOException, MessagingException { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + String attachmentText = "Test Attachment Text"; + EmailAttachment textAttach = EmailAttachment.createTextAttachment(attachmentText, "ISO-8859-1", "test.txt"); + + EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", textAttach); + emailer.sendEmailAsync(myInfo); + + emailer.processQueuedEmails(); + + MimeMessage msg = testMailSender.fetchSentEmail(); + MimeBodyPart firstAttachment = getFirstAttachment(msg); + + // check content bytes + Object content = firstAttachment.getContent(); + assertTrue(content instanceof InputStream); + byte[] data = IOUtils.toByteArray((InputStream) content); + assertEquals(attachmentText, new String(data, "ISO-8859-1")); + + // disposition + assertEquals(Part.ATTACHMENT, firstAttachment.getDisposition()); + + // charset header + String contentType = firstAttachment.getContentType(); + assertTrue(contentType.toLowerCase().contains("charset=iso-8859-1")); + } + + @Test + public void testInlineImage() throws Exception { + doTestInlineImage(false); + } + + @Test + public void testInlineImageFS() throws Exception { + doTestInlineImage(true); + } + + private void doTestInlineImage(boolean useFs) throws IOException, MessagingException { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + byte[] imageBytes = new byte[]{1, 2, 3, 4, 5}; + String fileName = "logo.png"; + EmailAttachment imageAttach = new EmailAttachment(imageBytes, fileName, "logo"); + + EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", imageAttach); + emailer.sendEmailAsync(myInfo); + + emailer.processQueuedEmails(); + + MimeMessage msg = testMailSender.fetchSentEmail(); + MimeBodyPart attachment = getInlineAttachment(msg); + + // check content bytes + InputStream content = (InputStream) attachment.getContent(); + byte[] data = IOUtils.toByteArray(content); + assertByteArrayEquals(imageBytes, data); + + // disposition + assertEquals(Part.INLINE, attachment.getDisposition()); + + // mime type + String contentType = attachment.getContentType(); + assertTrue(contentType.contains("image/png")); + } + + @Test + public void testPdfAttachment() throws Exception { + doTestPdfAttachment(false); + } + + @Test + public void testPdfAttachmentFS() throws Exception { + doTestPdfAttachment(true); + } + + private void doTestPdfAttachment(boolean useFs) throws IOException, MessagingException { + emailerConfig.setFileStorageUsed(useFs); + testMailSender.clearBuffer(); + + byte[] pdfBytes = new byte[]{1, 2, 3, 4, 6}; + String fileName = "invoice.pdf"; + EmailAttachment pdfAttach = new EmailAttachment(pdfBytes, fileName); + + EmailInfo myInfo = new EmailInfo("test@example.com", "Test", null, "Test", pdfAttach); + emailer.sendEmailAsync(myInfo); + + emailer.processQueuedEmails(); + + MimeMessage msg = testMailSender.fetchSentEmail(); + MimeBodyPart attachment = getFirstAttachment(msg); + + // check content bytes + InputStream content = (InputStream) attachment.getContent(); + byte[] data = IOUtils.toByteArray(content); + assertByteArrayEquals(pdfBytes, data); + + // disposition + assertEquals(Part.ATTACHMENT, attachment.getDisposition()); + + // mime type + String contentType = attachment.getContentType(); + assertTrue(contentType.contains("application/pdf")); + } + + @Test + public void testLoadBody() throws Exception { + doTestLoadBody(false); + } + + @Test + public void testLoadBodyFS() throws Exception { + doTestLoadBody(true); + } + + private void doTestLoadBody(boolean useFs) throws Exception { + emailerConfig.setFileStorageUsed(useFs); + + String body = "Hi! This is test email. Bye."; + EmailInfo emailInfo = new EmailInfo("test@example.com", "Test", body); + List messages = emailer.sendEmailAsync(emailInfo); + + SendingMessage msg = reload(messages.get(0)); + + String actualBody = emailer.loadContentText(msg); + assertEquals(body, actualBody); + } + + @Test + public void testMigration() throws Exception { + emailerConfig.setFileStorageUsed(false); + + byte[] expectedBytes = new byte[]{1, 2, 3, 4, 6}; + EmailAttachment fileAttachment = new EmailAttachment(expectedBytes, "invoice.pdf"); + + String body = "Hi! This is test email. Bye."; + EmailInfo emailInfo = new EmailInfo("test@example.com", "Test", body); + emailInfo.setAttachments(new EmailAttachment[]{fileAttachment}); + + List messages = emailer.sendEmailAsync(emailInfo); + SendingMessage msg; + SendingAttachment attachment; + + // check DB storage + msg = reload(messages.get(0), "sendingMessage.loadFromQueue"); + attachment = msg.getAttachments().get(0); + + assertNotNull(msg.getContentText()); + assertNull(msg.getContentTextFile()); + assertNotNull(attachment.getContent()); + assertNull(attachment.getContentFile()); + + emailer.migrateEmailsToFileStorage(Lists.newArrayList(msg)); + emailer.migrateAttachmentsToFileStorage(Lists.newArrayList(attachment)); + + // check file storage + msg = reload(msg, "sendingMessage.loadFromQueue"); + attachment = msg.getAttachments().get(0); + + assertNull(msg.getContentText()); + assertNotNull(msg.getContentTextFile()); + assertEquals(body, emailer.loadContentText(msg)); + + assertNull(attachment.getContent()); + assertNotNull(attachment.getContentFile()); + FileStorageAPI fileStorage = AppBeans.get(FileStorageAPI.NAME); + byte[] actualBytes = fileStorage.loadFile(attachment.getContentFile()); + assertByteArrayEquals(expectedBytes, actualBytes); + } + + /* Utility */ + private Date getDeadlineWhichDoesntMatter() { + return DateUtils.addHours(timeSource.currentTimestamp(), 2); + } + + private String getBody(MimeMessage msg) throws Exception { + MimeBodyPart textPart = getTextPart(msg); + return (String) textPart.getContent(); + } + + private String getBodyContentType(MimeMessage msg) throws Exception { + MimeBodyPart textPart = getTextPart(msg); + return textPart.getContentType(); + } + + private MimeBodyPart getTextPart(MimeMessage msg) throws IOException, MessagingException { + assertTrue(msg.getContent() instanceof MimeMultipart); + MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); + + Object content2 = mimeMultipart.getBodyPart(0).getContent(); + assertTrue(content2 instanceof MimeMultipart); + MimeMultipart textBodyPart = (MimeMultipart) content2; + + return (MimeBodyPart) textBodyPart.getBodyPart(0); + } + + private MimeBodyPart getFirstAttachment(MimeMessage msg) throws IOException, MessagingException { + assertTrue(msg.getContent() instanceof MimeMultipart); + MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); + return (MimeBodyPart) mimeMultipart.getBodyPart(1); + } + + private MimeBodyPart getInlineAttachment(MimeMessage msg) throws IOException, MessagingException { + assertTrue(msg.getContent() instanceof MimeMultipart); + MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); + + Object content2 = mimeMultipart.getBodyPart(0).getContent(); + assertTrue(content2 instanceof MimeMultipart); + MimeMultipart textBodyPart = (MimeMultipart) content2; + + return (MimeBodyPart) textBodyPart.getBodyPart(1); + } + + private SendingMessage reload(SendingMessage sendingMessage) { + return reload(sendingMessage, null); + } + + private SendingMessage reload(SendingMessage sendingMessage, String viewName) { + LoadContext loadContext = LoadContext.create(SendingMessage.class).setId(sendingMessage.getId()); + if (viewName != null) + loadContext.setView(viewName); + + return dataManager.load(loadContext); + +// Transaction tx = cont.persistence().createTransaction(); +// try { +// sendingMessage = cont.persistence().getEntityManager().reload(sendingMessage, viewNames); +// tx.commit(); +// } finally { +// tx.end(); +// } +// return sendingMessage; + } + + private void assertByteArrayEquals(byte[] expected, byte[] actual) { + assertEquals(expected.length, actual.length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], actual[i]); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorageTest.java b/modules/core/test/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorageTest.java index 92f1eeb23f..a96d01bb1c 100644 --- a/modules/core/test/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorageTest.java +++ b/modules/core/test/com/haulmont/cuba/core/app/filestorage/amazon/AmazonS3FileStorageTest.java @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.filestorage.amazon; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.testsupport.TestContainer; -import org.apache.commons.io.IOUtils; -import org.junit.*; - -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Date; - -@Ignore -public class AmazonS3FileStorageTest { - public static final String FILE_CONTENT = "This text is for Amazon S3 service test. Second version."; - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - protected AmazonS3FileStorage fileStorageAPI; - - protected FileDescriptor fileDescr; - protected FileDescriptor fileDescr2; - - @Before - public void setUp() throws Exception { - fileDescr = new FileDescriptor(); - fileDescr.setCreateDate(new Date()); - fileDescr.setSize((long) FILE_CONTENT.length()); - fileDescr.setName("AmazonFileStorageTest"); - fileDescr.setExtension("txt"); - - fileDescr2 = new FileDescriptor(); - fileDescr2.setCreateDate(new Date()); - fileDescr2.setSize((long) FILE_CONTENT.length()); - fileDescr2.setName("AmazonFileStorageTest"); - - fileStorageAPI = new AmazonS3FileStorage(); - fileStorageAPI.amazonS3Config = AppBeans.get(Configuration.class).getConfig(AmazonS3Config.class); - } - - @Test - public void testWithExtension() throws Exception { - fileStorageAPI.saveFile(fileDescr, FILE_CONTENT.getBytes()); - - InputStream inputStream = fileStorageAPI.openStream(fileDescr); - Assert.assertEquals(FILE_CONTENT, IOUtils.toString(inputStream, StandardCharsets.UTF_8)); - - boolean fileExists = fileStorageAPI.fileExists(fileDescr); - Assert.assertTrue(fileExists); - - fileStorageAPI.removeFile(fileDescr); - } - - @Test - public void testWithoutExtension() throws Exception { - fileStorageAPI.saveFile(fileDescr2, FILE_CONTENT.getBytes()); - - InputStream inputStream = fileStorageAPI.openStream(fileDescr2); - Assert.assertEquals(FILE_CONTENT, IOUtils.toString(inputStream, StandardCharsets.UTF_8)); - - boolean fileExists = fileStorageAPI.fileExists(fileDescr2); - Assert.assertTrue(fileExists); - - fileStorageAPI.removeFile(fileDescr2); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.filestorage.amazon; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.testsupport.TestContainer; +import org.apache.commons.io.IOUtils; +import org.junit.*; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Date; + +@Ignore +public class AmazonS3FileStorageTest { + public static final String FILE_CONTENT = "This text is for Amazon S3 service test. Second version."; + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + protected AmazonS3FileStorage fileStorageAPI; + + protected FileDescriptor fileDescr; + protected FileDescriptor fileDescr2; + + @Before + public void setUp() throws Exception { + fileDescr = new FileDescriptor(); + fileDescr.setCreateDate(new Date()); + fileDescr.setSize((long) FILE_CONTENT.length()); + fileDescr.setName("AmazonFileStorageTest"); + fileDescr.setExtension("txt"); + + fileDescr2 = new FileDescriptor(); + fileDescr2.setCreateDate(new Date()); + fileDescr2.setSize((long) FILE_CONTENT.length()); + fileDescr2.setName("AmazonFileStorageTest"); + + fileStorageAPI = new AmazonS3FileStorage(); + fileStorageAPI.amazonS3Config = AppBeans.get(Configuration.class).getConfig(AmazonS3Config.class); + } + + @Test + public void testWithExtension() throws Exception { + fileStorageAPI.saveFile(fileDescr, FILE_CONTENT.getBytes()); + + InputStream inputStream = fileStorageAPI.openStream(fileDescr); + Assert.assertEquals(FILE_CONTENT, IOUtils.toString(inputStream, StandardCharsets.UTF_8)); + + boolean fileExists = fileStorageAPI.fileExists(fileDescr); + Assert.assertTrue(fileExists); + + fileStorageAPI.removeFile(fileDescr); + } + + @Test + public void testWithoutExtension() throws Exception { + fileStorageAPI.saveFile(fileDescr2, FILE_CONTENT.getBytes()); + + InputStream inputStream = fileStorageAPI.openStream(fileDescr2); + Assert.assertEquals(FILE_CONTENT, IOUtils.toString(inputStream, StandardCharsets.UTF_8)); + + boolean fileExists = fileStorageAPI.fileExists(fileDescr2); + Assert.assertTrue(fileExists); + + fileStorageAPI.removeFile(fileDescr2); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/app/scheduling/SchedulingTest.java b/modules/core/test/com/haulmont/cuba/core/app/scheduling/SchedulingTest.java index 156e1efa37..f79a44b413 100644 --- a/modules/core/test/com/haulmont/cuba/core/app/scheduling/SchedulingTest.java +++ b/modules/core/test/com/haulmont/cuba/core/app/scheduling/SchedulingTest.java @@ -1,140 +1,140 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.scheduling; - -import com.haulmont.cuba.core.entity.ScheduledTask; -import com.haulmont.cuba.core.entity.SchedulingType; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.testsupport.TestContainer; -import junit.framework.Assert; -import org.junit.ClassRule; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -public class SchedulingTest { - - private SimpleDateFormat simpleDateFormat; - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - public SchedulingTest() { - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); - simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-0")); - } - - @Test - public void testCurrentStart() throws Exception { - Scheduling scheduling = new Scheduling() { - @Override - protected TimeZone getCurrentTimeZone() { - return TimeZone.getTimeZone("GMT-0"); - } - }; - - ScheduledTask scheduledTask = new ScheduledTask(); - scheduledTask.setSchedulingType(SchedulingType.CRON); - scheduledTask.setCron("*/5 * * * * *"); - - //scheduler has failed couple of runs and now we should run it - long currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-13 15:29:00").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); - assertEquals(date("2013-11-13 15:29:55"), new Date(currentStart)); - - //last run was year ago, so now-frame should be considered - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2012-11-13 15:29:00").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); - assertEquals(date("2013-11-13 15:29:55"), new Date(currentStart)); - - //last run was very close to now, last start date should be considered - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-13 15:29:59").getTime(), date("2013-11-13 15:30:01").getTime(), 10000l); - assertEquals(date("2013-11-13 15:30:00"), new Date(currentStart)); - - scheduledTask.setCron("0 0 0 * * FRI"); - - //task should run in next friday - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-08 01:01:01").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); - assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); - - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-08 01:01:01").getTime(), date("2013-11-08 01:01:02").getTime(), 600000l); - assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); - - //task is late but matches frame - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-07 23:59:59").getTime(), date("2013-11-08 00:01:00").getTime(), 600000l); - assertEquals(date("2013-11-8 00:00:00"), new Date(currentStart)); - - //task is late and does not match frame - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-07 23:59:59").getTime(), date("2013-11-08 00:11:00").getTime(), 600000l); - assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); - - scheduledTask.setCron("0 59 1 * * *"); - - //time shift forward - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-10-26 1:59:59").getTime(), date("2013-10-27 00:00:00").getTime(), 600000l); - assertEquals(date("2013-10-27 01:59:00"), new Date(currentStart)); - - //time shift backward - currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-03-30 1:59:00").getTime(), date("2013-03-31 00:00:00").getTime(), 600000l); - assertEquals(date("2013-03-31 01:59:00"), new Date(currentStart)); - } - - public Date date(String s) { - try { - return simpleDateFormat.parse(s); - } catch (ParseException e) { - Assert.fail(); - } - - return null; - } - - @Test - public void testRunning() { - Scheduling scheduling = new Scheduling() { - { - timeSource = new TimeSource() { - @Override - public Date currentTimestamp() { - return new Date(); - } - - @Override - public long currentTimeMillis() { - return System.currentTimeMillis(); - } - }; - } - - @Override - protected TimeZone getCurrentTimeZone() { - return TimeZone.getTimeZone("GMT-0"); - } - }; - ScheduledTask scheduledTask = new ScheduledTask(); - - assertFalse(scheduling.setRunning(scheduledTask, true)); - assertTrue(scheduling.setRunning(scheduledTask, true)); - - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.scheduling; + +import com.haulmont.cuba.core.entity.ScheduledTask; +import com.haulmont.cuba.core.entity.SchedulingType; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.testsupport.TestContainer; +import junit.framework.Assert; +import org.junit.ClassRule; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +public class SchedulingTest { + + private SimpleDateFormat simpleDateFormat; + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + public SchedulingTest() { + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-0")); + } + + @Test + public void testCurrentStart() throws Exception { + Scheduling scheduling = new Scheduling() { + @Override + protected TimeZone getCurrentTimeZone() { + return TimeZone.getTimeZone("GMT-0"); + } + }; + + ScheduledTask scheduledTask = new ScheduledTask(); + scheduledTask.setSchedulingType(SchedulingType.CRON); + scheduledTask.setCron("*/5 * * * * *"); + + //scheduler has failed couple of runs and now we should run it + long currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-13 15:29:00").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); + assertEquals(date("2013-11-13 15:29:55"), new Date(currentStart)); + + //last run was year ago, so now-frame should be considered + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2012-11-13 15:29:00").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); + assertEquals(date("2013-11-13 15:29:55"), new Date(currentStart)); + + //last run was very close to now, last start date should be considered + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-13 15:29:59").getTime(), date("2013-11-13 15:30:01").getTime(), 10000l); + assertEquals(date("2013-11-13 15:30:00"), new Date(currentStart)); + + scheduledTask.setCron("0 0 0 * * FRI"); + + //task should run in next friday + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-08 01:01:01").getTime(), date("2013-11-13 15:30:00").getTime(), 10000l); + assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); + + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-08 01:01:01").getTime(), date("2013-11-08 01:01:02").getTime(), 600000l); + assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); + + //task is late but matches frame + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-07 23:59:59").getTime(), date("2013-11-08 00:01:00").getTime(), 600000l); + assertEquals(date("2013-11-8 00:00:00"), new Date(currentStart)); + + //task is late and does not match frame + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-11-07 23:59:59").getTime(), date("2013-11-08 00:11:00").getTime(), 600000l); + assertEquals(date("2013-11-15 00:00:00"), new Date(currentStart)); + + scheduledTask.setCron("0 59 1 * * *"); + + //time shift forward + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-10-26 1:59:59").getTime(), date("2013-10-27 00:00:00").getTime(), 600000l); + assertEquals(date("2013-10-27 01:59:00"), new Date(currentStart)); + + //time shift backward + currentStart = scheduling.calculateNextCronDate(scheduledTask, date("2013-03-30 1:59:00").getTime(), date("2013-03-31 00:00:00").getTime(), 600000l); + assertEquals(date("2013-03-31 01:59:00"), new Date(currentStart)); + } + + public Date date(String s) { + try { + return simpleDateFormat.parse(s); + } catch (ParseException e) { + Assert.fail(); + } + + return null; + } + + @Test + public void testRunning() { + Scheduling scheduling = new Scheduling() { + { + timeSource = new TimeSource() { + @Override + public Date currentTimestamp() { + return new Date(); + } + + @Override + public long currentTimeMillis() { + return System.currentTimeMillis(); + } + }; + } + + @Override + protected TimeZone getCurrentTimeZone() { + return TimeZone.getTimeZone("GMT-0"); + } + }; + ScheduledTask scheduledTask = new ScheduledTask(); + + assertFalse(scheduling.setRunning(scheduledTask, true)); + assertTrue(scheduling.setRunning(scheduledTask, true)); + + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/app/testEmailTemplate.ftl b/modules/core/test/com/haulmont/cuba/core/app/testEmailTemplate.ftl index 66fc82b47b..ae9cfcd316 100644 --- a/modules/core/test/com/haulmont/cuba/core/app/testEmailTemplate.ftl +++ b/modules/core/test/com/haulmont/cuba/core/app/testEmailTemplate.ftl @@ -1,2 +1,2 @@ -<#assign dateFormatted=dateParam?string("dd-MM-yyyy")> -Greetings, ${userName}! ${dateFormatted} +<#assign dateFormatted=dateParam?string("dd-MM-yyyy")> +Greetings, ${userName}! ${dateFormatted} diff --git a/modules/core/test/com/haulmont/cuba/core/config/TestConfig.java b/modules/core/test/com/haulmont/cuba/core/config/TestConfig.java index 8f7be5e37d..bf0c131528 100644 --- a/modules/core/test/com/haulmont/cuba/core/config/TestConfig.java +++ b/modules/core/test/com/haulmont/cuba/core/config/TestConfig.java @@ -1,113 +1,113 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.config; - -import com.haulmont.cuba.core.config.defaults.Default; -import com.haulmont.cuba.core.config.defaults.DefaultBoolean; -import com.haulmont.cuba.core.config.defaults.DefaultInt; -import com.haulmont.cuba.core.config.defaults.DefaultInteger; -import com.haulmont.cuba.core.config.type.*; -import com.haulmont.cuba.security.entity.RoleType; -import com.haulmont.cuba.security.entity.User; - -import java.util.Date; -import java.util.List; -import java.util.UUID; - -@Source(type = SourceType.APP) -public interface TestConfig extends Config -{ - @Property("cuba.test.stringProp") - String getStringProp(); - void setStringProp(String value); - - @Property("cuba.test.stringPropDef") - @Default("def_value") - String getStringPropDef(); - void setStringPropDef(String value); - - @Property("cuba.test.integerProp") - Integer getIntegerProp(); - void setIntegerProp(Integer value); - - @Property("cuba.test.integerPropDef") - @DefaultInteger(100) - Integer getIntegerPropDef(); - void setIntegerPropDef(Integer value); - - @Property("cuba.test.integerPropDefRuntime") - Integer getIntegerPropDefRuntime(Integer defaultValue); - - @Property("cuba.test.intPropDef") - @DefaultInt(0) - int getIntPropDef(); - void setIntPropDef(int value); - - @Property("cuba.test.intPropDefRuntime") - int getIntPropDefRuntime(int defaultValue); - void setIntPropDefRuntime(int value); - - @Property("cuba.test.booleanProp") - Boolean getBooleanProp(); - void setBooleanProp(Boolean value); - - @Property("cuba.test.booleanPropDef") - @DefaultBoolean(true) - Boolean getBooleanPropDef(); - - @Property("cuba.test.boolProp") - @DefaultBoolean(false) - boolean getBoolProp(); - void setBoolProp(boolean value); - - @Property("cuba.test.uuidProp") - @Factory(factory = UuidTypeFactory.class) - UUID getUuidProp(); - void setUuidProp(UUID value); - - @Property("cuba.test.databaseProp") - @Source(type = SourceType.DATABASE) - String getDatabaseProp(); - void setDatabaseProp(String value); - - @Property("cuba.test.adminUser") - @Default("sec$User-60885987-1b61-4247-94c7-dff348347f93") - User getAdminUser(); - - @Property("cuba.test.roleTypeProp") - @Default("STANDARD") - RoleType getRoleTypeProp(); - - @Property("cuba.test.dateProp") - @Default("2013-12-12 00:00:00.000") - @Factory(factory = DateFactory.class) - Date getDateProp(); - - @Property("cuba.test.integerListProp") - @Default("1 2 3") - @Factory(factory = IntegerListTypeFactory.class) - List getIntegerListProp(); - - @Property("cuba.test.stringListProp") - @Default("aaa|bbb|ccc") - @Factory(factory = StringListTypeFactory.class) - List getStringListProp(); - - @Property("cuba.test.stringNotFoundGetterProp") - String getStringNotFoundGetterProp(); - void setStringNotFoundGetProp(String value); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.config; + +import com.haulmont.cuba.core.config.defaults.Default; +import com.haulmont.cuba.core.config.defaults.DefaultBoolean; +import com.haulmont.cuba.core.config.defaults.DefaultInt; +import com.haulmont.cuba.core.config.defaults.DefaultInteger; +import com.haulmont.cuba.core.config.type.*; +import com.haulmont.cuba.security.entity.RoleType; +import com.haulmont.cuba.security.entity.User; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Source(type = SourceType.APP) +public interface TestConfig extends Config +{ + @Property("cuba.test.stringProp") + String getStringProp(); + void setStringProp(String value); + + @Property("cuba.test.stringPropDef") + @Default("def_value") + String getStringPropDef(); + void setStringPropDef(String value); + + @Property("cuba.test.integerProp") + Integer getIntegerProp(); + void setIntegerProp(Integer value); + + @Property("cuba.test.integerPropDef") + @DefaultInteger(100) + Integer getIntegerPropDef(); + void setIntegerPropDef(Integer value); + + @Property("cuba.test.integerPropDefRuntime") + Integer getIntegerPropDefRuntime(Integer defaultValue); + + @Property("cuba.test.intPropDef") + @DefaultInt(0) + int getIntPropDef(); + void setIntPropDef(int value); + + @Property("cuba.test.intPropDefRuntime") + int getIntPropDefRuntime(int defaultValue); + void setIntPropDefRuntime(int value); + + @Property("cuba.test.booleanProp") + Boolean getBooleanProp(); + void setBooleanProp(Boolean value); + + @Property("cuba.test.booleanPropDef") + @DefaultBoolean(true) + Boolean getBooleanPropDef(); + + @Property("cuba.test.boolProp") + @DefaultBoolean(false) + boolean getBoolProp(); + void setBoolProp(boolean value); + + @Property("cuba.test.uuidProp") + @Factory(factory = UuidTypeFactory.class) + UUID getUuidProp(); + void setUuidProp(UUID value); + + @Property("cuba.test.databaseProp") + @Source(type = SourceType.DATABASE) + String getDatabaseProp(); + void setDatabaseProp(String value); + + @Property("cuba.test.adminUser") + @Default("sec$User-60885987-1b61-4247-94c7-dff348347f93") + User getAdminUser(); + + @Property("cuba.test.roleTypeProp") + @Default("STANDARD") + RoleType getRoleTypeProp(); + + @Property("cuba.test.dateProp") + @Default("2013-12-12 00:00:00.000") + @Factory(factory = DateFactory.class) + Date getDateProp(); + + @Property("cuba.test.integerListProp") + @Default("1 2 3") + @Factory(factory = IntegerListTypeFactory.class) + List getIntegerListProp(); + + @Property("cuba.test.stringListProp") + @Default("aaa|bbb|ccc") + @Factory(factory = StringListTypeFactory.class) + List getStringListProp(); + + @Property("cuba.test.stringNotFoundGetterProp") + String getStringNotFoundGetterProp(); + void setStringNotFoundGetProp(String value); +} diff --git a/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerAstBasedTest.java b/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerAstBasedTest.java index 8ca99d391f..e9bf3c9fa3 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerAstBasedTest.java +++ b/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerAstBasedTest.java @@ -1,1264 +1,1264 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.JpqlSyntaxException; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModelImpl; -import com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased; -import org.antlr.runtime.RecognitionException; -import org.junit.Before; -import org.junit.Test; - -import java.util.Date; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -public class QueryTransformerAstBasedTest { - - @Before - public void setUp() throws Exception { - } - - @Test - public void getResult_noChangesMade() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModelImpl playerEntity = builder.produceImmediately("Player"); - DomainModel model = new DomainModel(playerEntity); - - assertTransformsToSame(model, "SELECT p FROM Player p"); - } - - @Test - public void getResult_noChangesMade_withJoinAndAsAndMemberField() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addReferenceAttribute("as", "Team"); - builder.addReferenceAttribute("member", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT p FROM Player p JOIN p.as t"); - assertTransformsToSame(model, "SELECT p FROM Player p JOIN p.member t"); - } - - @Test - public void getResult_noChangesMade_withJoinAndSeveralJoinConditions() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addStringAttribute("name"); - builder.addReferenceAttribute("as", "Team"); - builder.addReferenceAttribute("member", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT p FROM Player p JOIN Team t on p.member = t and p.name = :param"); - } - - - @Test - public void getResult_noChangesMade_withMultiFieldSelect() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("Team"); - builder.addStringAttribute("name"); - JpqlEntityModel teamEntity = builder.produce(); - - builder.startNewEntity("Player"); - builder.addStringAttribute("nickname"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT p.team.name, p.nickname FROM Player p"); - } - - @Test - public void getResult_noChangesMade_withMultiEntitySelect() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team"); - JpqlEntityModel playerEntity = builder.produceImmediately("Player"); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT p, t FROM Player p, Team t"); - } - - @Test - public void getResult_noChangesMade_withAggregateExpression() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addSingleValueAttribute(Integer.class, "age"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT count(p) FROM Player p"); - assertTransformsToSame(model, "SELECT max(p.age) FROM Player p"); - assertTransformsToSame(model, "SELECT min(p.age) FROM Player p"); - assertTransformsToSame(model, "SELECT avg(p.age) FROM Player p"); - assertTransformsToSame(model, "SELECT sum(p.age) FROM Player p"); - assertTransformsToSame(model, "SELECT max(p.age), t FROM Player p join p.team t group by t"); - assertTransformsToSame(model, "SELECT max(p.age), t.name FROM Player p join p.team t group by t.name"); - } - - @Test - public void getResult_noChangesMade_withMacros() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addSingleValueAttribute(Date.class, "birthDate"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @between(p.birthDate, now-2, now+2, month) "); - String result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where @between ( p.birthDate, now - 2, now + 2, month)", result); - - transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateBefore(p.birthDate, :d) "); - result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where @dateBefore ( p.birthDate, :d)", result); - - transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateAfter(p.birthDate, :d) "); - result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where @dateAfter ( p.birthDate, :d)", result); - - transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateEquals(p.birthDate, :d) "); - result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where @dateEquals ( p.birthDate, :d)", result); - - transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @today(p.birthDate) "); - result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where @today ( p.birthDate)", result); - - } - - @Test - public void getResult_noChangesMade_withWhere() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - - builder.startNewEntity("Player"); - builder.addReferenceAttribute("team", "Team"); - builder.addStringAttribute("name"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "SELECT p FROM Player p where p.name = 'de Souza'"); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p left join p.team as t WHERE t.name = 'KS FC'"); - String result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p left join p.team t WHERE t.name = 'KS FC'", result); - } - - @Test - public void getResult_noChangesMade_withJoin() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); - - builder.startNewEntity("Team"); - builder.addStringAttribute("name"); - builder.addStringAttribute("owner"); - builder.addReferenceAttribute("manager", "Person"); - JpqlEntityModel teamEntity = builder.produce(); - - builder.startNewEntity("Player"); - builder.addStringAttribute("name"); - builder.addStringAttribute("nickname"); - builder.addReferenceAttribute("team", "Team"); - builder.addReferenceAttribute("agent", "Person"); - JpqlEntityModel playerEntity = builder.produce(); - - builder.startNewEntity("League"); - builder.addStringAttribute("name"); - builder.addCollectionReferenceAttribute("teams", "Team"); - JpqlEntityModel leagueEntity = builder.produce(); - - builder.startNewEntity("Country"); - builder.addStringAttribute("flag"); - builder.addReferenceAttribute("league", "League"); - JpqlEntityModel countryEntity = builder.produce(); - - DomainModel model = new DomainModel(teamEntity, playerEntity, leagueEntity, personEntity, countryEntity); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select m.personName from Player p left join p.team.manager as m"); - String result = transformerAstBased.getResult(); - assertEquals("select m.personName from Player p left join p.team.manager m", result); - - transformerAstBased = new QueryTransformerAstBased(model, "select c.flag from Country c join c.league.teams as t join t.manager m"); - assertEquals("select c.flag from Country c join c.league.teams t join t.manager m", - transformerAstBased.getResult()); - } - - @Test - public void getResult_noChangesMade_withLeft_InnerJoinFetch() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); - - builder.startNewEntity("Team"); - builder.addStringAttribute("name"); - builder.addStringAttribute("owner"); - builder.addReferenceAttribute("manager", "Person"); - JpqlEntityModel teamEntity = builder.produce(); - - builder.startNewEntity("Player"); - builder.addStringAttribute("name"); - builder.addStringAttribute("nickname"); - builder.addReferenceAttribute("team", "Team"); - builder.addReferenceAttribute("agent", "Person"); - JpqlEntityModel playerEntity = builder.produce(); - - DomainModel model = new DomainModel(teamEntity, playerEntity, personEntity); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.name from Player p join fetch p.team left join fetch p.agent"); - assertEquals("select p.name from Player p join fetch p.team left join fetch p.agent", - transformerAstBased.getResult()); - - transformerAstBased = new QueryTransformerAstBased(model, "select p.name from Player p left outer join fetch p.team inner join fetch p.agent"); - assertEquals("select p.name from Player p left outer join fetch p.team inner join fetch p.agent", - transformerAstBased.getResult()); - } - - @Test - public void getResult_noChangesMade_withDistinct() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); - - builder.startNewEntity("Team"); - builder.addStringAttribute("name"); - builder.addStringAttribute("owner"); - builder.addReferenceAttribute("manager", "Person"); - JpqlEntityModel teamEntity = builder.produce(); - - builder.startNewEntity("Player"); - builder.addStringAttribute("name"); - builder.addStringAttribute("nickname"); - builder.addReferenceAttribute("team", "Team"); - builder.addReferenceAttribute("agent", "Person"); - JpqlEntityModel playerEntity = builder.produce(); - - builder.startNewEntity("League"); - builder.addStringAttribute("name"); - builder.addCollectionReferenceAttribute("teams", "Team"); - JpqlEntityModel leagueEntity = builder.produce(); - - builder.startNewEntity("Country"); - builder.addStringAttribute("flag"); - builder.addReferenceAttribute("league", "League"); - JpqlEntityModel countryEntity = builder.produce(); - - DomainModel model = new DomainModel(teamEntity, playerEntity, leagueEntity, personEntity, countryEntity); - - assertTransformsToSame(model, "select distinct m from Player p left join p.team.manager m"); - } - -// The following functions are not supported by JPA2 JPQL (see jpql21.bnf) -// @Test -// public void getResult_noChangesMade_withSubqueries() throws RecognitionException { -// EntityBuilder builder = new EntityBuilder(); -// JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); -// -// builder.startNewEntity("Player"); -// builder.addStringAttribute("name"); -// builder.addStringAttribute("nickname"); -// builder.addReferenceAttribute("team", "Team"); -// JpqlEntityModel playerEntity = builder.produce(); -// -// DomainModel model = new DomainModel(playerEntity, teamEntity); -// -// assertTransformsToSame(model, "select p.name from (select t.name from Team t) p"); -// assertTransformsToSame(model, "select p.owner from (select t.name, t.owner from Team t) p"); -// assertTransformsToSame(model, "select g.owner from (select t.name, t.owner from Team t) p, (select t.name from Team t) g"); -// } - -// The following functions are not supported by JPA2 JPQL (see jpql21.bnf) -// @Test -// public void getResult_noChangesMade_severalLevelsOfSubquery() throws RecognitionException { -// EntityBuilder builder = new EntityBuilder(); -// JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); -// -// builder.startNewEntity("Player"); -// builder.addStringAttribute("name"); -// builder.addStringAttribute("nickname"); -// builder.addReferenceAttribute("team", "Team"); -// JpqlEntityModel playerEntity = builder.produce(); -// -// DomainModel model = new DomainModel(playerEntity, teamEntity); -// -// assertTransformsToSame(model, "select p.owner from (select t from Team t where t.name in (select a.name from Player a)) p"); -// // 'as' опускается -// QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.owner from (select t.owner from Team as t where t.name = '1') p", "AsdfAsdfAsdf"); -// String result = transformerAstBased.getResult(); -// assertEquals("select p.owner from (select t.owner from Team t where t.name = '1') p", result); -// } - - @Test - public void getResult_noChangesMade_subqueries() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); - - builder.startNewEntity("Player"); - builder.addStringAttribute("name"); - builder.addStringAttribute("nickname"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - - DomainModel model = new DomainModel(playerEntity, teamEntity); - - assertTransformsToSame(model, "select p.owner from Player pl where exists (select t from Team t where t.name = 'Team1' and pl.team.id = t.id)"); - assertTransformsToSame(model, "select p.owner from Player pl where pl.team.id in (select t.id from Team t where t.name = 'Team1')"); - assertTransformsToSame(model, "select t.name from Team t where (select count(p) from Player p where p.team.id = t.id) > 10"); - } - - @Test - public void getResult_noChangesMade_withParameters() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname"); - - DomainModel model = new DomainModel(playerEntity); - - assertTransformsToSame(model, "select p.nickname from Player p where p.name = :name"); - assertTransformsToSame(model, "select p.nickname from Player p where p.name = :name or p.name = :name2"); - assertTransformsToSame(model, "select p.nickname from Player p where p.name = ?1 or p.name = ?2"); - - assertTransformsToSame(model, "select p.nickname from Player p where p.name like :component$playersFilter.name52981"); - } - - @Test - public void getResult_noChangesMade_with_in_collections() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel driver = builder.produceImmediately("Driver", "name", "signal"); - - builder.startNewEntity("HomeBase"); - builder.addStringAttribute("city"); - JpqlEntityModel homeBase = builder.produce(); - - builder.startNewEntity("Car"); - builder.addStringAttribute("model"); - builder.addCollectionReferenceAttribute("drivers", "Driver"); - builder.addReferenceAttribute("station", "HomeBase"); - JpqlEntityModel car = builder.produce(); - DomainModel model = new DomainModel(car, driver, homeBase); - - assertTransformsToSame(model, "select d.name from Car c, in(c.drivers) d where d.name = ?1"); - - assertTransformsToSame(model, "select d.name from Car c join c.station s, in(c.drivers) d where d.name = ?1 and s.city = :par2"); - } - - @Test - public void getResult_noChangesMade_withGroupBy() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); - - DomainModel model = new DomainModel(playerEntity); - assertTransformsToSame(model, "select p from Player p group by p.level, p.name"); - - assertTransformsToSame(model, "select p from Player p group by p.level"); - } - - @Test - public void getResult_noChangesMade_withGroupByHavingOrderBy() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); - - builder.startNewEntity("Team"); - builder.addCollectionReferenceAttribute("players", "Player"); - builder.addStringAttribute("title"); - JpqlEntityModel team = builder.produce(); - - DomainModel model = new DomainModel(playerEntity, team); - assertTransformsToSame(model, "select p from Team t join t.players p " + - "group by p.level having p.level > 0 order by p.level"); - } - - private void assertTransformsToSame(DomainModel model, String query) throws RecognitionException { - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, query); - String result = transformerAstBased.getResult(); - assertEquals(query, result); - } - - @Test - public void test() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par" - ); - - transformer.addWhere("{E}.createdBy = :par1"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = :par) and (h.createdBy = :par1)", - res); - - transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = ?1 " + - "group by c.level having c.level > 0 order by c.level" - ); - - transformer.addWhere("{E}.createdBy = :par1"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = ?1) " + - "and (h.createdBy = :par1) group by c.level having c.level > 0 order by c.level", - res); - Set set = transformer.getAddedParams(); - assertEquals(1, set.size()); - assertEquals("par1", set.iterator().next()); - - transformer.addWhere("({E}.updatedBy = :par2 and {E}.groupId = :par3)"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where ((h.userGroup = ?1) " + - "and (h.createdBy = :par1)) and ((h.updatedBy = :par2 and h.groupId = :par3)) group by c.level having c.level > 0 order by c.level", - res); - set = transformer.getAddedParams(); - assertEquals(3, set.size()); - - transformer.reset(); - - transformer.mergeWhere("select gh from sec$GroupHierarchy gh where gh.version between 1 and 2"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = ?1) " + - "and (h.version between 1 and 2) group by c.level having c.level > 0 order by c.level", - res); - } - - @Test - public void addWhereAsId() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par" - ); - - transformer.addWhereAsIs("a.createdBy = :par1"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = :par) " + - "and (a.createdBy = :par1)", - res); - } - - @Test - public void getResult_noChangesMade_parametersWithDot() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addSingleValueAttribute(Date.class, "birthDate"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where p.birthDate = :d.option"); - String result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p where p.birthDate = :d.option", result); - } - - @Test - public void getResult_noChangesMade_orderBySeveralFields() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); - builder.startNewEntity("Player"); - builder.addSingleValueAttribute(Date.class, "birthDate"); - builder.addStringAttribute("surname"); - builder.addReferenceAttribute("team", "Team"); - JpqlEntityModel playerEntity = builder.produce(); - DomainModel model = new DomainModel(playerEntity, teamEntity); - - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p order by p.birthDate, p.surname"); - String result = transformerAstBased.getResult(); - assertEquals("SELECT p FROM Player p order by p.birthDate, p.surname", result); - } - - @Test - public void getResult_noChangesMade_join_fetch() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h join fetch h.parent.constraints where h.userGroup = :par" - ); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join fetch h.parent.constraints where h.userGroup = :par", - res); - } - - @Test - public void getResult_noChangesMade_update() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("sec$Car"); - builder.addStringAttribute("model"); - builder.addStringAttribute("vin"); - JpqlEntityModel car = builder.produce(); - DomainModel model = new DomainModel(car); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "update sec$Car c set c.model = :model, c.vin = :vin" - ); - assertEquals( - "update sec$Car c set c.model=:model,c.vin=:vin", - transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, - "update sec$Car c set c.model = :model, c.vin = :vin where c.vin = :oldVin" - ); - assertEquals( - "update sec$Car c set c.model=:model,c.vin=:vin where c.vin = :oldVin", - transformer.getResult()); - } - - @Test - public void getResult_noChangesMade_delete() throws Exception { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "delete from sec$GroupHierarchy g where g.createdBy = :createdBy"); - assertEquals(transformerAstBased.getResult(), "delete from sec$GroupHierarchy g where g.createdBy = :createdBy"); - } - - @Test - public void getResult_noChangesMade_AsInSelect() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); - - DomainModel model = new DomainModel(playerEntity); - assertTransformsToSame(model, "select p.name as name, p.nickname as nickname from Player p"); - assertTransformsToSame(model, "select p.name as name from Player p"); - } - - - @Test - public void addJoinAsId() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par" - ); - - transformer.addJoinAsIs("join a.parent.constraints c"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$Constraint u, sec$GroupHierarchy h join a.parent.constraints c where h.userGroup = :par", - res); - } - - @Test - public void addJoinOn() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par" - ); - - transformer.addJoinAsIs("join sec$Constraint c on c.group.id = h.parent.id"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$Constraint u, sec$GroupHierarchy h join sec$Constraint c on c.group.id = h.parent.id where h.userGroup = :par", - res); - } - - @Test - public void addWhere_with_child_select() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("Car"); - builder.addStringAttribute("model"); - builder.addReferenceAttribute("driver", "Person"); - JpqlEntityModel car = builder.produce(); - - JpqlEntityModel person = builder.produceImmediately("Person", "fullname"); - DomainModel model = new DomainModel(car, person); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select car.driver from Car car"); - transformer.addWhere("{E}.model = ?1"); - assertEquals("select car.driver from Car car where car.model = ?1", - transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, - "select car.driver from Car car"); - transformer.addWhere("{E}.driver.fullname = ?1"); - assertEquals("select car.driver from Car car where car.driver.fullname = ?1", - transformer.getResult()); - } - - - private DomainModel prepareDomainModel() { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("sec$GroupHierarchy"); - builder.addStringAttribute("group"); - builder.addStringAttribute("createdBy"); - builder.addReferenceAttribute("parent", "sec$GroupHierarchy"); - builder.addReferenceAttribute("other", "sec$GroupHierarchy"); - builder.addReferenceAttribute("token", "fake$EmbeddedToken", "token", true); - - builder.addCollectionReferenceAttribute("constraints", "sec$Constraint"); - JpqlEntityModel groupHierarchy = builder.produce(); - - builder = new EntityBuilder(); - builder.startNewEntity("sec$Constraint"); - builder.addReferenceAttribute("group", "sec$GroupHierarchy"); - JpqlEntityModel constraintEntity = builder.produce(); - - JpqlEntityModel userEntity = builder.produceImmediately("sec$User", "login"); - - builder = new EntityBuilder(); - builder.startNewEntity("fake$EmbeddedToken"); - builder.addStringAttribute("name"); - builder.addStringAttribute("code"); - builder.addReferenceAttribute("manager", "sec$User"); - builder.addReferenceAttribute("parentToken", "fake$EmbeddedToken", "parentToken", true); - JpqlEntityModel token = builder.produce(); - - return new DomainModel(groupHierarchy, constraintEntity, userEntity, token); - } - - @Test - public void testAliasPlaceholder() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par" - ); - - transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = :par2"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + - " and h.updatedBy = :par2)", - res); - - //////////////////////////////////// - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = :par" - ); - - transformer.addJoinAndWhere("join h.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + - " and h.updatedBy = :par2 and c.createTs = :par3)", - res); - - //////////////////////////////////// - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = :par" - ); - - transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + - " and h.updatedBy = :par2 and c.createTs = :par3)", - res); - } - -//todo eude : fix the following -// @Test -// public void testInvalidEntity() throws RecognitionException { -// DomainModel model = prepareDomainModel(); -// -// QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, -// "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + -// "group by c.level having c.level > 0 order by c.level"); -// try { -// transformer.addWhere("a.createdBy = :par1"); -// fail(); -// } catch (Exception e) { -// assertTrue(e instanceof RuntimeException); -// } -// } - - @Test - public void addWhere_adds_Where_IfNeeded() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h"); - transformer.addWhere("h.group = ?1"); - assertEquals("select h from sec$GroupHierarchy h where h.group = ?1", - transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h join h.parent.constraints c"); - transformer.addWhere("h.group = ?1"); - assertEquals("select h from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1", - transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h join h.parent.constraints c group by c.level having c.level > 0 order by c.level"); - transformer.addWhere("h.group = ?1"); - assertEquals("select h from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 group by c.level having c.level > 0 order by c.level", - transformer.getResult()); - } - -//todo eude : fix the following -// @Test -// public void addWhere_onIncorrectHavingInTheEnd() throws RecognitionException { -// DomainModel model = prepareDomainModel(); -// -// try { -// new QueryTransformerAstBased(model, -// "select h from sec$GroupHierarchy h join h.parent.constraints c group by c.level order by c.level having c.level > 0"); -// fail("Incorrectly placed 'having' passed"); -// } catch (JpqlSyntaxException e) { -// //expected -// } -// } - - @Test - public void addWhere_onIncorrectQuery() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - try { - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h join h.parent.constraints"); - transformer.getResult(); - fail("Not named join variable passed"); - } catch (JpqlSyntaxException e) { - //expected - } - } - - @Test - public void testJoin() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = :par"); - - transformer.addJoinAndWhere("join h.parent.constraints c", "c.createdBy = :par2"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (c.createdBy = :par2)", - res); - - transformer.reset(); - transformer.addJoinAndWhere("left join h.parent.constraints c", "c.createdBy = :par2"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent.constraints c where (h.group = :par) and (c.createdBy = :par2)", - res); - - transformer.reset(); - transformer.addJoinAndWhere(",sec$Constraint c", "c.createdBy = :par2"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h, sec$Constraint c where (h.group = :par) and (c.createdBy = :par2)", - res); - } - - @Test - public void testDoubleJoins() throws Exception { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = :par"); - - transformer.reset(); - transformer.addJoinAndWhere("join h.parent.constraints c1 join h.constraints c2", "c.createdBy = :par2"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints c1 join h.constraints c2 where (h.group = :par) and (c.createdBy = :par2)", - res); - - transformer.reset(); - transformer.addJoinAndWhere("join {E}.parent p join p.constraints cr", "c.createdBy = :par2"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent p join p.constraints cr where (h.group = :par) and (c.createdBy = :par2)", - res); - - transformer.reset(); - transformer.addJoinAndWhere("join replaceEntity.parent p join p.constraints cr", "c.createdBy = :par2"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent p join p.constraints cr where (h.group = :par) and (c.createdBy = :par2)", - res); - } - - @Test - public void testJoin_WithComma() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = :par"); - transformer.addJoinAndWhere("join h.parent.constraints pco, sec$Constraint sc", "1 = 1"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints pco, sec$Constraint sc where (h.group = :par) and (1 = 1)", - res); - - - transformer.reset(); - transformer.addJoinAsIs("join h.parent.constraints pco, sec$Constraint sc"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints pco, sec$Constraint sc where h.group = :par", - res); - - } - - // todo eude : fix the following - @Test - public void join_with_in_collections() throws RecognitionException { -// EntityBuilder builder = new EntityBuilder(); -// -// builder.startNewEntity("HomeBase"); -// builder.addStringAttribute("name"); -// JpqlEntityModel homeBase = builder.produce(); -// -// builder.startNewEntity("Driver"); -// builder.addStringAttribute("name"); -// builder.addStringAttribute("signal"); -// builder.addReferenceAttribute("home", "HomeBase"); -// JpqlEntityModel driver = builder.produce(); -// -// builder.startNewEntity("Car"); -// builder.addStringAttribute("model"); -// builder.addCollectionReferenceAttribute("drivers", "Driver"); -// builder.addReferenceAttribute("station", "HomeBase"); -// JpqlEntityModel car = builder.produce(); -// DomainModel model = new DomainModel(car, driver, homeBase); -// -// QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, -// "select d.name from Car c, in(c.drivers) d where d.signal = ?1"); -// -// transformer.addJoinAndWhere("join d.home h", "h.name = :par2"); -// String res = transformer.getResult(); -// assertEquals( -// "select d.name from Car c, in(c.drivers) d join d.home h where (d.signal = ?1) and (h.name = :par2)", -// res); -// -// transformer = new QueryTransformerAstBased(model, -// "select d.name from Car c, in(c.drivers) d where d.signal = ?1"); -// transformer.addJoinAndWhere("join c.station h", "h.name = :par2"); -// res = transformer.getResult(); -// assertEquals( -// "select d.name from Car c join c.station h, in(c.drivers) d where (d.signal = ?1) and (h.name = :par2)", -// res); -// -// transformer = new QueryTransformerAstBased(model, -// "select c, d from Car c, Driver d where d.signal = ?1"); -// -// transformer.addJoinAndWhere("join d.station h", "h.name = :par2"); -// res = transformer.getResult(); -// assertEquals( -// "select c, d from Car c join c.station h, Driver d where (d.signal = ?1) and (h.name = :par2)", -// res); -// -// transformer = new QueryTransformerAstBased(model, -// "select c, d from Car c, Driver d where d.signal = ?1"); -// transformer.addJoinAndWhere("join d.home h", "h.name = :par2"); -// res = transformer.getResult(); -// assertEquals( -// "select c, d from Car c, Driver d join d.home h where (d.signal = ?1) and (h.name = :par2)", -// res); - } - - @Test - public void testReplaceWithCount() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - assertEquals( - "select count(c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - assertEquals( - "select count(c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - transformer.getResult()); - } - - @Test - public void testHandleCaseInsensitiveParam() throws Exception { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select u from sec$User u where u.name like :name"); - transformer.handleCaseInsensitiveParam("name"); - String res = transformer.getResult(); - assertEquals( - "select u from sec$User u where lower ( u.name) like :name", - res); - - transformer = new QueryTransformerAstBased(model, "select u from sec$User u where u.name=:name"); - - transformer.handleCaseInsensitiveParam("name"); - res = transformer.getResult(); - assertEquals( - "select u from sec$User u where lower ( u.name) = :name", - res); - - transformer = new QueryTransformerAstBased(model, "select u from sec$User u where concat(u.name, ' ', u.login) = :name"); - - transformer.handleCaseInsensitiveParam("name"); - res = transformer.getResult(); - assertEquals( - "select u from sec$User u where concat( lower ( u.name), ' ', lower ( u.login)) = :name", - res); - } - - @Test - public void testAddWhereWithSubquery() throws Exception { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select u from sec$User u"); - transformer.addWhere("{E}.login not like '[hide]'"); - transformer.addWhere("{E}.group.id in (select h.group.id from sec$GroupHierarchy h " + - "where h.group.id = :session$userGroupId or h.parent.id = :session$userGroupId)"); - String res = transformer.getResult(); - assertEquals("select u from sec$User u " + - "where (u.login not like '[hide]') " + - "and (u.group.id in (" + - "select h.group.id from sec$GroupHierarchy h " + - "where h.group.id = :session$userGroupId or h.parent.id = :session$userGroupId))", res); - } - - - @Test - public void testReplaceWithCount_distinct() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select distinct c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - String res = transformer.getResult(); - assertEquals( - "select count(distinct c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - } - - @Test - public void testOrderBy() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.level desc"); - transformer.replaceOrderBy(false, "group"); - String res = transformer.getResult(); - assertEquals("select h from sec$GroupHierarchy h order by h.group", res); - - transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by h.level desc"); - transformer.replaceOrderBy(false, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by c.group", - res); - transformer.replaceOrderBy(true, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by c.group desc", - res); - - - transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by h.level desc, h.createdBy"); - transformer.replaceOrderBy(false, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by c.group", - res); - - transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by h.level desc, h.createdBy"); - transformer.replaceOrderBy(true, "group", "createdBy"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by h.level having h.level > 0 order by c.group desc, c.createdBy desc", - res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); - transformer.replaceOrderBy(true, "token.name", "token.code"); - res = transformer.getResult(); - assertEquals("select h from sec$GroupHierarchy h where h.group = ?1 " + - "order by h.token.name desc, h.token.code desc", res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); - transformer.replaceOrderBy(true, "token.manager.login"); - res = transformer.getResult(); - assertEquals("select h from sec$GroupHierarchy h left join h.token.manager h_token_manager " + - "where h.group = ?1 order by h_token_manager.login desc", res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); - transformer.replaceOrderBy(true, "token.parentToken.name"); - res = transformer.getResult(); - assertEquals("select h from sec$GroupHierarchy h where h.group = ?1 order by h.token.parentToken.name desc", res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.level desc"); - transformer.replaceOrderBy(false, "parent.other.createdBy"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.createdBy", - res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.level desc"); - transformer.replaceOrderBy(false, "parent.other.token.name"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.token.name", - res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.level desc nulls first"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h order by h.level desc nulls first", - res); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.level desc nulls last"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h order by h.level desc nulls last", - res); - } - - @Test - public void testOrderByAssociatedProperty() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h"); - transformer.replaceOrderBy(false, "parent.group"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent h_parent order by h_parent.group", - res); - transformer.reset(); - - transformer.replaceOrderBy(true, "parent.other.group"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.group desc", - res); - transformer.reset(); - - transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h"); - transformer.replaceOrderBy(false, "parent.group", "parent.createdBy"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h left join h.parent h_parent order by h_parent.group, h_parent.createdBy", - res); - - } - - @Test - public void testRemoveDistinct() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select distinct h from sec$GroupHierarchy h"); - transformer.removeDistinct(); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h", - res); - } - - @Test - public void testAddDistinct() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h"); - transformer.addDistinct(); - String res = transformer.getResult(); - assertEquals( - "select distinct h from sec$GroupHierarchy h", - res); - } - - @Test - public void testRemoveOrderBy() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h order by h.createdBy"); - transformer.removeOrderBy(); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h", - res); - } - - @Test - public void testReplaceName() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select h from sec$GroupHierarchy h"); - transformer.replaceEntityName("sec$ExtGroupHierarchy"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$ExtGroupHierarchy h", - res); - } - - @Test - public void testReplaceInCondition() throws RecognitionException { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select u from sec$User u where u.login in (:param)"); - transformer.replaceInCondition("param"); - String res = transformer.getResult(); - assertEquals("select u from sec$User u where 1=0", res); - - transformer = new QueryTransformerAstBased(model, - "select u from sec$User u where u.login not in (:param)"); - transformer.replaceInCondition("param"); - res = transformer.getResult(); - assertEquals("select u from sec$User u where 1=1", res); - } - - @Test - public void transformationsUsingSelectedEntity() throws RecognitionException { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("sec$Car"); - builder.addStringAttribute("model"); - builder.addReferenceAttribute("colour", "sec$Colour"); - JpqlEntityModel car = builder.produce(); - - builder.startNewEntity("sec$Colour"); - builder.addStringAttribute("name"); - builder.addStringAttribute("createdBy"); - builder.addSingleValueAttribute(Integer.class, "version"); - builder.addReferenceAttribute("manufacturer", "Manufacturer"); - JpqlEntityModel colour = builder.produce(); - - JpqlEntityModel manufacturer = builder.produceImmediately("Manufacturer", "companyName"); - DomainModel model = new DomainModel(car, colour, manufacturer); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c.colour from sec$Car c where c.colour.createdBy = :p"); - transformer.addWhere("{E}.colour.createdBy = :session$userLogin"); - - String res = transformer.getResult(); - assertEquals( - "select c.colour from sec$Car c where (c.colour.createdBy = :p) and (c.colour.createdBy = :session$userLogin)", - res); - - - transformer = new QueryTransformerAstBased(model, - "select c.colour from sec$Car c where c.colour.createdBy = :p"); - transformer.addJoinAndWhere("join {E}.manufacturer m", "m.companyName = :par1"); - - res = transformer.getResult(); - assertEquals( - "select c.colour from sec$Car c join c.manufacturer m where (c.colour.createdBy = :p) and (m.companyName = :par1)", - res); - - -//todo eude: fix the following -// transformer = new QueryTransformerAstBased(model, -// "select c.colour from sec$Car c where c.colour.createdBy = :p"); -// transformer.mergeWhere("select gh from sec$Colour gh where gh.version between 1 and 2"); -// -// res = transformer.getResult(); -// assertEquals( -// "select c.colour from sec$Car c where (c.colour.createdBy = :p) and (c.colour.version between 1 and 2)", -// res); - - -// transformer = new QueryTransformerAstBased(model, -// "select c.colour from sec$Car c where c.colour.createdBy = :p order by c.colour.name"); -// transformer.replaceOrderBy(true, "version"); -// -// res = transformer.getResult(); -// assertEquals( -// "select c.colour from sec$Car c left join c.colour c_colour where c.colour.createdBy = :p order by c_colour.version desc", -// res); -// -// -// transformer = new QueryTransformerAstBased(model, -// "select c.colour from sec$Car c where c.colour.createdBy = :p"); -// transformer.replaceWithCount(); -// -// res = transformer.getResult(); -// assertEquals( -// "select count(c.colour) from sec$Car c where c.colour.createdBy = :p", -// res); - } - - @Test - public void testNotCorrectEntityAliasInWhere() { - DomainModel model = prepareDomainModel(); - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - //since 3.4 we don't check equality of targetEntity and an entity in the query - transformer.addWhere("a.createdBy = :par1"); - assertEquals("select c from sec$GroupHierarchy h join h.parent.constraints c where (h.group = ?1) and (a.createdBy = :par1) " + - "group by c.level having c.level > 0 order by c.level", transformer.getResult()); - } - - @Test - public void testAddWhereWithInExpression() throws RecognitionException { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); - transformer.addWhere("{E}.group in (select g.id from sec$GroupHierarchy g where {E} in (g.constraints))"); - - assertEquals("select c from sec$Constraint c " + - "where c.group in (select g.id from sec$GroupHierarchy g where c in ( g.constraints))", transformer.getResult()); - - transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); - transformer.addWhere("{E}.group in (select g.id from sec$GroupHierarchy g where {E}.id in (g.constraints.id))"); - - assertEquals("select c from sec$Constraint c " + - "where c.group in (select g.id from sec$GroupHierarchy g where c.id in ( g.constraints.id))", transformer.getResult()); - - } - - @Test - public void testAddWrongWhere() throws RecognitionException { - try { - DomainModel model = prepareDomainModel(); - - QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); - transformer.addWhere("{E}.group.id == :group"); - fail(); - } catch (JpqlSyntaxException e) { - //expected - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.JpqlSyntaxException; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModelImpl; +import com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased; +import org.antlr.runtime.RecognitionException; +import org.junit.Before; +import org.junit.Test; + +import java.util.Date; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class QueryTransformerAstBasedTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void getResult_noChangesMade() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModelImpl playerEntity = builder.produceImmediately("Player"); + DomainModel model = new DomainModel(playerEntity); + + assertTransformsToSame(model, "SELECT p FROM Player p"); + } + + @Test + public void getResult_noChangesMade_withJoinAndAsAndMemberField() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addReferenceAttribute("as", "Team"); + builder.addReferenceAttribute("member", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT p FROM Player p JOIN p.as t"); + assertTransformsToSame(model, "SELECT p FROM Player p JOIN p.member t"); + } + + @Test + public void getResult_noChangesMade_withJoinAndSeveralJoinConditions() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addStringAttribute("name"); + builder.addReferenceAttribute("as", "Team"); + builder.addReferenceAttribute("member", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT p FROM Player p JOIN Team t on p.member = t and p.name = :param"); + } + + + @Test + public void getResult_noChangesMade_withMultiFieldSelect() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("Team"); + builder.addStringAttribute("name"); + JpqlEntityModel teamEntity = builder.produce(); + + builder.startNewEntity("Player"); + builder.addStringAttribute("nickname"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT p.team.name, p.nickname FROM Player p"); + } + + @Test + public void getResult_noChangesMade_withMultiEntitySelect() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team"); + JpqlEntityModel playerEntity = builder.produceImmediately("Player"); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT p, t FROM Player p, Team t"); + } + + @Test + public void getResult_noChangesMade_withAggregateExpression() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addSingleValueAttribute(Integer.class, "age"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT count(p) FROM Player p"); + assertTransformsToSame(model, "SELECT max(p.age) FROM Player p"); + assertTransformsToSame(model, "SELECT min(p.age) FROM Player p"); + assertTransformsToSame(model, "SELECT avg(p.age) FROM Player p"); + assertTransformsToSame(model, "SELECT sum(p.age) FROM Player p"); + assertTransformsToSame(model, "SELECT max(p.age), t FROM Player p join p.team t group by t"); + assertTransformsToSame(model, "SELECT max(p.age), t.name FROM Player p join p.team t group by t.name"); + } + + @Test + public void getResult_noChangesMade_withMacros() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addSingleValueAttribute(Date.class, "birthDate"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @between(p.birthDate, now-2, now+2, month) "); + String result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where @between ( p.birthDate, now - 2, now + 2, month)", result); + + transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateBefore(p.birthDate, :d) "); + result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where @dateBefore ( p.birthDate, :d)", result); + + transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateAfter(p.birthDate, :d) "); + result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where @dateAfter ( p.birthDate, :d)", result); + + transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @dateEquals(p.birthDate, :d) "); + result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where @dateEquals ( p.birthDate, :d)", result); + + transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where @today(p.birthDate) "); + result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where @today ( p.birthDate)", result); + + } + + @Test + public void getResult_noChangesMade_withWhere() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + + builder.startNewEntity("Player"); + builder.addReferenceAttribute("team", "Team"); + builder.addStringAttribute("name"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "SELECT p FROM Player p where p.name = 'de Souza'"); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p left join p.team as t WHERE t.name = 'KS FC'"); + String result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p left join p.team t WHERE t.name = 'KS FC'", result); + } + + @Test + public void getResult_noChangesMade_withJoin() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); + + builder.startNewEntity("Team"); + builder.addStringAttribute("name"); + builder.addStringAttribute("owner"); + builder.addReferenceAttribute("manager", "Person"); + JpqlEntityModel teamEntity = builder.produce(); + + builder.startNewEntity("Player"); + builder.addStringAttribute("name"); + builder.addStringAttribute("nickname"); + builder.addReferenceAttribute("team", "Team"); + builder.addReferenceAttribute("agent", "Person"); + JpqlEntityModel playerEntity = builder.produce(); + + builder.startNewEntity("League"); + builder.addStringAttribute("name"); + builder.addCollectionReferenceAttribute("teams", "Team"); + JpqlEntityModel leagueEntity = builder.produce(); + + builder.startNewEntity("Country"); + builder.addStringAttribute("flag"); + builder.addReferenceAttribute("league", "League"); + JpqlEntityModel countryEntity = builder.produce(); + + DomainModel model = new DomainModel(teamEntity, playerEntity, leagueEntity, personEntity, countryEntity); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select m.personName from Player p left join p.team.manager as m"); + String result = transformerAstBased.getResult(); + assertEquals("select m.personName from Player p left join p.team.manager m", result); + + transformerAstBased = new QueryTransformerAstBased(model, "select c.flag from Country c join c.league.teams as t join t.manager m"); + assertEquals("select c.flag from Country c join c.league.teams t join t.manager m", + transformerAstBased.getResult()); + } + + @Test + public void getResult_noChangesMade_withLeft_InnerJoinFetch() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); + + builder.startNewEntity("Team"); + builder.addStringAttribute("name"); + builder.addStringAttribute("owner"); + builder.addReferenceAttribute("manager", "Person"); + JpqlEntityModel teamEntity = builder.produce(); + + builder.startNewEntity("Player"); + builder.addStringAttribute("name"); + builder.addStringAttribute("nickname"); + builder.addReferenceAttribute("team", "Team"); + builder.addReferenceAttribute("agent", "Person"); + JpqlEntityModel playerEntity = builder.produce(); + + DomainModel model = new DomainModel(teamEntity, playerEntity, personEntity); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.name from Player p join fetch p.team left join fetch p.agent"); + assertEquals("select p.name from Player p join fetch p.team left join fetch p.agent", + transformerAstBased.getResult()); + + transformerAstBased = new QueryTransformerAstBased(model, "select p.name from Player p left outer join fetch p.team inner join fetch p.agent"); + assertEquals("select p.name from Player p left outer join fetch p.team inner join fetch p.agent", + transformerAstBased.getResult()); + } + + @Test + public void getResult_noChangesMade_withDistinct() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel personEntity = builder.produceImmediately("Person", "personName"); + + builder.startNewEntity("Team"); + builder.addStringAttribute("name"); + builder.addStringAttribute("owner"); + builder.addReferenceAttribute("manager", "Person"); + JpqlEntityModel teamEntity = builder.produce(); + + builder.startNewEntity("Player"); + builder.addStringAttribute("name"); + builder.addStringAttribute("nickname"); + builder.addReferenceAttribute("team", "Team"); + builder.addReferenceAttribute("agent", "Person"); + JpqlEntityModel playerEntity = builder.produce(); + + builder.startNewEntity("League"); + builder.addStringAttribute("name"); + builder.addCollectionReferenceAttribute("teams", "Team"); + JpqlEntityModel leagueEntity = builder.produce(); + + builder.startNewEntity("Country"); + builder.addStringAttribute("flag"); + builder.addReferenceAttribute("league", "League"); + JpqlEntityModel countryEntity = builder.produce(); + + DomainModel model = new DomainModel(teamEntity, playerEntity, leagueEntity, personEntity, countryEntity); + + assertTransformsToSame(model, "select distinct m from Player p left join p.team.manager m"); + } + +// The following functions are not supported by JPA2 JPQL (see jpql21.bnf) +// @Test +// public void getResult_noChangesMade_withSubqueries() throws RecognitionException { +// EntityBuilder builder = new EntityBuilder(); +// JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); +// +// builder.startNewEntity("Player"); +// builder.addStringAttribute("name"); +// builder.addStringAttribute("nickname"); +// builder.addReferenceAttribute("team", "Team"); +// JpqlEntityModel playerEntity = builder.produce(); +// +// DomainModel model = new DomainModel(playerEntity, teamEntity); +// +// assertTransformsToSame(model, "select p.name from (select t.name from Team t) p"); +// assertTransformsToSame(model, "select p.owner from (select t.name, t.owner from Team t) p"); +// assertTransformsToSame(model, "select g.owner from (select t.name, t.owner from Team t) p, (select t.name from Team t) g"); +// } + +// The following functions are not supported by JPA2 JPQL (see jpql21.bnf) +// @Test +// public void getResult_noChangesMade_severalLevelsOfSubquery() throws RecognitionException { +// EntityBuilder builder = new EntityBuilder(); +// JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); +// +// builder.startNewEntity("Player"); +// builder.addStringAttribute("name"); +// builder.addStringAttribute("nickname"); +// builder.addReferenceAttribute("team", "Team"); +// JpqlEntityModel playerEntity = builder.produce(); +// +// DomainModel model = new DomainModel(playerEntity, teamEntity); +// +// assertTransformsToSame(model, "select p.owner from (select t from Team t where t.name in (select a.name from Player a)) p"); +// // 'as' опускается +// QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "select p.owner from (select t.owner from Team as t where t.name = '1') p", "AsdfAsdfAsdf"); +// String result = transformerAstBased.getResult(); +// assertEquals("select p.owner from (select t.owner from Team t where t.name = '1') p", result); +// } + + @Test + public void getResult_noChangesMade_subqueries() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name", "owner"); + + builder.startNewEntity("Player"); + builder.addStringAttribute("name"); + builder.addStringAttribute("nickname"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + + DomainModel model = new DomainModel(playerEntity, teamEntity); + + assertTransformsToSame(model, "select p.owner from Player pl where exists (select t from Team t where t.name = 'Team1' and pl.team.id = t.id)"); + assertTransformsToSame(model, "select p.owner from Player pl where pl.team.id in (select t.id from Team t where t.name = 'Team1')"); + assertTransformsToSame(model, "select t.name from Team t where (select count(p) from Player p where p.team.id = t.id) > 10"); + } + + @Test + public void getResult_noChangesMade_withParameters() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname"); + + DomainModel model = new DomainModel(playerEntity); + + assertTransformsToSame(model, "select p.nickname from Player p where p.name = :name"); + assertTransformsToSame(model, "select p.nickname from Player p where p.name = :name or p.name = :name2"); + assertTransformsToSame(model, "select p.nickname from Player p where p.name = ?1 or p.name = ?2"); + + assertTransformsToSame(model, "select p.nickname from Player p where p.name like :component$playersFilter.name52981"); + } + + @Test + public void getResult_noChangesMade_with_in_collections() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel driver = builder.produceImmediately("Driver", "name", "signal"); + + builder.startNewEntity("HomeBase"); + builder.addStringAttribute("city"); + JpqlEntityModel homeBase = builder.produce(); + + builder.startNewEntity("Car"); + builder.addStringAttribute("model"); + builder.addCollectionReferenceAttribute("drivers", "Driver"); + builder.addReferenceAttribute("station", "HomeBase"); + JpqlEntityModel car = builder.produce(); + DomainModel model = new DomainModel(car, driver, homeBase); + + assertTransformsToSame(model, "select d.name from Car c, in(c.drivers) d where d.name = ?1"); + + assertTransformsToSame(model, "select d.name from Car c join c.station s, in(c.drivers) d where d.name = ?1 and s.city = :par2"); + } + + @Test + public void getResult_noChangesMade_withGroupBy() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); + + DomainModel model = new DomainModel(playerEntity); + assertTransformsToSame(model, "select p from Player p group by p.level, p.name"); + + assertTransformsToSame(model, "select p from Player p group by p.level"); + } + + @Test + public void getResult_noChangesMade_withGroupByHavingOrderBy() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); + + builder.startNewEntity("Team"); + builder.addCollectionReferenceAttribute("players", "Player"); + builder.addStringAttribute("title"); + JpqlEntityModel team = builder.produce(); + + DomainModel model = new DomainModel(playerEntity, team); + assertTransformsToSame(model, "select p from Team t join t.players p " + + "group by p.level having p.level > 0 order by p.level"); + } + + private void assertTransformsToSame(DomainModel model, String query) throws RecognitionException { + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, query); + String result = transformerAstBased.getResult(); + assertEquals(query, result); + } + + @Test + public void test() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par" + ); + + transformer.addWhere("{E}.createdBy = :par1"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = :par) and (h.createdBy = :par1)", + res); + + transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = ?1 " + + "group by c.level having c.level > 0 order by c.level" + ); + + transformer.addWhere("{E}.createdBy = :par1"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = ?1) " + + "and (h.createdBy = :par1) group by c.level having c.level > 0 order by c.level", + res); + Set set = transformer.getAddedParams(); + assertEquals(1, set.size()); + assertEquals("par1", set.iterator().next()); + + transformer.addWhere("({E}.updatedBy = :par2 and {E}.groupId = :par3)"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where ((h.userGroup = ?1) " + + "and (h.createdBy = :par1)) and ((h.updatedBy = :par2 and h.groupId = :par3)) group by c.level having c.level > 0 order by c.level", + res); + set = transformer.getAddedParams(); + assertEquals(3, set.size()); + + transformer.reset(); + + transformer.mergeWhere("select gh from sec$GroupHierarchy gh where gh.version between 1 and 2"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = ?1) " + + "and (h.version between 1 and 2) group by c.level having c.level > 0 order by c.level", + res); + } + + @Test + public void addWhereAsId() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par" + ); + + transformer.addWhereAsIs("a.createdBy = :par1"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.userGroup = :par) " + + "and (a.createdBy = :par1)", + res); + } + + @Test + public void getResult_noChangesMade_parametersWithDot() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addSingleValueAttribute(Date.class, "birthDate"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p where p.birthDate = :d.option"); + String result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p where p.birthDate = :d.option", result); + } + + @Test + public void getResult_noChangesMade_orderBySeveralFields() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel teamEntity = builder.produceImmediately("Team", "name"); + builder.startNewEntity("Player"); + builder.addSingleValueAttribute(Date.class, "birthDate"); + builder.addStringAttribute("surname"); + builder.addReferenceAttribute("team", "Team"); + JpqlEntityModel playerEntity = builder.produce(); + DomainModel model = new DomainModel(playerEntity, teamEntity); + + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "SELECT p FROM Player p order by p.birthDate, p.surname"); + String result = transformerAstBased.getResult(); + assertEquals("SELECT p FROM Player p order by p.birthDate, p.surname", result); + } + + @Test + public void getResult_noChangesMade_join_fetch() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h join fetch h.parent.constraints where h.userGroup = :par" + ); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join fetch h.parent.constraints where h.userGroup = :par", + res); + } + + @Test + public void getResult_noChangesMade_update() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("sec$Car"); + builder.addStringAttribute("model"); + builder.addStringAttribute("vin"); + JpqlEntityModel car = builder.produce(); + DomainModel model = new DomainModel(car); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "update sec$Car c set c.model = :model, c.vin = :vin" + ); + assertEquals( + "update sec$Car c set c.model=:model,c.vin=:vin", + transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, + "update sec$Car c set c.model = :model, c.vin = :vin where c.vin = :oldVin" + ); + assertEquals( + "update sec$Car c set c.model=:model,c.vin=:vin where c.vin = :oldVin", + transformer.getResult()); + } + + @Test + public void getResult_noChangesMade_delete() throws Exception { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(model, "delete from sec$GroupHierarchy g where g.createdBy = :createdBy"); + assertEquals(transformerAstBased.getResult(), "delete from sec$GroupHierarchy g where g.createdBy = :createdBy"); + } + + @Test + public void getResult_noChangesMade_AsInSelect() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + JpqlEntityModel playerEntity = builder.produceImmediately("Player", "name", "nickname", "level"); + + DomainModel model = new DomainModel(playerEntity); + assertTransformsToSame(model, "select p.name as name, p.nickname as nickname from Player p"); + assertTransformsToSame(model, "select p.name as name from Player p"); + } + + + @Test + public void addJoinAsId() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par" + ); + + transformer.addJoinAsIs("join a.parent.constraints c"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$Constraint u, sec$GroupHierarchy h join a.parent.constraints c where h.userGroup = :par", + res); + } + + @Test + public void addJoinOn() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par" + ); + + transformer.addJoinAsIs("join sec$Constraint c on c.group.id = h.parent.id"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$Constraint u, sec$GroupHierarchy h join sec$Constraint c on c.group.id = h.parent.id where h.userGroup = :par", + res); + } + + @Test + public void addWhere_with_child_select() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("Car"); + builder.addStringAttribute("model"); + builder.addReferenceAttribute("driver", "Person"); + JpqlEntityModel car = builder.produce(); + + JpqlEntityModel person = builder.produceImmediately("Person", "fullname"); + DomainModel model = new DomainModel(car, person); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select car.driver from Car car"); + transformer.addWhere("{E}.model = ?1"); + assertEquals("select car.driver from Car car where car.model = ?1", + transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, + "select car.driver from Car car"); + transformer.addWhere("{E}.driver.fullname = ?1"); + assertEquals("select car.driver from Car car where car.driver.fullname = ?1", + transformer.getResult()); + } + + + private DomainModel prepareDomainModel() { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("sec$GroupHierarchy"); + builder.addStringAttribute("group"); + builder.addStringAttribute("createdBy"); + builder.addReferenceAttribute("parent", "sec$GroupHierarchy"); + builder.addReferenceAttribute("other", "sec$GroupHierarchy"); + builder.addReferenceAttribute("token", "fake$EmbeddedToken", "token", true); + + builder.addCollectionReferenceAttribute("constraints", "sec$Constraint"); + JpqlEntityModel groupHierarchy = builder.produce(); + + builder = new EntityBuilder(); + builder.startNewEntity("sec$Constraint"); + builder.addReferenceAttribute("group", "sec$GroupHierarchy"); + JpqlEntityModel constraintEntity = builder.produce(); + + JpqlEntityModel userEntity = builder.produceImmediately("sec$User", "login"); + + builder = new EntityBuilder(); + builder.startNewEntity("fake$EmbeddedToken"); + builder.addStringAttribute("name"); + builder.addStringAttribute("code"); + builder.addReferenceAttribute("manager", "sec$User"); + builder.addReferenceAttribute("parentToken", "fake$EmbeddedToken", "parentToken", true); + JpqlEntityModel token = builder.produce(); + + return new DomainModel(groupHierarchy, constraintEntity, userEntity, token); + } + + @Test + public void testAliasPlaceholder() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par" + ); + + transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = :par2"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + + " and h.updatedBy = :par2)", + res); + + //////////////////////////////////// + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = :par" + ); + + transformer.addJoinAndWhere("join h.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + + " and h.updatedBy = :par2 and c.createTs = :par3)", + res); + + //////////////////////////////////// + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = :par" + ); + + transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (h.createdBy = :par1" + + " and h.updatedBy = :par2 and c.createTs = :par3)", + res); + } + +//todo eude : fix the following +// @Test +// public void testInvalidEntity() throws RecognitionException { +// DomainModel model = prepareDomainModel(); +// +// QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, +// "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + +// "group by c.level having c.level > 0 order by c.level"); +// try { +// transformer.addWhere("a.createdBy = :par1"); +// fail(); +// } catch (Exception e) { +// assertTrue(e instanceof RuntimeException); +// } +// } + + @Test + public void addWhere_adds_Where_IfNeeded() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h"); + transformer.addWhere("h.group = ?1"); + assertEquals("select h from sec$GroupHierarchy h where h.group = ?1", + transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h join h.parent.constraints c"); + transformer.addWhere("h.group = ?1"); + assertEquals("select h from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1", + transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h join h.parent.constraints c group by c.level having c.level > 0 order by c.level"); + transformer.addWhere("h.group = ?1"); + assertEquals("select h from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 group by c.level having c.level > 0 order by c.level", + transformer.getResult()); + } + +//todo eude : fix the following +// @Test +// public void addWhere_onIncorrectHavingInTheEnd() throws RecognitionException { +// DomainModel model = prepareDomainModel(); +// +// try { +// new QueryTransformerAstBased(model, +// "select h from sec$GroupHierarchy h join h.parent.constraints c group by c.level order by c.level having c.level > 0"); +// fail("Incorrectly placed 'having' passed"); +// } catch (JpqlSyntaxException e) { +// //expected +// } +// } + + @Test + public void addWhere_onIncorrectQuery() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + try { + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h join h.parent.constraints"); + transformer.getResult(); + fail("Not named join variable passed"); + } catch (JpqlSyntaxException e) { + //expected + } + } + + @Test + public void testJoin() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = :par"); + + transformer.addJoinAndWhere("join h.parent.constraints c", "c.createdBy = :par2"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints c where (h.group = :par) and (c.createdBy = :par2)", + res); + + transformer.reset(); + transformer.addJoinAndWhere("left join h.parent.constraints c", "c.createdBy = :par2"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent.constraints c where (h.group = :par) and (c.createdBy = :par2)", + res); + + transformer.reset(); + transformer.addJoinAndWhere(",sec$Constraint c", "c.createdBy = :par2"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h, sec$Constraint c where (h.group = :par) and (c.createdBy = :par2)", + res); + } + + @Test + public void testDoubleJoins() throws Exception { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = :par"); + + transformer.reset(); + transformer.addJoinAndWhere("join h.parent.constraints c1 join h.constraints c2", "c.createdBy = :par2"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints c1 join h.constraints c2 where (h.group = :par) and (c.createdBy = :par2)", + res); + + transformer.reset(); + transformer.addJoinAndWhere("join {E}.parent p join p.constraints cr", "c.createdBy = :par2"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent p join p.constraints cr where (h.group = :par) and (c.createdBy = :par2)", + res); + + transformer.reset(); + transformer.addJoinAndWhere("join replaceEntity.parent p join p.constraints cr", "c.createdBy = :par2"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent p join p.constraints cr where (h.group = :par) and (c.createdBy = :par2)", + res); + } + + @Test + public void testJoin_WithComma() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = :par"); + transformer.addJoinAndWhere("join h.parent.constraints pco, sec$Constraint sc", "1 = 1"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints pco, sec$Constraint sc where (h.group = :par) and (1 = 1)", + res); + + + transformer.reset(); + transformer.addJoinAsIs("join h.parent.constraints pco, sec$Constraint sc"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints pco, sec$Constraint sc where h.group = :par", + res); + + } + + // todo eude : fix the following + @Test + public void join_with_in_collections() throws RecognitionException { +// EntityBuilder builder = new EntityBuilder(); +// +// builder.startNewEntity("HomeBase"); +// builder.addStringAttribute("name"); +// JpqlEntityModel homeBase = builder.produce(); +// +// builder.startNewEntity("Driver"); +// builder.addStringAttribute("name"); +// builder.addStringAttribute("signal"); +// builder.addReferenceAttribute("home", "HomeBase"); +// JpqlEntityModel driver = builder.produce(); +// +// builder.startNewEntity("Car"); +// builder.addStringAttribute("model"); +// builder.addCollectionReferenceAttribute("drivers", "Driver"); +// builder.addReferenceAttribute("station", "HomeBase"); +// JpqlEntityModel car = builder.produce(); +// DomainModel model = new DomainModel(car, driver, homeBase); +// +// QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, +// "select d.name from Car c, in(c.drivers) d where d.signal = ?1"); +// +// transformer.addJoinAndWhere("join d.home h", "h.name = :par2"); +// String res = transformer.getResult(); +// assertEquals( +// "select d.name from Car c, in(c.drivers) d join d.home h where (d.signal = ?1) and (h.name = :par2)", +// res); +// +// transformer = new QueryTransformerAstBased(model, +// "select d.name from Car c, in(c.drivers) d where d.signal = ?1"); +// transformer.addJoinAndWhere("join c.station h", "h.name = :par2"); +// res = transformer.getResult(); +// assertEquals( +// "select d.name from Car c join c.station h, in(c.drivers) d where (d.signal = ?1) and (h.name = :par2)", +// res); +// +// transformer = new QueryTransformerAstBased(model, +// "select c, d from Car c, Driver d where d.signal = ?1"); +// +// transformer.addJoinAndWhere("join d.station h", "h.name = :par2"); +// res = transformer.getResult(); +// assertEquals( +// "select c, d from Car c join c.station h, Driver d where (d.signal = ?1) and (h.name = :par2)", +// res); +// +// transformer = new QueryTransformerAstBased(model, +// "select c, d from Car c, Driver d where d.signal = ?1"); +// transformer.addJoinAndWhere("join d.home h", "h.name = :par2"); +// res = transformer.getResult(); +// assertEquals( +// "select c, d from Car c, Driver d join d.home h where (d.signal = ?1) and (h.name = :par2)", +// res); + } + + @Test + public void testReplaceWithCount() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + assertEquals( + "select count(c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + assertEquals( + "select count(c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + transformer.getResult()); + } + + @Test + public void testHandleCaseInsensitiveParam() throws Exception { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select u from sec$User u where u.name like :name"); + transformer.handleCaseInsensitiveParam("name"); + String res = transformer.getResult(); + assertEquals( + "select u from sec$User u where lower ( u.name) like :name", + res); + + transformer = new QueryTransformerAstBased(model, "select u from sec$User u where u.name=:name"); + + transformer.handleCaseInsensitiveParam("name"); + res = transformer.getResult(); + assertEquals( + "select u from sec$User u where lower ( u.name) = :name", + res); + + transformer = new QueryTransformerAstBased(model, "select u from sec$User u where concat(u.name, ' ', u.login) = :name"); + + transformer.handleCaseInsensitiveParam("name"); + res = transformer.getResult(); + assertEquals( + "select u from sec$User u where concat( lower ( u.name), ' ', lower ( u.login)) = :name", + res); + } + + @Test + public void testAddWhereWithSubquery() throws Exception { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select u from sec$User u"); + transformer.addWhere("{E}.login not like '[hide]'"); + transformer.addWhere("{E}.group.id in (select h.group.id from sec$GroupHierarchy h " + + "where h.group.id = :session$userGroupId or h.parent.id = :session$userGroupId)"); + String res = transformer.getResult(); + assertEquals("select u from sec$User u " + + "where (u.login not like '[hide]') " + + "and (u.group.id in (" + + "select h.group.id from sec$GroupHierarchy h " + + "where h.group.id = :session$userGroupId or h.parent.id = :session$userGroupId))", res); + } + + + @Test + public void testReplaceWithCount_distinct() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select distinct c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + String res = transformer.getResult(); + assertEquals( + "select count(distinct c) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + } + + @Test + public void testOrderBy() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.level desc"); + transformer.replaceOrderBy(false, "group"); + String res = transformer.getResult(); + assertEquals("select h from sec$GroupHierarchy h order by h.group", res); + + transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by h.level desc"); + transformer.replaceOrderBy(false, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by c.group", + res); + transformer.replaceOrderBy(true, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by c.group desc", + res); + + + transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by h.level desc, h.createdBy"); + transformer.replaceOrderBy(false, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by c.group", + res); + + transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by h.level desc, h.createdBy"); + transformer.replaceOrderBy(true, "group", "createdBy"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by h.level having h.level > 0 order by c.group desc, c.createdBy desc", + res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); + transformer.replaceOrderBy(true, "token.name", "token.code"); + res = transformer.getResult(); + assertEquals("select h from sec$GroupHierarchy h where h.group = ?1 " + + "order by h.token.name desc, h.token.code desc", res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); + transformer.replaceOrderBy(true, "token.manager.login"); + res = transformer.getResult(); + assertEquals("select h from sec$GroupHierarchy h left join h.token.manager h_token_manager " + + "where h.group = ?1 order by h_token_manager.login desc", res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h where h.group = ?1 order by h.level desc, h.createdBy"); + transformer.replaceOrderBy(true, "token.parentToken.name"); + res = transformer.getResult(); + assertEquals("select h from sec$GroupHierarchy h where h.group = ?1 order by h.token.parentToken.name desc", res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.level desc"); + transformer.replaceOrderBy(false, "parent.other.createdBy"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.createdBy", + res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.level desc"); + transformer.replaceOrderBy(false, "parent.other.token.name"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.token.name", + res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.level desc nulls first"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h order by h.level desc nulls first", + res); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.level desc nulls last"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h order by h.level desc nulls last", + res); + } + + @Test + public void testOrderByAssociatedProperty() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h"); + transformer.replaceOrderBy(false, "parent.group"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent h_parent order by h_parent.group", + res); + transformer.reset(); + + transformer.replaceOrderBy(true, "parent.other.group"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent h_parent left join h_parent.other h_parent_other order by h_parent_other.group desc", + res); + transformer.reset(); + + transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h"); + transformer.replaceOrderBy(false, "parent.group", "parent.createdBy"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h left join h.parent h_parent order by h_parent.group, h_parent.createdBy", + res); + + } + + @Test + public void testRemoveDistinct() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select distinct h from sec$GroupHierarchy h"); + transformer.removeDistinct(); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h", + res); + } + + @Test + public void testAddDistinct() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h"); + transformer.addDistinct(); + String res = transformer.getResult(); + assertEquals( + "select distinct h from sec$GroupHierarchy h", + res); + } + + @Test + public void testRemoveOrderBy() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h order by h.createdBy"); + transformer.removeOrderBy(); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h", + res); + } + + @Test + public void testReplaceName() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select h from sec$GroupHierarchy h"); + transformer.replaceEntityName("sec$ExtGroupHierarchy"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$ExtGroupHierarchy h", + res); + } + + @Test + public void testReplaceInCondition() throws RecognitionException { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select u from sec$User u where u.login in (:param)"); + transformer.replaceInCondition("param"); + String res = transformer.getResult(); + assertEquals("select u from sec$User u where 1=0", res); + + transformer = new QueryTransformerAstBased(model, + "select u from sec$User u where u.login not in (:param)"); + transformer.replaceInCondition("param"); + res = transformer.getResult(); + assertEquals("select u from sec$User u where 1=1", res); + } + + @Test + public void transformationsUsingSelectedEntity() throws RecognitionException { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("sec$Car"); + builder.addStringAttribute("model"); + builder.addReferenceAttribute("colour", "sec$Colour"); + JpqlEntityModel car = builder.produce(); + + builder.startNewEntity("sec$Colour"); + builder.addStringAttribute("name"); + builder.addStringAttribute("createdBy"); + builder.addSingleValueAttribute(Integer.class, "version"); + builder.addReferenceAttribute("manufacturer", "Manufacturer"); + JpqlEntityModel colour = builder.produce(); + + JpqlEntityModel manufacturer = builder.produceImmediately("Manufacturer", "companyName"); + DomainModel model = new DomainModel(car, colour, manufacturer); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c.colour from sec$Car c where c.colour.createdBy = :p"); + transformer.addWhere("{E}.colour.createdBy = :session$userLogin"); + + String res = transformer.getResult(); + assertEquals( + "select c.colour from sec$Car c where (c.colour.createdBy = :p) and (c.colour.createdBy = :session$userLogin)", + res); + + + transformer = new QueryTransformerAstBased(model, + "select c.colour from sec$Car c where c.colour.createdBy = :p"); + transformer.addJoinAndWhere("join {E}.manufacturer m", "m.companyName = :par1"); + + res = transformer.getResult(); + assertEquals( + "select c.colour from sec$Car c join c.manufacturer m where (c.colour.createdBy = :p) and (m.companyName = :par1)", + res); + + +//todo eude: fix the following +// transformer = new QueryTransformerAstBased(model, +// "select c.colour from sec$Car c where c.colour.createdBy = :p"); +// transformer.mergeWhere("select gh from sec$Colour gh where gh.version between 1 and 2"); +// +// res = transformer.getResult(); +// assertEquals( +// "select c.colour from sec$Car c where (c.colour.createdBy = :p) and (c.colour.version between 1 and 2)", +// res); + + +// transformer = new QueryTransformerAstBased(model, +// "select c.colour from sec$Car c where c.colour.createdBy = :p order by c.colour.name"); +// transformer.replaceOrderBy(true, "version"); +// +// res = transformer.getResult(); +// assertEquals( +// "select c.colour from sec$Car c left join c.colour c_colour where c.colour.createdBy = :p order by c_colour.version desc", +// res); +// +// +// transformer = new QueryTransformerAstBased(model, +// "select c.colour from sec$Car c where c.colour.createdBy = :p"); +// transformer.replaceWithCount(); +// +// res = transformer.getResult(); +// assertEquals( +// "select count(c.colour) from sec$Car c where c.colour.createdBy = :p", +// res); + } + + @Test + public void testNotCorrectEntityAliasInWhere() { + DomainModel model = prepareDomainModel(); + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + //since 3.4 we don't check equality of targetEntity and an entity in the query + transformer.addWhere("a.createdBy = :par1"); + assertEquals("select c from sec$GroupHierarchy h join h.parent.constraints c where (h.group = ?1) and (a.createdBy = :par1) " + + "group by c.level having c.level > 0 order by c.level", transformer.getResult()); + } + + @Test + public void testAddWhereWithInExpression() throws RecognitionException { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); + transformer.addWhere("{E}.group in (select g.id from sec$GroupHierarchy g where {E} in (g.constraints))"); + + assertEquals("select c from sec$Constraint c " + + "where c.group in (select g.id from sec$GroupHierarchy g where c in ( g.constraints))", transformer.getResult()); + + transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); + transformer.addWhere("{E}.group in (select g.id from sec$GroupHierarchy g where {E}.id in (g.constraints.id))"); + + assertEquals("select c from sec$Constraint c " + + "where c.group in (select g.id from sec$GroupHierarchy g where c.id in ( g.constraints.id))", transformer.getResult()); + + } + + @Test + public void testAddWrongWhere() throws RecognitionException { + try { + DomainModel model = prepareDomainModel(); + + QueryTransformerAstBased transformer = new QueryTransformerAstBased(model, "select c from sec$Constraint c"); + transformer.addWhere("{E}.group.id == :group"); + fail(); + } catch (JpqlSyntaxException e) { + //expected + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerRegexTest.java b/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerRegexTest.java index 800ecd148f..a69a56e5e2 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerRegexTest.java +++ b/modules/core/test/com/haulmont/cuba/core/global/QueryTransformerRegexTest.java @@ -1,446 +1,446 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import junit.framework.TestCase; - -import java.util.Set; - -public class QueryTransformerRegexTest extends TestCase { - - public void test() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par"); - - transformer.addWhere("{E}.createdBy = :par1"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1)", - res); - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - - transformer.addWhere("{E}.createdBy = :par1"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "and (h.createdBy = :par1) group by c.level having c.level > 0 order by c.level", - res); - Set set = transformer.getAddedParams(); - assertEquals(1, set.size()); - assertEquals("par1", set.iterator().next()); - - transformer.addWhere("({E}.updatedBy = :par2 and {E}.groupId = :par3)"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "and (h.createdBy = :par1) and ((h.updatedBy = :par2 and h.groupId = :par3)) group by c.level having c.level > 0 order by c.level", - res); - set = transformer.getAddedParams(); - assertEquals(3, set.size()); - - transformer.reset(); - - transformer.mergeWhere("select h from sec$GroupHierarchy h where h.version between 1 and 2"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "and (h.version between 1 and 2) group by c.level having c.level > 0 order by c.level", - res); - - } - - public void testAliasPlaceholder() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par"); - - transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = :par2"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + - " and h.updatedBy = :par2)", - res); - - //////////////////////////////////// - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h where h.group = :par"); - - transformer.addJoinAndWhere("join h.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + - " and h.updatedBy = :par2 and c.createTs = :par3)", - res); - - //////////////////////////////////// - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h where h.group = :par"); - - transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + - " and h.updatedBy = :par2 and c.createTs = :par3)", - res); - } - - - public void testNotCorrectEntityAliasInWhere() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - //since 3.4 we don't check equality of targetEntity and an entity in the query - transformer.addWhere("a.createdBy = :par1"); - assertEquals("select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 and (a.createdBy = :par1) " + - "group by c.level having c.level > 0 order by c.level", transformer.getResult()); - } - - public void testJoin() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h where h.group = :par"); - - transformer.addJoinAndWhere("join h.parent.constraints c", "c.createdBy = :par2"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (c.createdBy = :par2)", - res); - } - - public void testReplaceWithCount() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - String res = transformer.getResult(); - assertEquals( - "select count(h) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - - transformer = new QueryTransformerRegex( - "select h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - res = transformer.getResult(); - assertEquals( - "select count(h.group) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - - transformer = new QueryTransformerRegex( - "select distinct h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithCount(); - res = transformer.getResult(); - assertEquals( - "select count(distinct h.group) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - } - - public void testReplaceWithSelectId() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithSelectId(); - String res = transformer.getResult(); - assertEquals( - "select h.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - - transformer = new QueryTransformerRegex( - "select h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithSelectId(); - res = transformer.getResult(); - assertEquals( - "select h.group.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - - transformer = new QueryTransformerRegex( - "select distinct h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceWithSelectId(); - res = transformer.getResult(); - assertEquals( - "select distinct h.group.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0", - res); - } - - public void testOrderBy() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by c.level"); - transformer.replaceOrderBy(false, "group"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group", - res); - transformer.replaceOrderBy(true, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group desc", - res); - } - - public void testOrderByAscDesc() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group asc"); - transformer.replaceOrderBy(true, "group"); - String res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group desc", - res); - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group desc"); - transformer.replaceOrderBy(false, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group", - res); - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group desc"); - transformer.replaceOrderBy(true, "group"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + - "group by c.level having c.level > 0 order by h.group desc", - res); - } - - public void testOrderByAssociatedProperty() { - // first level of association - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from ref$Car c where c.deleteTs is null"); - transformer.replaceOrderBy(false, "model.numberOfSeats"); - String res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats", - res); - transformer.replaceOrderBy(true, "model.numberOfSeats"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats desc", - res); - - // second level of association - transformer = new QueryTransformerRegex( - "select c from ref$Car c where c.deleteTs is null"); - transformer.replaceOrderBy(false, "model.manufacturer.name"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model.manufacturer c_model_manufacturer where c.deleteTs is null order by c_model_manufacturer.name", - res); - transformer.replaceOrderBy(true, "model.manufacturer.name"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model.manufacturer c_model_manufacturer where c.deleteTs is null order by c_model_manufacturer.name desc", - res); - } - - public void testOrderBySeveralProperties() throws Exception { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select c from ref$Car c where c.deleteTs is null"); - - - transformer.replaceOrderBy(false, "createTs", "vin"); - String res = transformer.getResult(); - assertEquals( - "select c from ref$Car c where c.deleteTs is null order by c.createTs, c.vin", - res); - - transformer.replaceOrderBy(false, "vin", "model.numberOfSeats"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c.vin, c_model.numberOfSeats", - res); - - transformer.replaceOrderBy(true, "vin", "model.numberOfSeats"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c.vin desc, c_model.numberOfSeats desc", - res); - - transformer.replaceOrderBy(false, "model.numberOfSeats", "vin"); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats, c.vin", - res); - } - - public void testRemoveDistinct() { - QueryTransformerRegex transformer; - String res; - - transformer = new QueryTransformerRegex( - "select c from ref$Car c where c.deleteTs is null"); - transformer.removeDistinct(); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c where c.deleteTs is null", - res); - - transformer = new QueryTransformerRegex( - "select distinct c from ref$Car c where c.deleteTs is null"); - transformer.removeDistinct(); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c where c.deleteTs is null", - res); - - transformer = new QueryTransformerRegex( - "select distinct c from ref$Car c where c.deleteTs is null"); - transformer.removeDistinct(); - res = transformer.getResult(); - assertEquals( - "select c from ref$Car c where c.deleteTs is null", - res); - } - - public void testReplaceEntityName() { - QueryTransformerRegex transformer; - String res; - - transformer = new QueryTransformerRegex( - "select c from ref$Car c where c.deleteTs is null"); - transformer.replaceEntityName("ref$ExtCar"); - res = transformer.getResult(); - assertEquals( - "select c from ref$ExtCar c where c.deleteTs is null", - res); - } - - public void testSubQueriesAddWhere() { - QueryTransformerRegex transformer; - String res; - - transformer = new QueryTransformerRegex( - "select h from sec$GroupHierarchy h where h.group = :par"); - - transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = (select u.login from sec$User u where u.login = :par2) and {E}.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h where h.group = :par and (h.createdBy = :par1" + - " and h.updatedBy = (select u.login from sec$User u where u.login = :par2) and h.createTs = :par3)", - res); - } - - public void testSubQueriesAddJoinAndWhere() { - QueryTransformerRegex transformer; - String res; - - transformer = new QueryTransformerRegex( - "select c from sec$GroupHierarchy h where h.group = :par"); - - transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = " + - "(select u.login from sec$User u where u.login = {E}.param) and c.createTs = :par3"); - res = transformer.getResult(); - assertEquals( - "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + - " and h.updatedBy = (select u.login from sec$User u where u.login = h.param) and c.createTs = :par3)", - res); - } - - public void testHandleCaseInsensitiveParam() throws Exception { - QueryTransformerRegex transformer; - String res; - - transformer = new QueryTransformerRegex("select u from sec$User u where u.name like :name"); - - transformer.handleCaseInsensitiveParam("name"); - res = transformer.getResult(); - assertEquals( - "select u from sec$User u where lower(u.name) like :name", - res); - - transformer = new QueryTransformerRegex("select u from sec$User u where u.name=:name"); - - transformer.handleCaseInsensitiveParam("name"); - res = transformer.getResult(); - assertEquals( - "select u from sec$User u where lower(u.name)=:name", - res); - } - - public void testJoinAsIs() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select h from sec$GroupHierarchy h, sec$Constraint u where h.userGroup = :par"); - - transformer.addJoinAsIs("join h.parent.constraints c"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$GroupHierarchy h join h.parent.constraints c, sec$Constraint u where h.userGroup = :par", - res); - } - - public void testJoinAsIs2() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); - - transformer.addJoinAsIs("join h.parent.constraints c"); - String res = transformer.getResult(); - assertEquals( - "select h from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", - res); - } - - public void testJoinAsIs3() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select h.level from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); - - transformer.addJoinAsIs("join h.parent.constraints c"); - String res = transformer.getResult(); - assertEquals( - "select h.level from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", - res); - } - - public void testJoinAsIs4() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "SELECT distinct h.level from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); - - transformer.addJoinAsIs("join h.parent.constraints c"); - String res = transformer.getResult(); - assertEquals( - "SELECT distinct h.level from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", - res); - } - - public void testNpeInReplaceOrderBy() { - QueryTransformerRegex transformer = new QueryTransformerRegex( - "select drB from taxi$DriverBan drB where drB.driver.id = :ds_driverDs order by drB.from"); - String[] properties = new String[]{"driver.name", "driver.callsignName"}; - - transformer.replaceOrderBy(true, properties); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import junit.framework.TestCase; + +import java.util.Set; + +public class QueryTransformerRegexTest extends TestCase { + + public void test() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par"); + + transformer.addWhere("{E}.createdBy = :par1"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1)", + res); + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + + transformer.addWhere("{E}.createdBy = :par1"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "and (h.createdBy = :par1) group by c.level having c.level > 0 order by c.level", + res); + Set set = transformer.getAddedParams(); + assertEquals(1, set.size()); + assertEquals("par1", set.iterator().next()); + + transformer.addWhere("({E}.updatedBy = :par2 and {E}.groupId = :par3)"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "and (h.createdBy = :par1) and ((h.updatedBy = :par2 and h.groupId = :par3)) group by c.level having c.level > 0 order by c.level", + res); + set = transformer.getAddedParams(); + assertEquals(3, set.size()); + + transformer.reset(); + + transformer.mergeWhere("select h from sec$GroupHierarchy h where h.version between 1 and 2"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "and (h.version between 1 and 2) group by c.level having c.level > 0 order by c.level", + res); + + } + + public void testAliasPlaceholder() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par"); + + transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = :par2"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + + " and h.updatedBy = :par2)", + res); + + //////////////////////////////////// + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h where h.group = :par"); + + transformer.addJoinAndWhere("join h.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + + " and h.updatedBy = :par2 and c.createTs = :par3)", + res); + + //////////////////////////////////// + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h where h.group = :par"); + + transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = :par2 and c.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + + " and h.updatedBy = :par2 and c.createTs = :par3)", + res); + } + + + public void testNotCorrectEntityAliasInWhere() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + //since 3.4 we don't check equality of targetEntity and an entity in the query + transformer.addWhere("a.createdBy = :par1"); + assertEquals("select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 and (a.createdBy = :par1) " + + "group by c.level having c.level > 0 order by c.level", transformer.getResult()); + } + + public void testJoin() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h where h.group = :par"); + + transformer.addJoinAndWhere("join h.parent.constraints c", "c.createdBy = :par2"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (c.createdBy = :par2)", + res); + } + + public void testReplaceWithCount() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + String res = transformer.getResult(); + assertEquals( + "select count(h) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + + transformer = new QueryTransformerRegex( + "select h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + res = transformer.getResult(); + assertEquals( + "select count(h.group) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + + transformer = new QueryTransformerRegex( + "select distinct h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithCount(); + res = transformer.getResult(); + assertEquals( + "select count(distinct h.group) from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + } + + public void testReplaceWithSelectId() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithSelectId(); + String res = transformer.getResult(); + assertEquals( + "select h.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + + transformer = new QueryTransformerRegex( + "select h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithSelectId(); + res = transformer.getResult(); + assertEquals( + "select h.group.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + + transformer = new QueryTransformerRegex( + "select distinct h.group from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceWithSelectId(); + res = transformer.getResult(); + assertEquals( + "select distinct h.group.id from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0", + res); + } + + public void testOrderBy() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by c.level"); + transformer.replaceOrderBy(false, "group"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group", + res); + transformer.replaceOrderBy(true, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group desc", + res); + } + + public void testOrderByAscDesc() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group asc"); + transformer.replaceOrderBy(true, "group"); + String res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group desc", + res); + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group desc"); + transformer.replaceOrderBy(false, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group", + res); + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group desc"); + transformer.replaceOrderBy(true, "group"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = ?1 " + + "group by c.level having c.level > 0 order by h.group desc", + res); + } + + public void testOrderByAssociatedProperty() { + // first level of association + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from ref$Car c where c.deleteTs is null"); + transformer.replaceOrderBy(false, "model.numberOfSeats"); + String res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats", + res); + transformer.replaceOrderBy(true, "model.numberOfSeats"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats desc", + res); + + // second level of association + transformer = new QueryTransformerRegex( + "select c from ref$Car c where c.deleteTs is null"); + transformer.replaceOrderBy(false, "model.manufacturer.name"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model.manufacturer c_model_manufacturer where c.deleteTs is null order by c_model_manufacturer.name", + res); + transformer.replaceOrderBy(true, "model.manufacturer.name"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model.manufacturer c_model_manufacturer where c.deleteTs is null order by c_model_manufacturer.name desc", + res); + } + + public void testOrderBySeveralProperties() throws Exception { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select c from ref$Car c where c.deleteTs is null"); + + + transformer.replaceOrderBy(false, "createTs", "vin"); + String res = transformer.getResult(); + assertEquals( + "select c from ref$Car c where c.deleteTs is null order by c.createTs, c.vin", + res); + + transformer.replaceOrderBy(false, "vin", "model.numberOfSeats"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c.vin, c_model.numberOfSeats", + res); + + transformer.replaceOrderBy(true, "vin", "model.numberOfSeats"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c.vin desc, c_model.numberOfSeats desc", + res); + + transformer.replaceOrderBy(false, "model.numberOfSeats", "vin"); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c left join c.model c_model where c.deleteTs is null order by c_model.numberOfSeats, c.vin", + res); + } + + public void testRemoveDistinct() { + QueryTransformerRegex transformer; + String res; + + transformer = new QueryTransformerRegex( + "select c from ref$Car c where c.deleteTs is null"); + transformer.removeDistinct(); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c where c.deleteTs is null", + res); + + transformer = new QueryTransformerRegex( + "select distinct c from ref$Car c where c.deleteTs is null"); + transformer.removeDistinct(); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c where c.deleteTs is null", + res); + + transformer = new QueryTransformerRegex( + "select distinct c from ref$Car c where c.deleteTs is null"); + transformer.removeDistinct(); + res = transformer.getResult(); + assertEquals( + "select c from ref$Car c where c.deleteTs is null", + res); + } + + public void testReplaceEntityName() { + QueryTransformerRegex transformer; + String res; + + transformer = new QueryTransformerRegex( + "select c from ref$Car c where c.deleteTs is null"); + transformer.replaceEntityName("ref$ExtCar"); + res = transformer.getResult(); + assertEquals( + "select c from ref$ExtCar c where c.deleteTs is null", + res); + } + + public void testSubQueriesAddWhere() { + QueryTransformerRegex transformer; + String res; + + transformer = new QueryTransformerRegex( + "select h from sec$GroupHierarchy h where h.group = :par"); + + transformer.addWhere("{E}.createdBy = :par1 and {E}.updatedBy = (select u.login from sec$User u where u.login = :par2) and {E}.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h where h.group = :par and (h.createdBy = :par1" + + " and h.updatedBy = (select u.login from sec$User u where u.login = :par2) and h.createTs = :par3)", + res); + } + + public void testSubQueriesAddJoinAndWhere() { + QueryTransformerRegex transformer; + String res; + + transformer = new QueryTransformerRegex( + "select c from sec$GroupHierarchy h where h.group = :par"); + + transformer.addJoinAndWhere("join {E}.parent.constraints c", "{E}.createdBy = :par1 and {E}.updatedBy = " + + "(select u.login from sec$User u where u.login = {E}.param) and c.createTs = :par3"); + res = transformer.getResult(); + assertEquals( + "select c from sec$GroupHierarchy h join h.parent.constraints c where h.group = :par and (h.createdBy = :par1" + + " and h.updatedBy = (select u.login from sec$User u where u.login = h.param) and c.createTs = :par3)", + res); + } + + public void testHandleCaseInsensitiveParam() throws Exception { + QueryTransformerRegex transformer; + String res; + + transformer = new QueryTransformerRegex("select u from sec$User u where u.name like :name"); + + transformer.handleCaseInsensitiveParam("name"); + res = transformer.getResult(); + assertEquals( + "select u from sec$User u where lower(u.name) like :name", + res); + + transformer = new QueryTransformerRegex("select u from sec$User u where u.name=:name"); + + transformer.handleCaseInsensitiveParam("name"); + res = transformer.getResult(); + assertEquals( + "select u from sec$User u where lower(u.name)=:name", + res); + } + + public void testJoinAsIs() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select h from sec$GroupHierarchy h, sec$Constraint u where h.userGroup = :par"); + + transformer.addJoinAsIs("join h.parent.constraints c"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$GroupHierarchy h join h.parent.constraints c, sec$Constraint u where h.userGroup = :par", + res); + } + + public void testJoinAsIs2() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select h from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); + + transformer.addJoinAsIs("join h.parent.constraints c"); + String res = transformer.getResult(); + assertEquals( + "select h from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", + res); + } + + public void testJoinAsIs3() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select h.level from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); + + transformer.addJoinAsIs("join h.parent.constraints c"); + String res = transformer.getResult(); + assertEquals( + "select h.level from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", + res); + } + + public void testJoinAsIs4() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "SELECT distinct h.level from sec$Constraint u, sec$GroupHierarchy h where h.userGroup = :par"); + + transformer.addJoinAsIs("join h.parent.constraints c"); + String res = transformer.getResult(); + assertEquals( + "SELECT distinct h.level from sec$Constraint u, sec$GroupHierarchy h join h.parent.constraints c where h.userGroup = :par", + res); + } + + public void testNpeInReplaceOrderBy() { + QueryTransformerRegex transformer = new QueryTransformerRegex( + "select drB from taxi$DriverBan drB where drB.driver.id = :ds_driverDs order by drB.from"); + String[] properties = new String[]{"driver.name", "driver.callsignName"}; + + transformer.replaceOrderBy(true, properties); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/global/ViewRepositoryTest.java b/modules/core/test/com/haulmont/cuba/core/global/ViewRepositoryTest.java index 95960f296d..ddb732292e 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/ViewRepositoryTest.java +++ b/modules/core/test/com/haulmont/cuba/core/global/ViewRepositoryTest.java @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.AbstractViewRepository; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.io.InputStream; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -public class ViewRepositoryTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private ViewRepository repository; - - @Before - public void setUp() throws Exception { - repository = cont.metadata().getViewRepository(); - - InputStream stream = ViewRepositoryTest.class.getResourceAsStream("test.view.xml"); - ((AbstractViewRepository) repository).deployViews(stream); - } - - @Test - public void testGetView() { - View view = repository.getView(User.class, "test"); - assertNotNull(view); - assertNotNull(view.getProperty("name")); - assertNotNull(view.getProperty("login")); - assertNotNull(view.getProperty("userRoles")); - - View userRolesView = view.getProperty("userRoles").getView(); - assertNotNull(userRolesView); - assertNotNull(userRolesView.getProperty("role")); - - View roleView = userRolesView.getProperty("role").getView(); - assertNotNull(roleView); - assertNotNull(roleView.getProperty("name")); - } - - @Test - public void testDefaultViews() { - View localView = repository.getView(User.class, View.LOCAL); - assertNotNull(localView); - assertNotNull(localView.getProperty("name")); - assertNotNull(localView.getProperty("login")); - assertNotNull(localView.getProperty("email")); - assertNull(localView.getProperty("userRoles")); - - View minView = repository.getView(User.class, View.MINIMAL); - assertNotNull(minView); - assertNotNull(minView.getProperty("name")); - assertNotNull(minView.getProperty("login")); - assertNull(minView.getProperty("email")); - assertNull(minView.getProperty("userRoles")); - } - - @Test - public void testInheritance() { - View view = repository.getView(User.class, "testInheritance"); - assertNotNull(view); - assertNotNull(view.getProperty("name")); - assertNotNull(view.getProperty("login")); - assertNotNull(view.getProperty("userRoles")); - assertNull(view.getProperty("substitutions")); - } - - @Test - public void testAnonymous() { - View view = repository.getView(User.class, "anonymousTest"); - assertNotNull(view); - assertNotNull(view.getProperty("group")); - assertNotNull(view.getProperty("group").getView()); - assertNull(view.getProperty("name")); - - View groupView = view.getProperty("group").getView(); - assertNotNull(groupView.getProperty("constraints")); - assertNotNull(groupView.getProperty("name")); - assertNull(groupView.getProperty("hierarchyList")); - - assertNotNull(groupView.getProperty("constraints").getView()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.AbstractViewRepository; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.InputStream; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +public class ViewRepositoryTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private ViewRepository repository; + + @Before + public void setUp() throws Exception { + repository = cont.metadata().getViewRepository(); + + InputStream stream = ViewRepositoryTest.class.getResourceAsStream("test.view.xml"); + ((AbstractViewRepository) repository).deployViews(stream); + } + + @Test + public void testGetView() { + View view = repository.getView(User.class, "test"); + assertNotNull(view); + assertNotNull(view.getProperty("name")); + assertNotNull(view.getProperty("login")); + assertNotNull(view.getProperty("userRoles")); + + View userRolesView = view.getProperty("userRoles").getView(); + assertNotNull(userRolesView); + assertNotNull(userRolesView.getProperty("role")); + + View roleView = userRolesView.getProperty("role").getView(); + assertNotNull(roleView); + assertNotNull(roleView.getProperty("name")); + } + + @Test + public void testDefaultViews() { + View localView = repository.getView(User.class, View.LOCAL); + assertNotNull(localView); + assertNotNull(localView.getProperty("name")); + assertNotNull(localView.getProperty("login")); + assertNotNull(localView.getProperty("email")); + assertNull(localView.getProperty("userRoles")); + + View minView = repository.getView(User.class, View.MINIMAL); + assertNotNull(minView); + assertNotNull(minView.getProperty("name")); + assertNotNull(minView.getProperty("login")); + assertNull(minView.getProperty("email")); + assertNull(minView.getProperty("userRoles")); + } + + @Test + public void testInheritance() { + View view = repository.getView(User.class, "testInheritance"); + assertNotNull(view); + assertNotNull(view.getProperty("name")); + assertNotNull(view.getProperty("login")); + assertNotNull(view.getProperty("userRoles")); + assertNull(view.getProperty("substitutions")); + } + + @Test + public void testAnonymous() { + View view = repository.getView(User.class, "anonymousTest"); + assertNotNull(view); + assertNotNull(view.getProperty("group")); + assertNotNull(view.getProperty("group").getView()); + assertNull(view.getProperty("name")); + + View groupView = view.getProperty("group").getView(); + assertNotNull(groupView.getProperty("constraints")); + assertNotNull(groupView.getProperty("name")); + assertNull(groupView.getProperty("hierarchyList")); + + assertNotNull(groupView.getProperty("constraints").getView()); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilter2Test.java b/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilter2Test.java index 2208392cdd..4fc8b093f7 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilter2Test.java +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilter2Test.java @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.cuba.testsupport.TestContainer; -import org.dom4j.Element; -import org.junit.ClassRule; -import org.junit.Test; - -public class QueryFilter2Test { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - String xml = "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " NULL\n" + - " \n" + - " \n" + - " \n" + - " NULL\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " GROUP\n" + - " \n" + - " \n" + - " \n" + - " 2015-11-02 00:00:00.000\n" + - " \n" + - " \n" + - ""; - - @Test - public void testParse() throws Exception { - Element element = Dom4j.readDocument(xml).getRootElement(); - QueryFilter queryFilter = new QueryFilter(element); - - Condition root = queryFilter.getRoot(); - System.out.println(new GroovyGenerator().generateGroovy(root)); - System.out.println(new SecurityJpqlGenerator().generateJpql(root)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.cuba.testsupport.TestContainer; +import org.dom4j.Element; +import org.junit.ClassRule; +import org.junit.Test; + +public class QueryFilter2Test { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + String xml = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " NULL\n" + + " \n" + + " \n" + + " \n" + + " NULL\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " GROUP\n" + + " \n" + + " \n" + + " \n" + + " 2015-11-02 00:00:00.000\n" + + " \n" + + " \n" + + ""; + + @Test + public void testParse() throws Exception { + Element element = Dom4j.readDocument(xml).getRootElement(); + QueryFilter queryFilter = new QueryFilter(element); + + Condition root = queryFilter.getRoot(); + System.out.println(new GroovyGenerator().generateGroovy(root)); + System.out.println(new SecurityJpqlGenerator().generateJpql(root)); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilterTest.java b/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilterTest.java index 2718474189..8ba62f9982 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilterTest.java +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/QueryFilterTest.java @@ -1,169 +1,169 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.testsupport.TestContainer; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; -import mockit.NonStrictExpectations; -import org.dom4j.Document; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -public class QueryFilterTest { - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Before - public void setUp() { - new MockUp(){ - // Redefine the method here - // But With No static modifier - @Mock - public QueryTransformer createTransformer(String query) { - return new QueryTransformerRegex(query); - } - }; - } - - private QueryFilter createFilter(String name) { - InputStream stream = QueryFilterTest.class.getResourceAsStream("/com/haulmont/cuba/core/global/filter/" + name); - Document doc = Dom4j.readDocument(stream); - return new QueryFilter(doc.getRootElement()); - } - - @Test - public void test1() { - QueryFilter filter = createFilter("filter1.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (d.processState <> 'Version')", s); - } - - @Test - public void test2() { - QueryFilter filter = createFilter("filter2.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d", s); - - params.put("custom$filter_state", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); - } - - @Test - public void test3() { - QueryFilter filter = createFilter("filter3.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d", s); - - params.put("custom$filter_state", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); - - params.put("custom$filter_barCode", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); - } - - @Test - public void test4() { - QueryFilter filter = createFilter("filter4.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d", s); - - params.put("custom$filter_state", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); - - params.put("custom$filter_barCode", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); - - params.put("custom$filter_notSigned", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); - } - - @Test - public void test5() { - QueryFilter filter = createFilter("filter5.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d", s); - - params.put("custom$filter_state", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); - - params.put("custom$filter_barCode", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); - - params.put("custom$filter_notSigned", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d where 1=1", params); - assertEquals("select distinct d from saneco$GenDoc d where 1=1 and (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); - } - - @Test - public void test6() { - QueryFilter filter = createFilter("filter6.xml"); - - Map params = new HashMap(); - params.put("p1", "v1"); - String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d", s); - - params.put("custom$filter_state", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where (d.processState = :custom$filter_state)", s); - - params.put("custom$filter_barCode", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d", params); - assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); - - params.put("custom$filter_notSigned", "v1"); - s = filter.processQuery("select distinct d from saneco$GenDoc d where 1=1", params); - assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where 1=1 and (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); - } - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.testsupport.TestContainer; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; +import mockit.NonStrictExpectations; +import org.dom4j.Document; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class QueryFilterTest { + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Before + public void setUp() { + new MockUp(){ + // Redefine the method here + // But With No static modifier + @Mock + public QueryTransformer createTransformer(String query) { + return new QueryTransformerRegex(query); + } + }; + } + + private QueryFilter createFilter(String name) { + InputStream stream = QueryFilterTest.class.getResourceAsStream("/com/haulmont/cuba/core/global/filter/" + name); + Document doc = Dom4j.readDocument(stream); + return new QueryFilter(doc.getRootElement()); + } + + @Test + public void test1() { + QueryFilter filter = createFilter("filter1.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (d.processState <> 'Version')", s); + } + + @Test + public void test2() { + QueryFilter filter = createFilter("filter2.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d", s); + + params.put("custom$filter_state", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); + } + + @Test + public void test3() { + QueryFilter filter = createFilter("filter3.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d", s); + + params.put("custom$filter_state", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); + + params.put("custom$filter_barCode", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); + } + + @Test + public void test4() { + QueryFilter filter = createFilter("filter4.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d", s); + + params.put("custom$filter_state", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); + + params.put("custom$filter_barCode", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); + + params.put("custom$filter_notSigned", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); + } + + @Test + public void test5() { + QueryFilter filter = createFilter("filter5.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d", s); + + params.put("custom$filter_state", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where (d.processState = :custom$filter_state)", s); + + params.put("custom$filter_barCode", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); + + params.put("custom$filter_notSigned", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d where 1=1", params); + assertEquals("select distinct d from saneco$GenDoc d where 1=1 and (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); + } + + @Test + public void test6() { + QueryFilter filter = createFilter("filter6.xml"); + + Map params = new HashMap(); + params.put("p1", "v1"); + String s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d", s); + + params.put("custom$filter_state", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where (d.processState = :custom$filter_state)", s); + + params.put("custom$filter_barCode", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d", params); + assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where ((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode))", s); + + params.put("custom$filter_notSigned", "v1"); + s = filter.processQuery("select distinct d from saneco$GenDoc d where 1=1", params); + assertEquals("select distinct d from saneco$GenDoc d , docflow$DocumentRole dr where 1=1 and (((d.processState = :custom$filter_state and d.barCode like :custom$filter_barCode) or d.processState <> :custom$filter_notSigned))", s); + } + +} diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter1.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter1.xml index 55d83b0b3b..b34e2962b0 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter1.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter1.xml @@ -1,19 +1,19 @@ - - - 'Version']]> + + + 'Version']]> \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter2.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter2.xml index 780a7f39a0..a3e49e03fe 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter2.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter2.xml @@ -1,19 +1,19 @@ - - - d.processState = :custom$filter_state + + + d.processState = :custom$filter_state \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter3.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter3.xml index 4951e006e6..035fc88c56 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter3.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter3.xml @@ -1,22 +1,22 @@ - - - - d.processState = :custom$filter_state - d.barCode like :custom$filter_barCode - + + + + d.processState = :custom$filter_state + d.barCode like :custom$filter_barCode + \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter4.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter4.xml index 02ea90acf7..cb911cb3eb 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter4.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter4.xml @@ -1,25 +1,25 @@ - - - - - d.processState = :custom$filter_state - d.barCode like :custom$filter_barCode - - :custom$filter_notSigned]]> - + + + + + d.processState = :custom$filter_state + d.barCode like :custom$filter_barCode + + :custom$filter_notSigned]]> + \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter5.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter5.xml index 02ea90acf7..cb911cb3eb 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter5.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter5.xml @@ -1,25 +1,25 @@ - - - - - d.processState = :custom$filter_state - d.barCode like :custom$filter_barCode - - :custom$filter_notSigned]]> - + + + + + d.processState = :custom$filter_state + d.barCode like :custom$filter_barCode + + :custom$filter_notSigned]]> + \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/filter/filter6.xml b/modules/core/test/com/haulmont/cuba/core/global/filter/filter6.xml index 662a7b7916..f35fde23dc 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/filter/filter6.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/filter/filter6.xml @@ -1,25 +1,25 @@ - - - - - d.processState = :custom$filter_state - d.barCode like :custom$filter_barCode - - :custom$filter_notSigned]]> - + + + + + d.processState = :custom$filter_state + d.barCode like :custom$filter_barCode + + :custom$filter_notSigned]]> + \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/global/test.view.xml b/modules/core/test/com/haulmont/cuba/core/global/test.view.xml index bd7613191c..21a5dcda52 100644 --- a/modules/core/test/com/haulmont/cuba/core/global/test.view.xml +++ b/modules/core/test/com/haulmont/cuba/core/global/test.view.xml @@ -1,45 +1,45 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/MpTestObj.java b/modules/core/test/com/haulmont/cuba/core/mp_test/MpTestObj.java index 418e66f0ea..eea7ac943b 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/MpTestObj.java +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/MpTestObj.java @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.mp_test; - -public class MpTestObj -{ -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.mp_test; + +public class MpTestObj +{ +} diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages.properties index 2c705df9bd..0d828d467d 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages.properties @@ -1,20 +1,20 @@ - -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -includedMsg=Included Message + +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +includedMsg=Included Message includedMsgToOverride=Included Msg To Override \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages_fr.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages_fr.properties index 9a6cbed6fd..684b6d6260 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages_fr.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/inc/messages_fr.properties @@ -1,19 +1,19 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -includedMsgToOverride = Message inclus à remplacer -includedMsg = Message inclus +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +includedMsgToOverride = Message inclus à remplacer +includedMsg = Message inclus diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/messages.properties index 97097974e5..4629ad8e2e 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/messages.properties @@ -1,18 +1,18 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + @include=com.haulmont.cuba.core.mp_test.includes.one, com.haulmont.cuba.core.mp_test.includes.two \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/one/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/one/messages.properties index d1e7d58798..6fbb8de537 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/one/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/one/messages.properties @@ -1,19 +1,19 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -oneKey = OK +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +oneKey = OK threeKey = initial \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/two/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/two/messages.properties index 8ff7ede6a3..018f09a829 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/includes/two/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/includes/two/messages.properties @@ -1,19 +1,19 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -twoKey = OK -threeKey = overridden +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +twoKey = OK +threeKey = overridden diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/messages.properties index a51ec31397..b7fe454b5f 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/messages.properties @@ -1,29 +1,29 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -@include=com.haulmont.cuba.core.mp_test.inc - -key1=Message1 -key2=Message2 -MpTestNestedEnum.ONE=One -MpTestNestedObj$InternalEnum.FIRST=First - -includedMsgToOverride=Overridden Included Message - -commonMsg=Common Message -languageMsg=Language Message +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +@include=com.haulmont.cuba.core.mp_test.inc + +key1=Message1 +key2=Message2 +MpTestNestedEnum.ONE=One +MpTestNestedObj$InternalEnum.FIRST=First + +includedMsgToOverride=Overridden Included Message + +commonMsg=Common Message +languageMsg=Language Message countryMsg=Country Message \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/messages_fr.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/messages_fr.properties index 71845b1a97..6e3df353dd 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/messages_fr.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/messages_fr.properties @@ -1,26 +1,26 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -MpTestNestedObj$InternalEnum.FIRST = Premier -includedMsgToOverride = Message inclus remplacé -key2 = Message2 -key1 = Message1 -@include = com.haulmont.cuba.core.mp_test.inc -MpTestNestedEnum.ONE = Un - -languageMsg=Language Message fr +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +MpTestNestedObj$InternalEnum.FIRST = Premier +includedMsgToOverride = Message inclus remplacé +key2 = Message2 +key1 = Message1 +@include = com.haulmont.cuba.core.mp_test.inc +MpTestNestedEnum.ONE = Un + +languageMsg=Language Message fr countryMsg=Country Message fr \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedEnum.java b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedEnum.java index 3338409f82..3fa40ce10d 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedEnum.java +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedEnum.java @@ -1,22 +1,22 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.mp_test.nested; - -public enum MpTestNestedEnum -{ - ONE, TWO -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.mp_test.nested; + +public enum MpTestNestedEnum +{ + ONE, TWO +} diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedObj.java b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedObj.java index 9f5029c0e2..0fa16fa9bd 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedObj.java +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/MpTestNestedObj.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.mp_test.nested; - -public class MpTestNestedObj -{ - public enum InternalEnum - { - FIRST, SECOND - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.mp_test.nested; + +public class MpTestNestedObj +{ + public enum InternalEnum + { + FIRST, SECOND + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages.properties index 72bb82edaa..a86185fa2a 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages.properties @@ -1,18 +1,18 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -key0=Message0 +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +key0=Message0 diff --git a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages_fr.properties b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages_fr.properties index 6aade39a4d..0781ca20cd 100644 --- a/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages_fr.properties +++ b/modules/core/test/com/haulmont/cuba/core/mp_test/nested/messages_fr.properties @@ -1,18 +1,18 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -key0 = Message0 in French +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +key0 = Message0 in French diff --git a/modules/core/test/com/haulmont/cuba/core/sys/EntityManagerContextTest.java b/modules/core/test/com/haulmont/cuba/core/sys/EntityManagerContextTest.java index 473ba777e1..a11b4e284a 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/EntityManagerContextTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/EntityManagerContextTest.java @@ -1,102 +1,102 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class EntityManagerContextTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - public static final String ATTR = "testAttr"; - private Object obj1 = new Object(); - private Object obj2 = new Object(); - - @Test - public void test() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager(); - EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); - ctx.setAttribute(ATTR, obj1); - - cont.persistence().getEntityManager(); - ctx = cont.persistence().getEntityManagerContext(); - assertTrue(ctx.getAttribute(ATTR) == obj1); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager(); - EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); - Object obj = ctx.getAttribute(ATTR); - assertNull(obj); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testCommitRetaining() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager(); - EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); - ctx.setAttribute(ATTR, obj1); - - ctx = cont.persistence().getEntityManagerContext(); - assertTrue(ctx.getAttribute(ATTR) == obj1); - - tx.commitRetaining(); - - cont.persistence().getEntityManager(); - ctx = cont.persistence().getEntityManagerContext(); - assertNull(ctx.getAttribute(ATTR)); - ctx.setAttribute(ATTR, obj2); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager(); - EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); - Object obj = ctx.getAttribute(ATTR); - assertNull(obj); - - tx.commit(); - } finally { - tx.end(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class EntityManagerContextTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + public static final String ATTR = "testAttr"; + private Object obj1 = new Object(); + private Object obj2 = new Object(); + + @Test + public void test() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager(); + EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); + ctx.setAttribute(ATTR, obj1); + + cont.persistence().getEntityManager(); + ctx = cont.persistence().getEntityManagerContext(); + assertTrue(ctx.getAttribute(ATTR) == obj1); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager(); + EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); + Object obj = ctx.getAttribute(ATTR); + assertNull(obj); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testCommitRetaining() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager(); + EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); + ctx.setAttribute(ATTR, obj1); + + ctx = cont.persistence().getEntityManagerContext(); + assertTrue(ctx.getAttribute(ATTR) == obj1); + + tx.commitRetaining(); + + cont.persistence().getEntityManager(); + ctx = cont.persistence().getEntityManagerContext(); + assertNull(ctx.getAttribute(ATTR)); + ctx.setAttribute(ATTR, obj2); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager(); + EntityManagerContext ctx = cont.persistence().getEntityManagerContext(); + Object obj = ctx.getAttribute(ATTR); + assertNull(obj); + + tx.commit(); + } finally { + tx.end(); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/sys/SecurityTokenManagerTest.java b/modules/core/test/com/haulmont/cuba/core/sys/SecurityTokenManagerTest.java index a136bb4f40..8a28005b80 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/SecurityTokenManagerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/SecurityTokenManagerTest.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.List; -import java.util.UUID; - -public class SecurityTokenManagerTest { - - @ClassRule - public static TestContainer testContainer = TestContainer.Common.INSTANCE; - - @Test - @Ignore - public void testSecurityToken() throws Exception { - SecurityTokenManager securityTokenManager = AppBeans.get(SecurityTokenManager.class); - User user = new User(); - UUID id1 = UUID.randomUUID(); - UUID id2 = UUID.randomUUID(); - UUID id3 = UUID.randomUUID(); - UUID id4 = UUID.randomUUID(); - securityTokenManager.addFiltered(user, "userRoles", id1); - securityTokenManager.addFiltered(user, "userRoles", id2); - securityTokenManager.addFiltered(user, "userRoles", id3); - securityTokenManager.addFiltered(user, "userRoles", id4); - - securityTokenManager.writeSecurityToken(user); - securityTokenManager.readSecurityToken(user); - - List userRoles = (List) BaseEntityInternalAccess.getFilteredData(user).get("userRoles"); - Assert.assertEquals(4, userRoles.size()); - Assert.assertEquals(id1, userRoles.get(0)); - Assert.assertEquals(id2, userRoles.get(1)); - Assert.assertEquals(id3, userRoles.get(2)); - Assert.assertEquals(id4, userRoles.get(3)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +public class SecurityTokenManagerTest { + + @ClassRule + public static TestContainer testContainer = TestContainer.Common.INSTANCE; + + @Test + @Ignore + public void testSecurityToken() throws Exception { + SecurityTokenManager securityTokenManager = AppBeans.get(SecurityTokenManager.class); + User user = new User(); + UUID id1 = UUID.randomUUID(); + UUID id2 = UUID.randomUUID(); + UUID id3 = UUID.randomUUID(); + UUID id4 = UUID.randomUUID(); + securityTokenManager.addFiltered(user, "userRoles", id1); + securityTokenManager.addFiltered(user, "userRoles", id2); + securityTokenManager.addFiltered(user, "userRoles", id3); + securityTokenManager.addFiltered(user, "userRoles", id4); + + securityTokenManager.writeSecurityToken(user); + securityTokenManager.readSecurityToken(user); + + List userRoles = (List) BaseEntityInternalAccess.getFilteredData(user).get("userRoles"); + Assert.assertEquals(4, userRoles.size()); + Assert.assertEquals(id1, userRoles.get(0)); + Assert.assertEquals(id2, userRoles.get(1)); + Assert.assertEquals(id3, userRoles.get(2)); + Assert.assertEquals(id4, userRoles.get(3)); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/sys/TrustedLoginHandlerTest.java b/modules/core/test/com/haulmont/cuba/core/sys/TrustedLoginHandlerTest.java index bfc6268111..c723ae099d 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/TrustedLoginHandlerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/TrustedLoginHandlerTest.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.security.sys.TrustedLoginHandler; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class TrustedLoginHandlerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private TrustedLoginHandler trustedLoginHandler; - - @Before - public void setUp() throws Exception { - trustedLoginHandler = AppBeans.get(TrustedLoginHandler.class); - } - - private boolean matches(String address) { - return trustedLoginHandler.checkAddress(address); - } - - @Test - public void testFullMatch() { - boolean isMatch = matches("127.0.0.1"); - assertTrue(isMatch); - } - - @Test - public void testPermittedIp() { - boolean isMatch = matches("10.17.8.3"); - assertTrue(isMatch); - } - - @Test - public void testNotPermittedIp() { - boolean isMatch = matches("127.10.0.1"); - assertFalse(isMatch); - } - - @Test - public void testNotANumber() { - boolean isMatch = matches("10.17.8.a"); - assertFalse(isMatch); - } - - @Test - public void testClippedIp() { - boolean isMatch = matches("10.17.8"); - assertFalse(isMatch); - } - - @Test - public void testOver255() { - boolean isMatch = matches("10.17.8.999"); - assertFalse(isMatch); - } - - @Test - public void testWrongSeparator() { - boolean isMatch = matches("10_17_8_3"); - assertFalse(isMatch); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.security.sys.TrustedLoginHandler; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TrustedLoginHandlerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private TrustedLoginHandler trustedLoginHandler; + + @Before + public void setUp() throws Exception { + trustedLoginHandler = AppBeans.get(TrustedLoginHandler.class); + } + + private boolean matches(String address) { + return trustedLoginHandler.checkAddress(address); + } + + @Test + public void testFullMatch() { + boolean isMatch = matches("127.0.0.1"); + assertTrue(isMatch); + } + + @Test + public void testPermittedIp() { + boolean isMatch = matches("10.17.8.3"); + assertTrue(isMatch); + } + + @Test + public void testNotPermittedIp() { + boolean isMatch = matches("127.10.0.1"); + assertFalse(isMatch); + } + + @Test + public void testNotANumber() { + boolean isMatch = matches("10.17.8.a"); + assertFalse(isMatch); + } + + @Test + public void testClippedIp() { + boolean isMatch = matches("10.17.8"); + assertFalse(isMatch); + } + + @Test + public void testOver255() { + boolean isMatch = matches("10.17.8.999"); + assertFalse(isMatch); + } + + @Test + public void testWrongSeparator() { + boolean isMatch = matches("10_17_8_3"); + assertFalse(isMatch); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterEngineTest.java b/modules/core/test/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterEngineTest.java index 73212ffef7..960c18930b 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterEngineTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/dbupdate/DbUpdaterEngineTest.java @@ -1,206 +1,206 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.dbupdate; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.testsupport.TestContainer; -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static org.junit.Assert.assertEquals; - -public class DbUpdaterEngineTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private File dbmsDir; - private File dbmsWebInfDir; - - private List mssqlInitFiles = new ArrayList<>(); - private List mssql2012InitFiles = new ArrayList<>(); - private List mssqlUpdateFiles = new ArrayList<>(); - private List mssql2012UpdateFiles = new ArrayList<>(); - - @SuppressWarnings("ResultOfMethodCallIgnored") - @Before - public void setUp() throws Exception { - GlobalConfig config = AppBeans.get(Configuration.class).getConfig(GlobalConfig.class); - dbmsDir = new File(config.getTempDir(), "db. dir"); - if (dbmsDir.exists()) { - FileUtils.deleteDirectory(dbmsDir); - } - dbmsDir.mkdirs(); - - dbmsWebInfDir = new File(config.getTempDir(), "WEB-INF/db"); - if (dbmsWebInfDir.exists()) { - FileUtils.deleteDirectory(dbmsWebInfDir); - } - dbmsWebInfDir.mkdirs(); - - File dir; - File file; - - // Init scripts - dir = new File(dbmsWebInfDir, "10-cuba/init/postgres"); - dir.mkdirs(); - file = new File(dir, "create-db.sql"); - file.createNewFile(); - - - dir = new File(dbmsDir, "10-cuba/init/mssql"); - dir.mkdirs(); - file = new File(dir, "create-db.sql"); - file.createNewFile(); - mssqlInitFiles.add(file); - - dir = new File(dbmsDir, "10-cuba/init/mssql-2012"); - dir.mkdirs(); - file = new File(dir, "create-db.sql"); - file.createNewFile(); - mssql2012InitFiles.add(file); - - dir = new File(dbmsDir, "50-app/init/mssql"); - dir.mkdirs(); - file = new File(dir, "10.create-db.sql"); - file.createNewFile(); - mssqlInitFiles.add(file); - mssql2012InitFiles.add(file); - file = new File(dir, "20.create-db.sql"); - file.createNewFile(); - mssqlInitFiles.add(file); - mssql2012InitFiles.add(file); - file = new File(dir, "30.create-db.sql"); - file.createNewFile(); - mssqlInitFiles.add(file); - - dir = new File(dbmsDir, "50-app/init/mssql-2012"); - dir.mkdirs(); - file = new File(dir, "30.create-db.sql"); - file.createNewFile(); - mssql2012InitFiles.add(file); - - file = new File(dir, "40.create-db.sql"); - file.createNewFile(); - mssql2012InitFiles.add(file); - - // Update scripts - - dir = new File(dbmsDir, "10-cuba/update/mssql/13"); - dir.mkdirs(); - file = new File(dir, "cuba-update-1.sql"); - file.createNewFile(); - mssqlUpdateFiles.add(file); - mssql2012UpdateFiles.add(file); - - dir = new File(dbmsDir, "10-cuba/update/mssql/14"); - dir.mkdirs(); - file = new File(dir, "cuba-update-2.sql"); - file.createNewFile(); - mssqlUpdateFiles.add(file); - mssql2012UpdateFiles.add(file); - - dir = new File(dbmsDir, "50-app/update/mssql/14"); - dir.mkdirs(); - file = new File(dir, "app-update-0.sql"); - file.createNewFile(); - mssqlUpdateFiles.add(file); - mssql2012UpdateFiles.add(file); - file = new File(dir, "app-update-1.sql"); - file.createNewFile(); - mssqlUpdateFiles.add(file); - - dir = new File(dbmsDir, "50-app/update/mssql-2012/14"); - dir.mkdirs(); - file = new File(dir, "app-update-1.sql"); - file.createNewFile(); - mssql2012UpdateFiles.add(file); - file = new File(dir, "app-update-2.sql"); - file.createNewFile(); - mssql2012UpdateFiles.add(file); - } - - @Test - public void testGetInitScripts() throws Exception { - DbUpdaterEngine engine = new DbUpdaterEngine(); - engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); - engine.dbmsType = "mssql"; - - List scripts = engine.getInitScripts(); - List files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); - assertEquals(mssqlInitFiles, files); - - engine.dbmsVersion = "2012"; - - scripts = engine.getInitScripts(); - files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); - assertEquals(mssql2012InitFiles, files); - } - - @Test - public void testGetUpdateScripts() throws Exception { - DbUpdaterEngine engine = new DbUpdaterEngine(); - engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); - engine.dbmsType = "mssql"; - - List scripts = engine.getUpdateScripts(); - List files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); - - assertEquals(mssqlUpdateFiles, files); - - engine.dbmsVersion = "2012"; - - scripts = engine.getUpdateScripts(); - files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); - assertEquals(mssql2012UpdateFiles, files); - } - - @Test - public void testGetModules() throws Exception { - DbUpdaterEngine engine = new DbUpdaterEngine(); - engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); - engine.dbmsType = "mssql"; - List moduleDirs = engine.getModuleDirs(); - assertEquals("10-cuba",moduleDirs.get(0)); - assertEquals("50-app",moduleDirs.get(1)); - } - - @Test - public void testGetScriptName() throws Exception { - File script = new File(dbmsDir, "50-app/update/mssql-2012/14/app-update-0.sql"); - DbUpdaterEngine engine = new DbUpdaterEngine(); - engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); - String scriptName = engine.getScriptName(script.getAbsolutePath()); - assertEquals("50-app/update/mssql-2012/14/app-update-0.sql", scriptName); - - script = new File(dbmsWebInfDir, "10-cuba/init/postgres/create-db.sql"); - engine = new DbUpdaterEngine(); - engine.dbScriptsDirectory = "web-inf:db"; - scriptName = engine.getScriptName(script.getAbsolutePath()); - assertEquals("10-cuba/init/postgres/create-db.sql", scriptName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.dbupdate; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.testsupport.TestContainer; +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +public class DbUpdaterEngineTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private File dbmsDir; + private File dbmsWebInfDir; + + private List mssqlInitFiles = new ArrayList<>(); + private List mssql2012InitFiles = new ArrayList<>(); + private List mssqlUpdateFiles = new ArrayList<>(); + private List mssql2012UpdateFiles = new ArrayList<>(); + + @SuppressWarnings("ResultOfMethodCallIgnored") + @Before + public void setUp() throws Exception { + GlobalConfig config = AppBeans.get(Configuration.class).getConfig(GlobalConfig.class); + dbmsDir = new File(config.getTempDir(), "db. dir"); + if (dbmsDir.exists()) { + FileUtils.deleteDirectory(dbmsDir); + } + dbmsDir.mkdirs(); + + dbmsWebInfDir = new File(config.getTempDir(), "WEB-INF/db"); + if (dbmsWebInfDir.exists()) { + FileUtils.deleteDirectory(dbmsWebInfDir); + } + dbmsWebInfDir.mkdirs(); + + File dir; + File file; + + // Init scripts + dir = new File(dbmsWebInfDir, "10-cuba/init/postgres"); + dir.mkdirs(); + file = new File(dir, "create-db.sql"); + file.createNewFile(); + + + dir = new File(dbmsDir, "10-cuba/init/mssql"); + dir.mkdirs(); + file = new File(dir, "create-db.sql"); + file.createNewFile(); + mssqlInitFiles.add(file); + + dir = new File(dbmsDir, "10-cuba/init/mssql-2012"); + dir.mkdirs(); + file = new File(dir, "create-db.sql"); + file.createNewFile(); + mssql2012InitFiles.add(file); + + dir = new File(dbmsDir, "50-app/init/mssql"); + dir.mkdirs(); + file = new File(dir, "10.create-db.sql"); + file.createNewFile(); + mssqlInitFiles.add(file); + mssql2012InitFiles.add(file); + file = new File(dir, "20.create-db.sql"); + file.createNewFile(); + mssqlInitFiles.add(file); + mssql2012InitFiles.add(file); + file = new File(dir, "30.create-db.sql"); + file.createNewFile(); + mssqlInitFiles.add(file); + + dir = new File(dbmsDir, "50-app/init/mssql-2012"); + dir.mkdirs(); + file = new File(dir, "30.create-db.sql"); + file.createNewFile(); + mssql2012InitFiles.add(file); + + file = new File(dir, "40.create-db.sql"); + file.createNewFile(); + mssql2012InitFiles.add(file); + + // Update scripts + + dir = new File(dbmsDir, "10-cuba/update/mssql/13"); + dir.mkdirs(); + file = new File(dir, "cuba-update-1.sql"); + file.createNewFile(); + mssqlUpdateFiles.add(file); + mssql2012UpdateFiles.add(file); + + dir = new File(dbmsDir, "10-cuba/update/mssql/14"); + dir.mkdirs(); + file = new File(dir, "cuba-update-2.sql"); + file.createNewFile(); + mssqlUpdateFiles.add(file); + mssql2012UpdateFiles.add(file); + + dir = new File(dbmsDir, "50-app/update/mssql/14"); + dir.mkdirs(); + file = new File(dir, "app-update-0.sql"); + file.createNewFile(); + mssqlUpdateFiles.add(file); + mssql2012UpdateFiles.add(file); + file = new File(dir, "app-update-1.sql"); + file.createNewFile(); + mssqlUpdateFiles.add(file); + + dir = new File(dbmsDir, "50-app/update/mssql-2012/14"); + dir.mkdirs(); + file = new File(dir, "app-update-1.sql"); + file.createNewFile(); + mssql2012UpdateFiles.add(file); + file = new File(dir, "app-update-2.sql"); + file.createNewFile(); + mssql2012UpdateFiles.add(file); + } + + @Test + public void testGetInitScripts() throws Exception { + DbUpdaterEngine engine = new DbUpdaterEngine(); + engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); + engine.dbmsType = "mssql"; + + List scripts = engine.getInitScripts(); + List files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); + assertEquals(mssqlInitFiles, files); + + engine.dbmsVersion = "2012"; + + scripts = engine.getInitScripts(); + files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); + assertEquals(mssql2012InitFiles, files); + } + + @Test + public void testGetUpdateScripts() throws Exception { + DbUpdaterEngine engine = new DbUpdaterEngine(); + engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); + engine.dbmsType = "mssql"; + + List scripts = engine.getUpdateScripts(); + List files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); + + assertEquals(mssqlUpdateFiles, files); + + engine.dbmsVersion = "2012"; + + scripts = engine.getUpdateScripts(); + files = scripts.stream().map(sr -> new File(sr.getPath())).collect(Collectors.toList()); + assertEquals(mssql2012UpdateFiles, files); + } + + @Test + public void testGetModules() throws Exception { + DbUpdaterEngine engine = new DbUpdaterEngine(); + engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); + engine.dbmsType = "mssql"; + List moduleDirs = engine.getModuleDirs(); + assertEquals("10-cuba",moduleDirs.get(0)); + assertEquals("50-app",moduleDirs.get(1)); + } + + @Test + public void testGetScriptName() throws Exception { + File script = new File(dbmsDir, "50-app/update/mssql-2012/14/app-update-0.sql"); + DbUpdaterEngine engine = new DbUpdaterEngine(); + engine.dbScriptsDirectory = dbmsDir.getAbsolutePath(); + String scriptName = engine.getScriptName(script.getAbsolutePath()); + assertEquals("50-app/update/mssql-2012/14/app-update-0.sql", scriptName); + + script = new File(dbmsWebInfDir, "10-cuba/init/postgres/create-db.sql"); + engine = new DbUpdaterEngine(); + engine.dbScriptsDirectory = "web-inf:db"; + scriptName = engine.getScriptName(script.getAbsolutePath()); + assertEquals("10-cuba/init/postgres/create-db.sql", scriptName); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandlerTest.java b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandlerTest.java index 67930ad9b0..e09a755bff 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandlerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/DateEqualsMacroHandlerTest.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import junit.framework.TestCase; -import org.apache.commons.lang.time.DateUtils; - -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.Map; - -public class DateEqualsMacroHandlerTest extends TestCase { - - public void testExpandMacro() throws Exception { - Date date = new Date(); - DateEqualsMacroHandler handler = new DateEqualsMacroHandler(); - String res = handler.expandMacro("select distinct t from tm$Task t where t.id <> :param_exclItem " + - "and @dateEquals(t.createTs, :component_genericFilter_nLxPpRlkOq29857) order by t.num desc"); - handler.setQueryParams(Collections.singletonMap("component_genericFilter_nLxPpRlkOq29857", date)); - Map params = handler.getParams(); - - System.out.println(res); - System.out.println(params); - - assertEquals("select distinct t from tm$Task t where t.id <> :param_exclItem and (t.createTs >= :component_genericFilter_nLxPpRlkOq29857 and t.createTs < :t_createTs_1) order by t.num desc", res); - assertEquals(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), params.get("component_genericFilter_nLxPpRlkOq29857")); - assertEquals(DateUtils.addDays(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), 1), params.get("t_createTs_1")); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import junit.framework.TestCase; +import org.apache.commons.lang.time.DateUtils; + +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.Map; + +public class DateEqualsMacroHandlerTest extends TestCase { + + public void testExpandMacro() throws Exception { + Date date = new Date(); + DateEqualsMacroHandler handler = new DateEqualsMacroHandler(); + String res = handler.expandMacro("select distinct t from tm$Task t where t.id <> :param_exclItem " + + "and @dateEquals(t.createTs, :component_genericFilter_nLxPpRlkOq29857) order by t.num desc"); + handler.setQueryParams(Collections.singletonMap("component_genericFilter_nLxPpRlkOq29857", date)); + Map params = handler.getParams(); + + System.out.println(res); + System.out.println(params); + + assertEquals("select distinct t from tm$Task t where t.id <> :param_exclItem and (t.createTs >= :component_genericFilter_nLxPpRlkOq29857 and t.createTs < :t_createTs_1) order by t.num desc", res); + assertEquals(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), params.get("component_genericFilter_nLxPpRlkOq29857")); + assertEquals(DateUtils.addDays(DateUtils.truncate(date, Calendar.DAY_OF_MONTH), 1), params.get("t_createTs_1")); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandlerTest.java b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandlerTest.java index 437915245d..5584aa5867 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandlerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeBetweenQueryMacroHandlerTest.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class TimeBetweenQueryMacroHandlerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void testExpandMacro() throws Exception { - TimeBetweenQueryMacroHandler handler = new TimeBetweenQueryMacroHandler(); - String res = handler.expandMacro("select u from sec$User where @between(u.createTs, now, now+1, day) and u.deleteTs is null"); - System.out.println(res); - System.out.println(handler.getParams()); - - handler = new TimeBetweenQueryMacroHandler(); - res = handler.expandMacro("select u from sec$User " + - "where @between(u.createTs, now-10, now+1, minute) or @between(u.createTs, now-20, now-10, minute)" + - " and u.deleteTs is null"); - System.out.println(res); - System.out.println(handler.getParams()); - - handler = new TimeBetweenQueryMacroHandler(); - res = handler.expandMacro("select u from sec$User where @between(u.createTs, now-5+2, now, day) and u.deleteTs is null"); - System.out.println(res); - System.out.println(handler.getParams()); - } - - @Test - public void testReplaceQueryParams() { - Map params = new HashMap<>(); - params.put("param1", 5); - TimeBetweenQueryMacroHandler handler = new TimeBetweenQueryMacroHandler(); - String res = handler.replaceQueryParams("select u from sec$User where @between(u.createTs, now, now+:param1, day) and u.deleteTs is null", params); - System.out.println(res); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class TimeBetweenQueryMacroHandlerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void testExpandMacro() throws Exception { + TimeBetweenQueryMacroHandler handler = new TimeBetweenQueryMacroHandler(); + String res = handler.expandMacro("select u from sec$User where @between(u.createTs, now, now+1, day) and u.deleteTs is null"); + System.out.println(res); + System.out.println(handler.getParams()); + + handler = new TimeBetweenQueryMacroHandler(); + res = handler.expandMacro("select u from sec$User " + + "where @between(u.createTs, now-10, now+1, minute) or @between(u.createTs, now-20, now-10, minute)" + + " and u.deleteTs is null"); + System.out.println(res); + System.out.println(handler.getParams()); + + handler = new TimeBetweenQueryMacroHandler(); + res = handler.expandMacro("select u from sec$User where @between(u.createTs, now-5+2, now, day) and u.deleteTs is null"); + System.out.println(res); + System.out.println(handler.getParams()); + } + + @Test + public void testReplaceQueryParams() { + Map params = new HashMap<>(); + params.put("param1", 5); + TimeBetweenQueryMacroHandler handler = new TimeBetweenQueryMacroHandler(); + String res = handler.replaceQueryParams("select u from sec$User where @between(u.createTs, now, now+:param1, day) and u.deleteTs is null", params); + System.out.println(res); + } +} diff --git a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandlerTest.java b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandlerTest.java index dcaafaf7f1..c881e1088b 100644 --- a/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandlerTest.java +++ b/modules/core/test/com/haulmont/cuba/core/sys/querymacro/TimeTodayQueryMacroHandlerTest.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.querymacro; - -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -public class TimeTodayQueryMacroHandlerTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void testExpandMacro() throws Exception { - TimeTodayQueryMacroHandler handler = new TimeTodayQueryMacroHandler(); - String res = handler.expandMacro("select u from sec$User where @today(u.createTs) and u.deleteTs is null"); - System.out.println(res); - System.out.println(handler.getParams()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.querymacro; + +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +public class TimeTodayQueryMacroHandlerTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void testExpandMacro() throws Exception { + TimeTodayQueryMacroHandler handler = new TimeTodayQueryMacroHandler(); + String res = handler.expandMacro("select u from sec$User where @today(u.createTs) and u.deleteTs is null"); + System.out.println(res); + System.out.println(handler.getParams()); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/security/ConstraintTest.java b/modules/core/test/com/haulmont/cuba/security/ConstraintTest.java index 2b8db1960e..73cda1d486 100644 --- a/modules/core/test/com/haulmont/cuba/security/ConstraintTest.java +++ b/modules/core/test/com/haulmont/cuba/security/ConstraintTest.java @@ -1,194 +1,194 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.entity.Server; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.security.app.LoginWorker; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.security.global.ConstraintData; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestUserSessionSource; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.List; -import java.util.Locale; -import java.util.UUID; - -import static org.junit.Assert.*; - -@SuppressWarnings("IncorrectCreateEntity") -public class ConstraintTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private static final String USER_LOGIN = "testUser"; - private static final String USER_PASSW = "testUser"; - - private UUID serverConstraintId, userRoleConstraintId, parentConstraintId, groupId, otherGroupId, parentGroupId, - userId, user2Id, userRoleId, roleId; - private UUID serverId; - - private PasswordEncryption passwordEncryption; - - @Before - public void setUp() throws Exception { - passwordEncryption = AppBeans.get(PasswordEncryption.class); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Server server = new Server(); - server.setName("someServer"); - server.setRunning(false); - serverId = server.getId(); - em.persist(server); - - Group parentGroup = new Group(); - parentGroupId = parentGroup.getId(); - parentGroup.setName("testParentGroup"); - em.persist(parentGroup); - - tx.commitRetaining(); - em = cont.persistence().getEntityManager(); - - Constraint parentConstraint = new Constraint(); - parentConstraintId = parentConstraint.getId(); - parentConstraint.setEntityName("sys$Server"); - parentConstraint.setWhereClause("{E}.running = true"); - parentConstraint.setGroup(parentGroup); - em.persist(parentConstraint); - - Group group = new Group(); - groupId = group.getId(); - group.setName("testGroup"); - group.setParent(parentGroup); - em.persist(group); - - Constraint serverConstraint = new Constraint(); - serverConstraintId = serverConstraint.getId(); - serverConstraint.setEntityName("sys$Server"); - serverConstraint.setWhereClause("{E}.name = 'localhost'"); - serverConstraint.setGroup(group); - em.persist(serverConstraint); - - Constraint userRoleConstraint = new Constraint(); - userRoleConstraintId = userRoleConstraint.getId(); - userRoleConstraint.setEntityName("sec$UserRole"); - userRoleConstraint.setWhereClause("{E}.user.id = :session$userId"); - userRoleConstraint.setGroup(group); - em.persist(userRoleConstraint); - - User user = new User(); - userId = user.getId(); - user.setLogin(USER_LOGIN); - - String pwd = passwordEncryption.getPasswordHash(userId, USER_PASSW); - user.setPassword(pwd); - - user.setGroup(group); - em.persist(user); - - Group otherGroup = new Group(); - otherGroupId = otherGroup.getId(); - otherGroup.setName("otherGroup"); - otherGroup.setParent(parentGroup); - em.persist(otherGroup); - - User user2 = new User(); - user2.setGroup(otherGroup); - user2Id = user2.getId(); - user2.setLogin("someOtherUser"); - em.persist(user2); - - UserRole userRole = new UserRole(); - userRoleId = userRole.getId(); - userRole.setUser(user2); - Role role = new Role(); - role.setName("TestRole"); - roleId = role.getId(); - em.persist(role); - userRole.setRole(role); - - em.persist(userRole); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SYS_SERVER", serverId); - cont.deleteRecord("SEC_USER_ROLE", userRoleId); - cont.deleteRecord("SEC_ROLE", roleId); - cont.deleteRecord("SEC_USER", userId, user2Id); - cont.deleteRecord("SEC_CONSTRAINT", "ID", parentConstraintId, serverConstraintId, userRoleConstraintId); - cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", groupId, otherGroupId); - cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", otherGroupId); - cont.deleteRecord("SEC_GROUP", groupId, otherGroupId); - cont.deleteRecord("SEC_GROUP", parentGroupId); - } - - @Test - public void test() throws LoginException { - LoginWorker lw = AppBeans.get(LoginWorker.NAME); - - UserSession userSession = lw.login(USER_LOGIN, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); - assertNotNull(userSession); - - List constraints = userSession.getConstraints("sys$Server"); - assertEquals(2, constraints.size()); - - List roleConstraints = userSession.getConstraints("sec$UserRole"); - assertEquals(1, roleConstraints.size()); - - UserSessionSource uss = AppBeans.get(UserSessionSource.class); - UserSession savedUserSession = uss.getUserSession(); - ((TestUserSessionSource) uss).setUserSession(userSession); - try { - DataManager dm = AppBeans.get(DataManager.NAME); - LoadContext loadContext = new LoadContext(Server.class) - .setQuery(new LoadContext.Query("select s from sys$Server s")); - List list = dm.loadList(loadContext); - for (Server server : list) { - if (server.getId().equals(serverId)) - fail("Constraints have not taken effect for some reason"); - } - - //test constraint that contains session parameter - loadContext = new LoadContext(UserRole.class) - .setQuery(new LoadContext.Query("select ur from sec$UserRole ur")); - List userRoles = dm.loadList(loadContext); - if (!userRoles.isEmpty()) { - fail("Constraint with session attribute failed"); - } - } finally { - ((TestUserSessionSource) uss).setUserSession(savedUserSession); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.entity.Server; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.security.app.LoginWorker; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.security.global.ConstraintData; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestUserSessionSource; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +import static org.junit.Assert.*; + +@SuppressWarnings("IncorrectCreateEntity") +public class ConstraintTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private static final String USER_LOGIN = "testUser"; + private static final String USER_PASSW = "testUser"; + + private UUID serverConstraintId, userRoleConstraintId, parentConstraintId, groupId, otherGroupId, parentGroupId, + userId, user2Id, userRoleId, roleId; + private UUID serverId; + + private PasswordEncryption passwordEncryption; + + @Before + public void setUp() throws Exception { + passwordEncryption = AppBeans.get(PasswordEncryption.class); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Server server = new Server(); + server.setName("someServer"); + server.setRunning(false); + serverId = server.getId(); + em.persist(server); + + Group parentGroup = new Group(); + parentGroupId = parentGroup.getId(); + parentGroup.setName("testParentGroup"); + em.persist(parentGroup); + + tx.commitRetaining(); + em = cont.persistence().getEntityManager(); + + Constraint parentConstraint = new Constraint(); + parentConstraintId = parentConstraint.getId(); + parentConstraint.setEntityName("sys$Server"); + parentConstraint.setWhereClause("{E}.running = true"); + parentConstraint.setGroup(parentGroup); + em.persist(parentConstraint); + + Group group = new Group(); + groupId = group.getId(); + group.setName("testGroup"); + group.setParent(parentGroup); + em.persist(group); + + Constraint serverConstraint = new Constraint(); + serverConstraintId = serverConstraint.getId(); + serverConstraint.setEntityName("sys$Server"); + serverConstraint.setWhereClause("{E}.name = 'localhost'"); + serverConstraint.setGroup(group); + em.persist(serverConstraint); + + Constraint userRoleConstraint = new Constraint(); + userRoleConstraintId = userRoleConstraint.getId(); + userRoleConstraint.setEntityName("sec$UserRole"); + userRoleConstraint.setWhereClause("{E}.user.id = :session$userId"); + userRoleConstraint.setGroup(group); + em.persist(userRoleConstraint); + + User user = new User(); + userId = user.getId(); + user.setLogin(USER_LOGIN); + + String pwd = passwordEncryption.getPasswordHash(userId, USER_PASSW); + user.setPassword(pwd); + + user.setGroup(group); + em.persist(user); + + Group otherGroup = new Group(); + otherGroupId = otherGroup.getId(); + otherGroup.setName("otherGroup"); + otherGroup.setParent(parentGroup); + em.persist(otherGroup); + + User user2 = new User(); + user2.setGroup(otherGroup); + user2Id = user2.getId(); + user2.setLogin("someOtherUser"); + em.persist(user2); + + UserRole userRole = new UserRole(); + userRoleId = userRole.getId(); + userRole.setUser(user2); + Role role = new Role(); + role.setName("TestRole"); + roleId = role.getId(); + em.persist(role); + userRole.setRole(role); + + em.persist(userRole); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SYS_SERVER", serverId); + cont.deleteRecord("SEC_USER_ROLE", userRoleId); + cont.deleteRecord("SEC_ROLE", roleId); + cont.deleteRecord("SEC_USER", userId, user2Id); + cont.deleteRecord("SEC_CONSTRAINT", "ID", parentConstraintId, serverConstraintId, userRoleConstraintId); + cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", groupId, otherGroupId); + cont.deleteRecord("SEC_GROUP_HIERARCHY", "GROUP_ID", otherGroupId); + cont.deleteRecord("SEC_GROUP", groupId, otherGroupId); + cont.deleteRecord("SEC_GROUP", parentGroupId); + } + + @Test + public void test() throws LoginException { + LoginWorker lw = AppBeans.get(LoginWorker.NAME); + + UserSession userSession = lw.login(USER_LOGIN, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); + assertNotNull(userSession); + + List constraints = userSession.getConstraints("sys$Server"); + assertEquals(2, constraints.size()); + + List roleConstraints = userSession.getConstraints("sec$UserRole"); + assertEquals(1, roleConstraints.size()); + + UserSessionSource uss = AppBeans.get(UserSessionSource.class); + UserSession savedUserSession = uss.getUserSession(); + ((TestUserSessionSource) uss).setUserSession(userSession); + try { + DataManager dm = AppBeans.get(DataManager.NAME); + LoadContext loadContext = new LoadContext(Server.class) + .setQuery(new LoadContext.Query("select s from sys$Server s")); + List list = dm.loadList(loadContext); + for (Server server : list) { + if (server.getId().equals(serverId)) + fail("Constraints have not taken effect for some reason"); + } + + //test constraint that contains session parameter + loadContext = new LoadContext(UserRole.class) + .setQuery(new LoadContext.Query("select ur from sec$UserRole ur")); + List userRoles = dm.loadList(loadContext); + if (!userRoles.isEmpty()) { + fail("Constraint with session attribute failed"); + } + } finally { + ((TestUserSessionSource) uss).setUserSession(savedUserSession); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/security/EntityLogTest.java b/modules/core/test/com/haulmont/cuba/security/EntityLogTest.java index 87b8401a32..1b2f19182e 100644 --- a/modules/core/test/com/haulmont/cuba/security/EntityLogTest.java +++ b/modules/core/test/com/haulmont/cuba/security/EntityLogTest.java @@ -1,334 +1,334 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.TypedQuery; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.security.app.EntityLogAPI; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.sql.SQLException; -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class EntityLogTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID userId; - private UUID roleId; - - private EntityLogAPI entityLog; - - @Before - public void setUp() throws Exception { - cleanup(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query q; - q = em.createNativeQuery("delete from SEC_ENTITY_LOG"); - q.executeUpdate(); - - LoggedEntity le = new LoggedEntity(); - le.setName("sec$User"); - le.setAuto(true); - em.persist(le); - - LoggedAttribute la = new LoggedAttribute(); - la.setEntity(le); - la.setName("email"); - em.persist(la); - - le = new LoggedEntity(); - le.setName("sec$Role"); - le.setAuto(true); - em.persist(le); - - la = new LoggedAttribute(); - la.setEntity(le); - la.setName("type"); - em.persist(la); - - tx.commit(); - } finally { - tx.end(); - } - - entityLog = AppBeans.get(EntityLogAPI.NAME); - entityLog.invalidateCache(); - } - - @After - public void tearDown() throws Exception { - cleanup(); - - if (userId != null) - cont.deleteRecord("SEC_USER", userId); - - if (roleId != null) - cont.deleteRecord("SEC_ROLE", roleId); - } - - private void cleanup() throws SQLException { - QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); - runner.update("delete from SEC_LOGGED_ATTR"); - runner.update("delete from SEC_LOGGED_ENTITY"); - } - - @Test - public void test() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); - - User user = new User(); - userId = user.getId(); - user.setGroup(group); - user.setLogin("test"); - user.setName("test-name"); - em.persist(user); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, userId); - user.setEmail("test-email"); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, userId); - user.setName("test-name-1"); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, userId); - user.setEmail("test-email-1"); - - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, userId); - em.remove(user); - - tx.commit(); - } finally { - tx.end(); - } - - List items; - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - TypedQuery query = em.createQuery( - "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2", EntityLogItem.class); - query.setParameter(1, "sec$User"); - query.setParameter(2, userId); - items = query.getResultList(); - - tx.commit(); - } finally { - tx.end(); - } - assertNotNull(items); - assertEquals(4, items.size()); - assertNotNull(items.get(0).getAttributes()); - assertEquals(1, items.get(0).getAttributes().size()); - } - - @Test - public void testEnumDisplayValue() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Role role = new Role(); - roleId = role.getId(); - role.setName("role1"); - role.setType(RoleType.READONLY); - em.persist(role); - - tx.commit(); - } finally { - tx.end(); - } - - List items; - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - TypedQuery query = em.createQuery( - "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2", EntityLogItem.class); - query.setParameter(1, "sec$Role"); - query.setParameter(2, roleId); - items = query.getResultList(); - - tx.commit(); - } finally { - tx.end(); - } - assertNotNull(items); - assertEquals(1, items.size()); - assertNotNull(items.get(0).getAttributes()); - assertEquals(1, items.get(0).getAttributes().size()); - - EntityLogAttr attr = items.get(0).getAttributes().iterator().next(); - - Messages messages = AppBeans.get(Messages.NAME); - assertEquals(messages.getMessage(RoleType.READONLY), attr.getDisplayValue()); - } - - @Test - public void testMultipleFlush() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); - - User user = new User(); - userId = user.getId(); - user.setGroup(group); - user.setLogin("test"); - user.setName("test-name"); - user.setEmail("name@test.com"); - em.persist(user); - - em.flush(); - - user.setEmail("changed-name@test.com"); - - tx.commit(); - } finally { - tx.end(); - } - - List items = getEntityLogItems(); - assertNotNull(items); - assertEquals(1, items.size()); - - EntityLogItem item = items.get(0); - assertEquals(EntityLogItem.Type.CREATE, item.getType()); - - EntityLogAttr attr = Iterables.find(item.getAttributes(), new Predicate() { - @Override - public boolean apply(EntityLogAttr attr) { - return "email".equals(attr.getName()); - } - }); - assertEquals("changed-name@test.com", attr.getValue()); - - //////// - - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, userId); - user.setEmail("changed-2@test.com"); - - em.flush(); - - user.setEmail("changed-3@test.com"); - - tx.commit(); - } finally { - tx.end(); - } - - items = getEntityLogItems(); - assertNotNull(items); - assertEquals(2, items.size()); - - item = items.get(0); // the last because of sorting in query - assertEquals(EntityLogItem.Type.MODIFY, item.getType()); - - attr = Iterables.find(item.getAttributes(), new Predicate() { - @Override - public boolean apply(EntityLogAttr attr) { - return "email".equals(attr.getName()); - } - }); - assertEquals("changed-3@test.com", attr.getValue()); - assertEquals("changed-2@test.com", attr.getOldValue()); - } - - private List getEntityLogItems() { - Transaction tx; - List items; - tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - TypedQuery query = em.createQuery( - "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2 order by i.eventTs desc", EntityLogItem.class); - query.setParameter(1, "sec$User"); - query.setParameter(2, userId); - items = query.getResultList(); - - tx.commit(); - } finally { - tx.end(); - } - return items; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.TypedQuery; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.security.app.EntityLogAPI; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.sql.SQLException; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class EntityLogTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID userId; + private UUID roleId; + + private EntityLogAPI entityLog; + + @Before + public void setUp() throws Exception { + cleanup(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query q; + q = em.createNativeQuery("delete from SEC_ENTITY_LOG"); + q.executeUpdate(); + + LoggedEntity le = new LoggedEntity(); + le.setName("sec$User"); + le.setAuto(true); + em.persist(le); + + LoggedAttribute la = new LoggedAttribute(); + la.setEntity(le); + la.setName("email"); + em.persist(la); + + le = new LoggedEntity(); + le.setName("sec$Role"); + le.setAuto(true); + em.persist(le); + + la = new LoggedAttribute(); + la.setEntity(le); + la.setName("type"); + em.persist(la); + + tx.commit(); + } finally { + tx.end(); + } + + entityLog = AppBeans.get(EntityLogAPI.NAME); + entityLog.invalidateCache(); + } + + @After + public void tearDown() throws Exception { + cleanup(); + + if (userId != null) + cont.deleteRecord("SEC_USER", userId); + + if (roleId != null) + cont.deleteRecord("SEC_ROLE", roleId); + } + + private void cleanup() throws SQLException { + QueryRunner runner = new QueryRunner(cont.persistence().getDataSource()); + runner.update("delete from SEC_LOGGED_ATTR"); + runner.update("delete from SEC_LOGGED_ENTITY"); + } + + @Test + public void test() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); + + User user = new User(); + userId = user.getId(); + user.setGroup(group); + user.setLogin("test"); + user.setName("test-name"); + em.persist(user); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, userId); + user.setEmail("test-email"); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, userId); + user.setName("test-name-1"); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, userId); + user.setEmail("test-email-1"); + + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, userId); + em.remove(user); + + tx.commit(); + } finally { + tx.end(); + } + + List items; + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + TypedQuery query = em.createQuery( + "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2", EntityLogItem.class); + query.setParameter(1, "sec$User"); + query.setParameter(2, userId); + items = query.getResultList(); + + tx.commit(); + } finally { + tx.end(); + } + assertNotNull(items); + assertEquals(4, items.size()); + assertNotNull(items.get(0).getAttributes()); + assertEquals(1, items.get(0).getAttributes().size()); + } + + @Test + public void testEnumDisplayValue() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Role role = new Role(); + roleId = role.getId(); + role.setName("role1"); + role.setType(RoleType.READONLY); + em.persist(role); + + tx.commit(); + } finally { + tx.end(); + } + + List items; + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + TypedQuery query = em.createQuery( + "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2", EntityLogItem.class); + query.setParameter(1, "sec$Role"); + query.setParameter(2, roleId); + items = query.getResultList(); + + tx.commit(); + } finally { + tx.end(); + } + assertNotNull(items); + assertEquals(1, items.size()); + assertNotNull(items.get(0).getAttributes()); + assertEquals(1, items.get(0).getAttributes().size()); + + EntityLogAttr attr = items.get(0).getAttributes().iterator().next(); + + Messages messages = AppBeans.get(Messages.NAME); + assertEquals(messages.getMessage(RoleType.READONLY), attr.getDisplayValue()); + } + + @Test + public void testMultipleFlush() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.find(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); + + User user = new User(); + userId = user.getId(); + user.setGroup(group); + user.setLogin("test"); + user.setName("test-name"); + user.setEmail("name@test.com"); + em.persist(user); + + em.flush(); + + user.setEmail("changed-name@test.com"); + + tx.commit(); + } finally { + tx.end(); + } + + List items = getEntityLogItems(); + assertNotNull(items); + assertEquals(1, items.size()); + + EntityLogItem item = items.get(0); + assertEquals(EntityLogItem.Type.CREATE, item.getType()); + + EntityLogAttr attr = Iterables.find(item.getAttributes(), new Predicate() { + @Override + public boolean apply(EntityLogAttr attr) { + return "email".equals(attr.getName()); + } + }); + assertEquals("changed-name@test.com", attr.getValue()); + + //////// + + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, userId); + user.setEmail("changed-2@test.com"); + + em.flush(); + + user.setEmail("changed-3@test.com"); + + tx.commit(); + } finally { + tx.end(); + } + + items = getEntityLogItems(); + assertNotNull(items); + assertEquals(2, items.size()); + + item = items.get(0); // the last because of sorting in query + assertEquals(EntityLogItem.Type.MODIFY, item.getType()); + + attr = Iterables.find(item.getAttributes(), new Predicate() { + @Override + public boolean apply(EntityLogAttr attr) { + return "email".equals(attr.getName()); + } + }); + assertEquals("changed-3@test.com", attr.getValue()); + assertEquals("changed-2@test.com", attr.getOldValue()); + } + + private List getEntityLogItems() { + Transaction tx; + List items; + tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + TypedQuery query = em.createQuery( + "select i from sec$EntityLog i where i.entity = ?1 and i.entityRef.entityId = ?2 order by i.eventTs desc", EntityLogItem.class); + query.setParameter(1, "sec$User"); + query.setParameter(2, userId); + items = query.getResultList(); + + tx.commit(); + } finally { + tx.end(); + } + return items; + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/security/GroupTest.java b/modules/core/test/com/haulmont/cuba/security/GroupTest.java index 8927c2e576..d79e62eaa5 100644 --- a/modules/core/test/com/haulmont/cuba/security/GroupTest.java +++ b/modules/core/test/com/haulmont/cuba/security/GroupTest.java @@ -1,139 +1,139 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.GroupHierarchy; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.UUID; - -import static org.junit.Assert.assertEquals; - -public class GroupTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UUID rootId, group1Id, group2Id, group3Id; - - private void createGroups() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Group root = new Group(); - rootId = root.getId(); - root.setName("root"); - em.persist(root); - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - root = em.find(Group.class, rootId); - Group group1 = new Group(); - group1Id = group1.getId(); - group1.setName("group1"); - group1.setParent(root); - em.persist(group1); - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - group1 = em.find(Group.class, group1Id); - Group group2 = new Group(); - group2Id = group2.getId(); - group2.setName("group2"); - group2.setParent(group1); - em.persist(group2); - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - root = em.find(Group.class, rootId); - Group group3 = new Group(); - group3Id = group3.getId(); - group3.setName("group3"); - group3.setParent(root); - em.persist(group3); - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testNew() { - createGroups(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Group group2 = em.find(Group.class, group2Id); - for (GroupHierarchy hierarchy : group2.getHierarchyList()) { - assertEquals(group2, hierarchy.getGroup()); - if (hierarchy.getLevel() == 0) - assertEquals(rootId, hierarchy.getParent().getId()); - else if (hierarchy.getLevel() == 1) - assertEquals(group1Id, hierarchy.getParent().getId()); - } - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void testUpdate() { - createGroups(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Group group1 = em.find(Group.class, group1Id); - Group group3 = em.find(Group.class, group3Id); - group1.setParent(group3); - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - - group1 = em.find(Group.class, group1Id); - for (GroupHierarchy hierarchy : group1.getHierarchyList()) { - assertEquals(group1, hierarchy.getGroup()); - if (hierarchy.getLevel() == 0) - assertEquals(rootId, hierarchy.getParent().getId()); - else if (hierarchy.getLevel() == 1) - assertEquals(group3Id, hierarchy.getParent().getId()); - } - - Group group2 = em.find(Group.class, group2Id); - for (GroupHierarchy hierarchy : group2.getHierarchyList()) { - assertEquals(group2, hierarchy.getGroup()); - if (hierarchy.getLevel() == 0) - assertEquals(rootId, hierarchy.getParent().getId()); - else if (hierarchy.getLevel() == 1) - assertEquals(group3Id, hierarchy.getParent().getId()); - else if (hierarchy.getLevel() == 2) - assertEquals(group1Id, hierarchy.getParent().getId()); - } - - tx.commit(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.GroupHierarchy; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.UUID; + +import static org.junit.Assert.assertEquals; + +public class GroupTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UUID rootId, group1Id, group2Id, group3Id; + + private void createGroups() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Group root = new Group(); + rootId = root.getId(); + root.setName("root"); + em.persist(root); + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + root = em.find(Group.class, rootId); + Group group1 = new Group(); + group1Id = group1.getId(); + group1.setName("group1"); + group1.setParent(root); + em.persist(group1); + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + group1 = em.find(Group.class, group1Id); + Group group2 = new Group(); + group2Id = group2.getId(); + group2.setName("group2"); + group2.setParent(group1); + em.persist(group2); + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + root = em.find(Group.class, rootId); + Group group3 = new Group(); + group3Id = group3.getId(); + group3.setName("group3"); + group3.setParent(root); + em.persist(group3); + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testNew() { + createGroups(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Group group2 = em.find(Group.class, group2Id); + for (GroupHierarchy hierarchy : group2.getHierarchyList()) { + assertEquals(group2, hierarchy.getGroup()); + if (hierarchy.getLevel() == 0) + assertEquals(rootId, hierarchy.getParent().getId()); + else if (hierarchy.getLevel() == 1) + assertEquals(group1Id, hierarchy.getParent().getId()); + } + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void testUpdate() { + createGroups(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Group group1 = em.find(Group.class, group1Id); + Group group3 = em.find(Group.class, group3Id); + group1.setParent(group3); + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + + group1 = em.find(Group.class, group1Id); + for (GroupHierarchy hierarchy : group1.getHierarchyList()) { + assertEquals(group1, hierarchy.getGroup()); + if (hierarchy.getLevel() == 0) + assertEquals(rootId, hierarchy.getParent().getId()); + else if (hierarchy.getLevel() == 1) + assertEquals(group3Id, hierarchy.getParent().getId()); + } + + Group group2 = em.find(Group.class, group2Id); + for (GroupHierarchy hierarchy : group2.getHierarchyList()) { + assertEquals(group2, hierarchy.getGroup()); + if (hierarchy.getLevel() == 0) + assertEquals(rootId, hierarchy.getParent().getId()); + else if (hierarchy.getLevel() == 1) + assertEquals(group3Id, hierarchy.getParent().getId()); + else if (hierarchy.getLevel() == 2) + assertEquals(group1Id, hierarchy.getParent().getId()); + } + + tx.commit(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/security/LoginTest.java b/modules/core/test/com/haulmont/cuba/security/LoginTest.java index ee039f68ad..eb77d79866 100644 --- a/modules/core/test/com/haulmont/cuba/security/LoginTest.java +++ b/modules/core/test/com/haulmont/cuba/security/LoginTest.java @@ -1,185 +1,185 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.PasswordEncryption; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.security.app.LoginWorker; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserSubstitution; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestUserSessionSource; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.Locale; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class LoginTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private PasswordEncryption passwordEncryption; - - private LoginWorker loginWorker; - - private UUID user1Id; - private UUID user2Id; - private UUID substitutionId; - private TestUserSessionSource userSessionSource; - private UserSession standardTestUserSession; - - @Before - public void setUp() throws Exception { - passwordEncryption = AppBeans.get(PasswordEncryption.NAME); - loginWorker = AppBeans.get(LoginWorker.NAME); - userSessionSource = AppBeans.get(UserSessionSource.NAME); - standardTestUserSession = userSessionSource.getUserSession(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Group group = em.getReference(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); - - User user1 = new User(); - user1Id = user1.getId(); - user1.setGroup(group); - user1.setLogin("user1"); - user1.setPassword(passwordEncryption.getPasswordHash(user1.getId(), "1")); - em.persist(user1); - - User user2 = new User(); - user2Id = user2.getId(); - user2.setGroup(group); - user2.setLogin("user2"); - user2.setPassword(passwordEncryption.getPasswordHash(user2.getId(), "2")); - em.persist(user2); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - cont.deleteRecord("SEC_USER_SUBSTITUTION", substitutionId); - cont.deleteRecord("SEC_USER", user1Id); - cont.deleteRecord("SEC_USER", user2Id); - - userSessionSource.setUserSession(standardTestUserSession); - } - - private User loadUser(final UUID userId) { - return cont.persistence().createTransaction().execute(new Transaction.Callable() { - @Override - public User call(EntityManager em) { - return em.find(User.class, userId); - } - }); - } - - @Test - public void testUserSubstitution() throws Exception { - // Log in - UserSession session1 = loginWorker.login("user1", passwordEncryption.getPlainHash("1"), Locale.forLanguageTag("en")); - userSessionSource.setUserSession(session1); - - // Substitute a user that is not in our substitutions list - fail - User user2 = loadUser(user2Id); - try { - loginWorker.substituteUser(user2); - fail(); - } catch (Exception e) { - // ok - } - - // Create a substitution - cont.persistence().createTransaction().execute(new Transaction.Runnable() { - @Override - public void run(EntityManager em) { - UserSubstitution substitution = new UserSubstitution(); - substitutionId = substitution.getId(); - substitution.setUser(em.getReference(User.class, user1Id)); - substitution.setSubstitutedUser(em.getReference(User.class, user2Id)); - em.persist(substitution); - } - }); - - // Try again - succeed - UserSession session2 = loginWorker.substituteUser(user2); - userSessionSource.setUserSession(session2); - assertEquals(session1.getId(), session2.getId()); - assertEquals(user1Id, session2.getUser().getId()); - assertEquals(user2Id, session2.getSubstitutedUser().getId()); - - // Switch back to the logged in user - User user1 = loadUser(user1Id); - UserSession session3 = loginWorker.substituteUser(user1); - assertEquals(session1.getId(), session3.getId()); - assertEquals(user1Id, session3.getUser().getId()); - assertNull(session3.getSubstitutedUser()); - } - - @Test - public void testUserSubstitutionSoftDelete() throws Exception { - // Create a substitution - cont.persistence().createTransaction().execute(new Transaction.Runnable() { - @Override - public void run(EntityManager em) { - UserSubstitution substitution = new UserSubstitution(); - substitutionId = substitution.getId(); - substitution.setUser(em.getReference(User.class, user1Id)); - substitution.setSubstitutedUser(em.getReference(User.class, user2Id)); - em.persist(substitution); - } - }); - - // Soft delete it - cont.persistence().createTransaction().execute(new Transaction.Runnable() { - @Override - public void run(EntityManager em) { - UserSubstitution substitution = em.getReference(UserSubstitution.class, substitutionId); - em.remove(substitution); - } - }); - - // Log in - UserSession session1 = loginWorker.login("user1", passwordEncryption.getPlainHash("1"), Locale.forLanguageTag("en")); - userSessionSource.setUserSession(session1); - - // Try to substitute - fail - User user2 = loadUser(user2Id); - try { - loginWorker.substituteUser(user2); - fail(); - } catch (Exception e) { - // ok - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.PasswordEncryption; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.security.app.LoginWorker; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserSubstitution; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestUserSessionSource; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.Locale; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class LoginTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private PasswordEncryption passwordEncryption; + + private LoginWorker loginWorker; + + private UUID user1Id; + private UUID user2Id; + private UUID substitutionId; + private TestUserSessionSource userSessionSource; + private UserSession standardTestUserSession; + + @Before + public void setUp() throws Exception { + passwordEncryption = AppBeans.get(PasswordEncryption.NAME); + loginWorker = AppBeans.get(LoginWorker.NAME); + userSessionSource = AppBeans.get(UserSessionSource.NAME); + standardTestUserSession = userSessionSource.getUserSession(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Group group = em.getReference(Group.class, UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93")); + + User user1 = new User(); + user1Id = user1.getId(); + user1.setGroup(group); + user1.setLogin("user1"); + user1.setPassword(passwordEncryption.getPasswordHash(user1.getId(), "1")); + em.persist(user1); + + User user2 = new User(); + user2Id = user2.getId(); + user2.setGroup(group); + user2.setLogin("user2"); + user2.setPassword(passwordEncryption.getPasswordHash(user2.getId(), "2")); + em.persist(user2); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + cont.deleteRecord("SEC_USER_SUBSTITUTION", substitutionId); + cont.deleteRecord("SEC_USER", user1Id); + cont.deleteRecord("SEC_USER", user2Id); + + userSessionSource.setUserSession(standardTestUserSession); + } + + private User loadUser(final UUID userId) { + return cont.persistence().createTransaction().execute(new Transaction.Callable() { + @Override + public User call(EntityManager em) { + return em.find(User.class, userId); + } + }); + } + + @Test + public void testUserSubstitution() throws Exception { + // Log in + UserSession session1 = loginWorker.login("user1", passwordEncryption.getPlainHash("1"), Locale.forLanguageTag("en")); + userSessionSource.setUserSession(session1); + + // Substitute a user that is not in our substitutions list - fail + User user2 = loadUser(user2Id); + try { + loginWorker.substituteUser(user2); + fail(); + } catch (Exception e) { + // ok + } + + // Create a substitution + cont.persistence().createTransaction().execute(new Transaction.Runnable() { + @Override + public void run(EntityManager em) { + UserSubstitution substitution = new UserSubstitution(); + substitutionId = substitution.getId(); + substitution.setUser(em.getReference(User.class, user1Id)); + substitution.setSubstitutedUser(em.getReference(User.class, user2Id)); + em.persist(substitution); + } + }); + + // Try again - succeed + UserSession session2 = loginWorker.substituteUser(user2); + userSessionSource.setUserSession(session2); + assertEquals(session1.getId(), session2.getId()); + assertEquals(user1Id, session2.getUser().getId()); + assertEquals(user2Id, session2.getSubstitutedUser().getId()); + + // Switch back to the logged in user + User user1 = loadUser(user1Id); + UserSession session3 = loginWorker.substituteUser(user1); + assertEquals(session1.getId(), session3.getId()); + assertEquals(user1Id, session3.getUser().getId()); + assertNull(session3.getSubstitutedUser()); + } + + @Test + public void testUserSubstitutionSoftDelete() throws Exception { + // Create a substitution + cont.persistence().createTransaction().execute(new Transaction.Runnable() { + @Override + public void run(EntityManager em) { + UserSubstitution substitution = new UserSubstitution(); + substitutionId = substitution.getId(); + substitution.setUser(em.getReference(User.class, user1Id)); + substitution.setSubstitutedUser(em.getReference(User.class, user2Id)); + em.persist(substitution); + } + }); + + // Soft delete it + cont.persistence().createTransaction().execute(new Transaction.Runnable() { + @Override + public void run(EntityManager em) { + UserSubstitution substitution = em.getReference(UserSubstitution.class, substitutionId); + em.remove(substitution); + } + }); + + // Log in + UserSession session1 = loginWorker.login("user1", passwordEncryption.getPlainHash("1"), Locale.forLanguageTag("en")); + userSessionSource.setUserSession(session1); + + // Try to substitute - fail + User user2 = loadUser(user2Id); + try { + loginWorker.substituteUser(user2); + fail(); + } catch (Exception e) { + // ok + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/security/PermissionTest.java b/modules/core/test/com/haulmont/cuba/security/PermissionTest.java index 8781d75260..3f0901a380 100644 --- a/modules/core/test/com/haulmont/cuba/security/PermissionTest.java +++ b/modules/core/test/com/haulmont/cuba/security/PermissionTest.java @@ -1,223 +1,223 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.PasswordEncryption; -import com.haulmont.cuba.security.app.LoginWorker; -import com.haulmont.cuba.security.entity.*; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.Locale; -import java.util.UUID; - -import static org.junit.Assert.*; - -public class PermissionTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private static final String USER_NAME = "testUser"; - private static final String USER_PASSW = "testUser"; - private static final String PERM_TARGET_SCREEN = "w:sys$Server.browse"; - private static final String PERM_TARGET_ATTR = "sys$Server:address"; - - private UUID role1Id, permission1Id, role2Id, permission2Id, userId, groupId, - userRole1Id, userRole2Id; - - private PasswordEncryption passwordEncryption; - - @Before - public void setUp() throws Exception { - passwordEncryption = AppBeans.get(PasswordEncryption.class); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Role role1 = new Role(); - role1Id = role1.getId(); - role1.setName("testRole1"); - em.persist(role1); - - Role role2 = new Role(); - role2Id = role2.getId(); - role2.setName("testRole2"); - em.persist(role2); - - Permission permission1 = new Permission(); - permission1Id = permission1.getId(); - permission1.setRole(role1); - permission1.setType(PermissionType.SCREEN); - permission1.setTarget(PERM_TARGET_SCREEN); - permission1.setValue(0); - em.persist(permission1); - - Permission permission2 = new Permission(); - permission2Id = permission2.getId(); - permission2.setRole(role2); - permission2.setType(PermissionType.ENTITY_ATTR); - permission2.setTarget(PERM_TARGET_ATTR); - permission2.setValue(1); - em.persist(permission2); - - Group group = new Group(); - groupId = group.getId(); - group.setName("testGroup"); - em.persist(group); - - User user = new User(); - userId = user.getId(); - user.setName(USER_NAME); - user.setLogin(USER_NAME); - - String pwd = passwordEncryption.getPasswordHash(userId, USER_PASSW); - user.setPassword(pwd); - - user.setGroup(group); - em.persist(user); - - UserRole userRole1 = new UserRole(); - userRole1Id = userRole1.getId(); - userRole1.setUser(user); - userRole1.setRole(role1); - em.persist(userRole1); - - UserRole userRole2 = new UserRole(); - userRole2Id = userRole2.getId(); - userRole2.setUser(user); - userRole2.setRole(role2); - em.persist(userRole2); - - tx.commit(); - } finally { - tx.end(); - } - } - - @After - public void tearDown() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Query q; - - q = em.createNativeQuery("delete from SEC_USER_ROLE where ID = ? or ID = ?"); - q.setParameter(1, userRole1Id.toString()); - q.setParameter(2, userRole2Id.toString()); - q.executeUpdate(); - - q = em.createNativeQuery("delete from SEC_USER where ID = ?"); - q.setParameter(1, userId.toString()); - q.executeUpdate(); - - q = em.createNativeQuery("delete from SEC_GROUP where ID = ?"); - q.setParameter(1, groupId.toString()); - q.executeUpdate(); - - q = em.createNativeQuery("delete from SEC_PERMISSION where ID = ? or ID = ?"); - q.setParameter(1, permission1Id.toString()); - q.setParameter(2, permission2Id.toString()); - q.executeUpdate(); - - q = em.createNativeQuery("delete from SEC_ROLE where ID = ? or ID = ?"); - q.setParameter(1, role1Id.toString()); - q.setParameter(2, role2Id.toString()); - q.executeUpdate(); - - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void test() throws LoginException { - LoginWorker lw = AppBeans.get(LoginWorker.NAME); - - UserSession userSession = lw.login(USER_NAME, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); - assertNotNull(userSession); - - boolean permitted = userSession.isPermitted(PermissionType.SCREEN, PERM_TARGET_SCREEN); - assertFalse(permitted); - - permitted = userSession.isPermitted(PermissionType.SCREEN, "some action"); - assertTrue(permitted); // permitted all if not explicitly denied - - permitted = userSession.isPermitted(PermissionType.ENTITY_ATTR, PERM_TARGET_ATTR); - assertTrue(permitted); // READ access permitted - - permitted = userSession.isPermitted(PermissionType.ENTITY_ATTR, PERM_TARGET_ATTR, 2); - assertFalse(permitted); // READ/WRITE access denied - } - - @Test - public void testNullPermissionsOnUser() throws LoginException { - LoginWorker lw = AppBeans.get(LoginWorker.NAME); - - UserSession userSession = lw.login(USER_NAME, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); - assertNotNull(userSession); - - //permission is empty on user - if (userSession.getUser().getUserRoles() != null) { - for (UserRole ur : userSession.getUser().getUserRoles()) { - if (ur.getRole() != null) { - assertNull(ur.getRole().getPermissions()); - } - } - } - - User user = userSession.getUser(); - Transaction tx = cont.persistence().createTransaction(); - try { - cont.persistence().getEntityManager().merge(user); - tx.commit(); - } finally { - tx.end(); - } - - tx = cont.persistence().createTransaction(); - try { - user = cont.persistence().getEntityManager().find(User.class, user.getId()); - if (userSession.getUser().getUserRoles() != null) { - for (UserRole ur : user.getUserRoles()) { - if (ur.getRole() != null) { - Role role = ur.getRole(); - if ("testRole1".equals(role.getName()) || "testRole2".equals(role.getName())) { - assertNotNull(role.getPermissions()); - assertEquals(1, role.getPermissions().size()); - } - } - } - } - tx.commit(); - } finally { - tx.end(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.PasswordEncryption; +import com.haulmont.cuba.security.app.LoginWorker; +import com.haulmont.cuba.security.entity.*; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.Locale; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class PermissionTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private static final String USER_NAME = "testUser"; + private static final String USER_PASSW = "testUser"; + private static final String PERM_TARGET_SCREEN = "w:sys$Server.browse"; + private static final String PERM_TARGET_ATTR = "sys$Server:address"; + + private UUID role1Id, permission1Id, role2Id, permission2Id, userId, groupId, + userRole1Id, userRole2Id; + + private PasswordEncryption passwordEncryption; + + @Before + public void setUp() throws Exception { + passwordEncryption = AppBeans.get(PasswordEncryption.class); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Role role1 = new Role(); + role1Id = role1.getId(); + role1.setName("testRole1"); + em.persist(role1); + + Role role2 = new Role(); + role2Id = role2.getId(); + role2.setName("testRole2"); + em.persist(role2); + + Permission permission1 = new Permission(); + permission1Id = permission1.getId(); + permission1.setRole(role1); + permission1.setType(PermissionType.SCREEN); + permission1.setTarget(PERM_TARGET_SCREEN); + permission1.setValue(0); + em.persist(permission1); + + Permission permission2 = new Permission(); + permission2Id = permission2.getId(); + permission2.setRole(role2); + permission2.setType(PermissionType.ENTITY_ATTR); + permission2.setTarget(PERM_TARGET_ATTR); + permission2.setValue(1); + em.persist(permission2); + + Group group = new Group(); + groupId = group.getId(); + group.setName("testGroup"); + em.persist(group); + + User user = new User(); + userId = user.getId(); + user.setName(USER_NAME); + user.setLogin(USER_NAME); + + String pwd = passwordEncryption.getPasswordHash(userId, USER_PASSW); + user.setPassword(pwd); + + user.setGroup(group); + em.persist(user); + + UserRole userRole1 = new UserRole(); + userRole1Id = userRole1.getId(); + userRole1.setUser(user); + userRole1.setRole(role1); + em.persist(userRole1); + + UserRole userRole2 = new UserRole(); + userRole2Id = userRole2.getId(); + userRole2.setUser(user); + userRole2.setRole(role2); + em.persist(userRole2); + + tx.commit(); + } finally { + tx.end(); + } + } + + @After + public void tearDown() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Query q; + + q = em.createNativeQuery("delete from SEC_USER_ROLE where ID = ? or ID = ?"); + q.setParameter(1, userRole1Id.toString()); + q.setParameter(2, userRole2Id.toString()); + q.executeUpdate(); + + q = em.createNativeQuery("delete from SEC_USER where ID = ?"); + q.setParameter(1, userId.toString()); + q.executeUpdate(); + + q = em.createNativeQuery("delete from SEC_GROUP where ID = ?"); + q.setParameter(1, groupId.toString()); + q.executeUpdate(); + + q = em.createNativeQuery("delete from SEC_PERMISSION where ID = ? or ID = ?"); + q.setParameter(1, permission1Id.toString()); + q.setParameter(2, permission2Id.toString()); + q.executeUpdate(); + + q = em.createNativeQuery("delete from SEC_ROLE where ID = ? or ID = ?"); + q.setParameter(1, role1Id.toString()); + q.setParameter(2, role2Id.toString()); + q.executeUpdate(); + + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void test() throws LoginException { + LoginWorker lw = AppBeans.get(LoginWorker.NAME); + + UserSession userSession = lw.login(USER_NAME, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); + assertNotNull(userSession); + + boolean permitted = userSession.isPermitted(PermissionType.SCREEN, PERM_TARGET_SCREEN); + assertFalse(permitted); + + permitted = userSession.isPermitted(PermissionType.SCREEN, "some action"); + assertTrue(permitted); // permitted all if not explicitly denied + + permitted = userSession.isPermitted(PermissionType.ENTITY_ATTR, PERM_TARGET_ATTR); + assertTrue(permitted); // READ access permitted + + permitted = userSession.isPermitted(PermissionType.ENTITY_ATTR, PERM_TARGET_ATTR, 2); + assertFalse(permitted); // READ/WRITE access denied + } + + @Test + public void testNullPermissionsOnUser() throws LoginException { + LoginWorker lw = AppBeans.get(LoginWorker.NAME); + + UserSession userSession = lw.login(USER_NAME, passwordEncryption.getPlainHash(USER_PASSW), Locale.getDefault()); + assertNotNull(userSession); + + //permission is empty on user + if (userSession.getUser().getUserRoles() != null) { + for (UserRole ur : userSession.getUser().getUserRoles()) { + if (ur.getRole() != null) { + assertNull(ur.getRole().getPermissions()); + } + } + } + + User user = userSession.getUser(); + Transaction tx = cont.persistence().createTransaction(); + try { + cont.persistence().getEntityManager().merge(user); + tx.commit(); + } finally { + tx.end(); + } + + tx = cont.persistence().createTransaction(); + try { + user = cont.persistence().getEntityManager().find(User.class, user.getId()); + if (userSession.getUser().getUserRoles() != null) { + for (UserRole ur : user.getUserRoles()) { + if (ur.getRole() != null) { + Role role = ur.getRole(); + if ("testRole1".equals(role.getName()) || "testRole2".equals(role.getName())) { + assertNotNull(role.getPermissions()); + assertEquals(1, role.getPermissions().size()); + } + } + } + } + tx.commit(); + } finally { + tx.end(); + } + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/security/RelationsTest.java b/modules/core/test/com/haulmont/cuba/security/RelationsTest.java index ca1a883cf1..4f6990aaa6 100644 --- a/modules/core/test/com/haulmont/cuba/security/RelationsTest.java +++ b/modules/core/test/com/haulmont/cuba/security/RelationsTest.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.security.entity.Role; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserRole; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.UUID; - -public class RelationsTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void testRole() { - UUID roleId = createRole(); - - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Role role = em.find(Role.class, roleId); - em.remove(role); - - tx.commit(); - } finally { - tx.end(); - } - } - - public UUID createRole() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - User user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); - - Role role = new Role(); - role.setName("RelationTest"); - em.persist(role); - - UserRole userRole = new UserRole(); - userRole.setUser(user); - userRole.setRole(role); - em.persist(userRole); - - tx.commit(); - - return role.getId(); - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.security.entity.Role; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserRole; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.UUID; + +public class RelationsTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void testRole() { + UUID roleId = createRole(); + + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Role role = em.find(Role.class, roleId); + em.remove(role); + + tx.commit(); + } finally { + tx.end(); + } + } + + public UUID createRole() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + User user = em.find(User.class, UUID.fromString("60885987-1b61-4247-94c7-dff348347f93")); + + Role role = new Role(); + role.setName("RelationTest"); + em.persist(role); + + UserRole userRole = new UserRole(); + userRole.setUser(user); + userRole.setRole(role); + em.persist(userRole); + + tx.commit(); + + return role.getId(); + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/security/UserRoleTest.java b/modules/core/test/com/haulmont/cuba/security/UserRoleTest.java index 7df3661e1f..39d45fb44f 100644 --- a/modules/core/test/com/haulmont/cuba/security/UserRoleTest.java +++ b/modules/core/test/com/haulmont/cuba/security/UserRoleTest.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.Role; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserRole; -import com.haulmont.cuba.testsupport.TestContainer; -import org.junit.ClassRule; -import org.junit.Test; - -import java.util.List; -import java.util.UUID; - -import static org.junit.Assert.assertEquals; - - -public class UserRoleTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - @Test - public void test() { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - - Role role = new Role(); - role.setName("testRole1"); - em.persist(role); - - Group group = new Group(); - group.setName("testGroup1"); - em.persist(group); - - User user = new User(); - UUID userId = user.getId(); - user.setLogin("testUser1"); - user.setName("Test User 1"); - user.setGroup(group); - em.persist(user); - - UserRole userRole = new UserRole(); - userRole.setUser(user); - userRole.setRole(role); - em.persist(userRole); - - tx.commitRetaining(); - - em = cont.persistence().getEntityManager(); - user = em.find(User.class, userId); - List userRoles = user.getUserRoles(); - assertEquals(1, userRoles.size()); - for (UserRole ur : userRoles) { - Role r = ur.getRole(); - assertEquals(role.getName(), r.getName()); - } - } finally { - tx.end(); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.Role; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserRole; +import com.haulmont.cuba.testsupport.TestContainer; +import org.junit.ClassRule; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; + + +public class UserRoleTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + @Test + public void test() { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + + Role role = new Role(); + role.setName("testRole1"); + em.persist(role); + + Group group = new Group(); + group.setName("testGroup1"); + em.persist(group); + + User user = new User(); + UUID userId = user.getId(); + user.setLogin("testUser1"); + user.setName("Test User 1"); + user.setGroup(group); + em.persist(user); + + UserRole userRole = new UserRole(); + userRole.setUser(user); + userRole.setRole(role); + em.persist(userRole); + + tx.commitRetaining(); + + em = cont.persistence().getEntityManager(); + user = em.find(User.class, userId); + List userRoles = user.getUserRoles(); + assertEquals(1, userRoles.size()); + for (UserRole ur : userRoles) { + Role r = ur.getRole(); + assertEquals(role.getName(), r.getName()); + } + } finally { + tx.end(); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/security/UserSettingServiceTest.java b/modules/core/test/com/haulmont/cuba/security/UserSettingServiceTest.java index 84dca99fff..9c63c3d1c0 100644 --- a/modules/core/test/com/haulmont/cuba/security/UserSettingServiceTest.java +++ b/modules/core/test/com/haulmont/cuba/security/UserSettingServiceTest.java @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security; - -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Query; -import com.haulmont.cuba.core.Transaction; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.security.app.UserSettingService; -import com.haulmont.cuba.testsupport.TestContainer; -import com.haulmont.cuba.testsupport.TestUserSessionSource; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class UserSettingServiceTest { - - @ClassRule - public static TestContainer cont = TestContainer.Common.INSTANCE; - - private UserSettingService uss; - - @Before - public void setUp() throws Exception { - uss = AppBeans.get(UserSettingService.NAME); - } - - @After - public void tearDown() throws Exception { - Transaction tx = cont.persistence().createTransaction(); - try { - EntityManager em = cont.persistence().getEntityManager(); - Query q = em.createNativeQuery("delete from SEC_USER_SETTING where USER_ID = ?"); - q.setParameter(1, TestUserSessionSource.USER_ID); - q.executeUpdate(); - tx.commit(); - } finally { - tx.end(); - } - } - - @Test - public void test() { - String val = uss.loadSetting(ClientType.WEB, "test-setting"); - assertNull(val); - - uss.saveSetting(ClientType.WEB, "test-setting", "test-value"); - - val = uss.loadSetting(ClientType.WEB, "test-setting"); - assertEquals("test-value", val); - - val = uss.loadSetting("test-setting"); - assertNull(val); - - uss.saveSetting("test-setting", "test-value-1"); - - val = uss.loadSetting("test-setting"); - assertEquals("test-value-1", val); - - val = uss.loadSetting(ClientType.WEB, "test-setting"); - assertEquals("test-value", val); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security; + +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Query; +import com.haulmont.cuba.core.Transaction; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.security.app.UserSettingService; +import com.haulmont.cuba.testsupport.TestContainer; +import com.haulmont.cuba.testsupport.TestUserSessionSource; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class UserSettingServiceTest { + + @ClassRule + public static TestContainer cont = TestContainer.Common.INSTANCE; + + private UserSettingService uss; + + @Before + public void setUp() throws Exception { + uss = AppBeans.get(UserSettingService.NAME); + } + + @After + public void tearDown() throws Exception { + Transaction tx = cont.persistence().createTransaction(); + try { + EntityManager em = cont.persistence().getEntityManager(); + Query q = em.createNativeQuery("delete from SEC_USER_SETTING where USER_ID = ?"); + q.setParameter(1, TestUserSessionSource.USER_ID); + q.executeUpdate(); + tx.commit(); + } finally { + tx.end(); + } + } + + @Test + public void test() { + String val = uss.loadSetting(ClientType.WEB, "test-setting"); + assertNull(val); + + uss.saveSetting(ClientType.WEB, "test-setting", "test-value"); + + val = uss.loadSetting(ClientType.WEB, "test-setting"); + assertEquals("test-value", val); + + val = uss.loadSetting("test-setting"); + assertNull(val); + + uss.saveSetting("test-setting", "test-value-1"); + + val = uss.loadSetting("test-setting"); + assertEquals("test-value-1", val); + + val = uss.loadSetting(ClientType.WEB, "test-setting"); + assertEquals("test-value", val); + } +} diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestContainer.java b/modules/core/test/com/haulmont/cuba/testsupport/TestContainer.java index 61c779c489..09afadb5f6 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestContainer.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestContainer.java @@ -1,388 +1,388 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.testsupport; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import com.haulmont.bali.db.QueryRunner; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.EntityManager; -import com.haulmont.cuba.core.Persistence; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Stores; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.core.sys.*; -import com.haulmont.cuba.core.sys.persistence.EclipseLinkCustomizer; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrLookup; -import org.apache.commons.lang.text.StrSubstitutor; -import org.apache.commons.lang.text.StrTokenizer; -import org.junit.rules.ExternalResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; - -import javax.naming.NamingException; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.sql.SQLException; -import java.util.*; - -/** - * Container for integration tests. - *

Usage of the common instance (time saving):

- *
- *    {@literal @}ClassRule
- *     public static TestContainer cont = TestContainer.Common.INSTANCE;
- *
- *    {@literal @}Test
- *     public void testSomething() {
- *         try (Transaction tx = cont.persistence().createTransaction()) { ... }
- *     }
- * 
- * - *

Usage of a specific instance:

- *
- *    {@literal @}ClassRule
- *     public static TestContainer cont = new TestContainer()
- *              .setAppPropertiesFiles(Arrays.asList("cuba-app.properties", "com/company/sample/core/my-test-app.properties"));
- *
- *    {@literal @}Test
- *     public void testSomething() {
- *         try (Transaction tx = cont.persistence().createTransaction()) { ... }
- *     }
- * 
- * - */ -public class TestContainer extends ExternalResource { - - public static class Common extends TestContainer { - - public static final Common INSTANCE = new Common(); - - private static volatile boolean initialized; - - private Common() { - } - - @Override - public void before() throws Throwable { - if (!initialized) { - super.before(); - initialized = true; - } - setupContext(); - } - - @Override - public void after() { - cleanupContext(); - // never stops - do not call super - } - } - - private Logger log; - - protected String springConfig; - protected List appComponents; - protected List appPropertiesFiles; - protected String dbDriver; - protected String dbUrl; - protected String dbUser; - protected String dbPassword; - - private ClassPathXmlApplicationContext springAppContext; - private Map appProperties = new HashMap<>(); - - public TestContainer() { - String property = System.getProperty("logback.configurationFile"); - if (StringUtils.isBlank(property)) { - System.setProperty("logback.configurationFile", "test-logback.xml"); - } - log = LoggerFactory.getLogger(TestContainer.class); - - springConfig = "test-spring.xml"; - appComponents = Collections.emptyList(); - appPropertiesFiles = Arrays.asList("cuba-app.properties", "test-app.properties", "cuba-test-app.properties"); - dbDriver = "org.hsqldb.jdbc.JDBCDriver"; - dbUrl = "jdbc:hsqldb:hsql://localhost:9111/cubadb"; - dbUser = "sa"; - dbPassword = ""; - } - - public Persistence persistence() { - return AppBeans.get(Persistence.class); - } - - public EntityManager entityManager() { - return persistence().getEntityManager(); - } - - public Metadata metadata() { - return AppBeans.get(Metadata.class); - } - - public void deleteRecord(String table, Object... ids) { - deleteRecord(table, "ID", ids); - } - - public void deleteRecord(String table, String primaryKeyCol, Object... ids) { - for (Object id : ids) { - String sql = "delete from " + table + " where " + primaryKeyCol + " = '" + id.toString() + "'"; - QueryRunner runner = new QueryRunner(persistence().getDataSource()); - try { - runner.update(sql); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - } - - public void deleteRecord(Entity... entities) { - if (entities == null) - return; - for (Entity entity : entities) { - MetadataTools metadataTools = metadata().getTools(); - MetaClass metaClass = metadata().getClassNN(entity.getClass()); - - String table = metadataTools.getDatabaseTable(metaClass); - String primaryKey = metadataTools.getPrimaryKeyName(metaClass); - if (table == null || primaryKey == null) - throw new RuntimeException("Unable to determine table or primary key name for " + entity); - - deleteRecord(table, primaryKey, entity.getId()); - } - } - - public void setupLogging(String logger, Level level) { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - context.getLogger(logger).setLevel(level); - } - - public List getAppComponents() { - return appComponents; - } - - public List getAppPropertiesFiles() { - return appPropertiesFiles; - } - - public String getSpringConfig() { - return springConfig; - } - - public TestContainer setSpringConfig(String springConfig) { - this.springConfig = springConfig; - return this; - } - - public TestContainer setAppComponents(List appComponents) { - this.appComponents = appComponents; - return this; - } - - public TestContainer setAppPropertiesFiles(List appPropertiesFiles) { - this.appPropertiesFiles = appPropertiesFiles; - return this; - } - - public TestContainer addAppPropertiesFile(String name) { - ArrayList list = new ArrayList<>(appPropertiesFiles); - list.add(name); - this.appPropertiesFiles = list; - return this; - } - - public String getDbDriver() { - return dbDriver; - } - - public TestContainer setDbDriver(String dbDriver) { - this.dbDriver = dbDriver; - return this; - } - - public String getDbUrl() { - return dbUrl; - } - - public TestContainer setDbUrl(String dbUrl) { - this.dbUrl = dbUrl; - return this; - } - - public String getDbUser() { - return dbUser; - } - - public TestContainer setDbUser(String dbUser) { - this.dbUser = dbUser; - return this; - } - - public String getDbPassword() { - return dbPassword; - } - - public TestContainer setDbPassword(String dbPassword) { - this.dbPassword = dbPassword; - return this; - } - - public ClassPathXmlApplicationContext getSpringAppContext() { - return springAppContext; - } - - public Map getAppProperties() { - return appProperties; - } - - @Override - protected void before() throws Throwable { - log.info("Starting test container " + this); - System.setProperty("cuba.unitTestMode", "true"); - - initAppComponents(); - initAppProperties(); - for (Map.Entry entry : appProperties.entrySet()) { - AppContext.setProperty(entry.getKey(), entry.getValue()); - } - - initDataSources(); - initPersistenceConfig(); - initAppContext(); - } - - @Override - protected void after() { - log.info("Stopping test container " + this); - try { - ((PersistenceImpl) AppBeans.get(Persistence.class)).dispose(); - ((ConfigurableApplicationContext) AppContext.getApplicationContext()).close(); - TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); - AppContext.Internals.setApplicationContext(null); - for (String name : AppContext.getPropertyNames()) { - AppContext.setProperty(name, null); - } - } catch (Exception e) { - log.warn("Error closing test container", e); - } - } - - protected void initDataSources() { - try { - Class.forName(dbDriver); - TestDataSource ds = new TestDataSource(dbUrl, dbUser, dbPassword); - TestContext.getInstance().bind(AppContext.getProperty("cuba.dataSourceJndiName"), ds); - } catch (ClassNotFoundException | NamingException e) { - throw new RuntimeException("Error initializing datasource", e); - } - } - - protected void initPersistenceConfig() { - Stores.getAll().forEach(AppContextLoader::createPersistenceXml); - } - - protected void initAppComponents() { - AppContext.Internals.setAppComponents(new AppComponents(getAppComponents(), "core")); - } - - protected void initAppProperties() { - final Properties properties = new Properties(); - - List locations = getAppPropertiesFiles(); - DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); - for (String location : locations) { - Resource resource = resourceLoader.getResource(location); - if (resource.exists()) { - InputStream stream = null; - try { - stream = resource.getInputStream(); - properties.load(stream); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(stream); - } - } else { - log.warn("Resource " + location + " not found, ignore it"); - } - } - - StrSubstitutor substitutor = new StrSubstitutor(new StrLookup() { - @Override - public String lookup(String key) { - String subst = properties.getProperty(key); - return subst != null ? subst : System.getProperty(key); - } - }); - for (Object key : properties.keySet()) { - String value = substitutor.replace(properties.getProperty((String) key)); - appProperties.put((String) key, value); - } - - File dir; - dir = new File(appProperties.get("cuba.confDir")); - dir.mkdirs(); - dir = new File(appProperties.get("cuba.logDir")); - dir.mkdirs(); - dir = new File(appProperties.get("cuba.tempDir")); - dir.mkdirs(); - dir = new File(appProperties.get("cuba.dataDir")); - dir.mkdirs(); - } - - protected void initAppContext() { - EclipseLinkCustomizer.initTransientCompatibleAnnotations(); - - String configProperty = AppContext.getProperty(AbstractAppContextLoader.SPRING_CONTEXT_CONFIG); - - StrTokenizer tokenizer = new StrTokenizer(configProperty); - List locations = tokenizer.getTokenList(); - locations.add(getSpringConfig()); - - springAppContext = new CubaCoreApplicationContext(locations.toArray(new String[locations.size()])); - AppContext.Internals.setApplicationContext(springAppContext); - } - - protected void cleanupContext() { - try { - TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); - } catch (NamingException e) { - throw new RuntimeException(e); - } - AppContext.Internals.setApplicationContext(null); - for (String name : AppContext.getPropertyNames()) { - AppContext.setProperty(name, null); - } - } - - protected void setupContext() { - AppContext.Internals.setApplicationContext(getSpringAppContext()); - for (Map.Entry entry : getAppProperties().entrySet()) { - AppContext.setProperty(entry.getKey(), entry.getValue()); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.testsupport; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import com.haulmont.bali.db.QueryRunner; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.EntityManager; +import com.haulmont.cuba.core.Persistence; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Stores; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.core.sys.*; +import com.haulmont.cuba.core.sys.persistence.EclipseLinkCustomizer; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrLookup; +import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.commons.lang.text.StrTokenizer; +import org.junit.rules.ExternalResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +import javax.naming.NamingException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; +import java.util.*; + +/** + * Container for integration tests. + *

Usage of the common instance (time saving):

+ *
+ *    {@literal @}ClassRule
+ *     public static TestContainer cont = TestContainer.Common.INSTANCE;
+ *
+ *    {@literal @}Test
+ *     public void testSomething() {
+ *         try (Transaction tx = cont.persistence().createTransaction()) { ... }
+ *     }
+ * 
+ * + *

Usage of a specific instance:

+ *
+ *    {@literal @}ClassRule
+ *     public static TestContainer cont = new TestContainer()
+ *              .setAppPropertiesFiles(Arrays.asList("cuba-app.properties", "com/company/sample/core/my-test-app.properties"));
+ *
+ *    {@literal @}Test
+ *     public void testSomething() {
+ *         try (Transaction tx = cont.persistence().createTransaction()) { ... }
+ *     }
+ * 
+ * + */ +public class TestContainer extends ExternalResource { + + public static class Common extends TestContainer { + + public static final Common INSTANCE = new Common(); + + private static volatile boolean initialized; + + private Common() { + } + + @Override + public void before() throws Throwable { + if (!initialized) { + super.before(); + initialized = true; + } + setupContext(); + } + + @Override + public void after() { + cleanupContext(); + // never stops - do not call super + } + } + + private Logger log; + + protected String springConfig; + protected List appComponents; + protected List appPropertiesFiles; + protected String dbDriver; + protected String dbUrl; + protected String dbUser; + protected String dbPassword; + + private ClassPathXmlApplicationContext springAppContext; + private Map appProperties = new HashMap<>(); + + public TestContainer() { + String property = System.getProperty("logback.configurationFile"); + if (StringUtils.isBlank(property)) { + System.setProperty("logback.configurationFile", "test-logback.xml"); + } + log = LoggerFactory.getLogger(TestContainer.class); + + springConfig = "test-spring.xml"; + appComponents = Collections.emptyList(); + appPropertiesFiles = Arrays.asList("cuba-app.properties", "test-app.properties", "cuba-test-app.properties"); + dbDriver = "org.hsqldb.jdbc.JDBCDriver"; + dbUrl = "jdbc:hsqldb:hsql://localhost:9111/cubadb"; + dbUser = "sa"; + dbPassword = ""; + } + + public Persistence persistence() { + return AppBeans.get(Persistence.class); + } + + public EntityManager entityManager() { + return persistence().getEntityManager(); + } + + public Metadata metadata() { + return AppBeans.get(Metadata.class); + } + + public void deleteRecord(String table, Object... ids) { + deleteRecord(table, "ID", ids); + } + + public void deleteRecord(String table, String primaryKeyCol, Object... ids) { + for (Object id : ids) { + String sql = "delete from " + table + " where " + primaryKeyCol + " = '" + id.toString() + "'"; + QueryRunner runner = new QueryRunner(persistence().getDataSource()); + try { + runner.update(sql); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + public void deleteRecord(Entity... entities) { + if (entities == null) + return; + for (Entity entity : entities) { + MetadataTools metadataTools = metadata().getTools(); + MetaClass metaClass = metadata().getClassNN(entity.getClass()); + + String table = metadataTools.getDatabaseTable(metaClass); + String primaryKey = metadataTools.getPrimaryKeyName(metaClass); + if (table == null || primaryKey == null) + throw new RuntimeException("Unable to determine table or primary key name for " + entity); + + deleteRecord(table, primaryKey, entity.getId()); + } + } + + public void setupLogging(String logger, Level level) { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.getLogger(logger).setLevel(level); + } + + public List getAppComponents() { + return appComponents; + } + + public List getAppPropertiesFiles() { + return appPropertiesFiles; + } + + public String getSpringConfig() { + return springConfig; + } + + public TestContainer setSpringConfig(String springConfig) { + this.springConfig = springConfig; + return this; + } + + public TestContainer setAppComponents(List appComponents) { + this.appComponents = appComponents; + return this; + } + + public TestContainer setAppPropertiesFiles(List appPropertiesFiles) { + this.appPropertiesFiles = appPropertiesFiles; + return this; + } + + public TestContainer addAppPropertiesFile(String name) { + ArrayList list = new ArrayList<>(appPropertiesFiles); + list.add(name); + this.appPropertiesFiles = list; + return this; + } + + public String getDbDriver() { + return dbDriver; + } + + public TestContainer setDbDriver(String dbDriver) { + this.dbDriver = dbDriver; + return this; + } + + public String getDbUrl() { + return dbUrl; + } + + public TestContainer setDbUrl(String dbUrl) { + this.dbUrl = dbUrl; + return this; + } + + public String getDbUser() { + return dbUser; + } + + public TestContainer setDbUser(String dbUser) { + this.dbUser = dbUser; + return this; + } + + public String getDbPassword() { + return dbPassword; + } + + public TestContainer setDbPassword(String dbPassword) { + this.dbPassword = dbPassword; + return this; + } + + public ClassPathXmlApplicationContext getSpringAppContext() { + return springAppContext; + } + + public Map getAppProperties() { + return appProperties; + } + + @Override + protected void before() throws Throwable { + log.info("Starting test container " + this); + System.setProperty("cuba.unitTestMode", "true"); + + initAppComponents(); + initAppProperties(); + for (Map.Entry entry : appProperties.entrySet()) { + AppContext.setProperty(entry.getKey(), entry.getValue()); + } + + initDataSources(); + initPersistenceConfig(); + initAppContext(); + } + + @Override + protected void after() { + log.info("Stopping test container " + this); + try { + ((PersistenceImpl) AppBeans.get(Persistence.class)).dispose(); + ((ConfigurableApplicationContext) AppContext.getApplicationContext()).close(); + TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); + AppContext.Internals.setApplicationContext(null); + for (String name : AppContext.getPropertyNames()) { + AppContext.setProperty(name, null); + } + } catch (Exception e) { + log.warn("Error closing test container", e); + } + } + + protected void initDataSources() { + try { + Class.forName(dbDriver); + TestDataSource ds = new TestDataSource(dbUrl, dbUser, dbPassword); + TestContext.getInstance().bind(AppContext.getProperty("cuba.dataSourceJndiName"), ds); + } catch (ClassNotFoundException | NamingException e) { + throw new RuntimeException("Error initializing datasource", e); + } + } + + protected void initPersistenceConfig() { + Stores.getAll().forEach(AppContextLoader::createPersistenceXml); + } + + protected void initAppComponents() { + AppContext.Internals.setAppComponents(new AppComponents(getAppComponents(), "core")); + } + + protected void initAppProperties() { + final Properties properties = new Properties(); + + List locations = getAppPropertiesFiles(); + DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); + for (String location : locations) { + Resource resource = resourceLoader.getResource(location); + if (resource.exists()) { + InputStream stream = null; + try { + stream = resource.getInputStream(); + properties.load(stream); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } else { + log.warn("Resource " + location + " not found, ignore it"); + } + } + + StrSubstitutor substitutor = new StrSubstitutor(new StrLookup() { + @Override + public String lookup(String key) { + String subst = properties.getProperty(key); + return subst != null ? subst : System.getProperty(key); + } + }); + for (Object key : properties.keySet()) { + String value = substitutor.replace(properties.getProperty((String) key)); + appProperties.put((String) key, value); + } + + File dir; + dir = new File(appProperties.get("cuba.confDir")); + dir.mkdirs(); + dir = new File(appProperties.get("cuba.logDir")); + dir.mkdirs(); + dir = new File(appProperties.get("cuba.tempDir")); + dir.mkdirs(); + dir = new File(appProperties.get("cuba.dataDir")); + dir.mkdirs(); + } + + protected void initAppContext() { + EclipseLinkCustomizer.initTransientCompatibleAnnotations(); + + String configProperty = AppContext.getProperty(AbstractAppContextLoader.SPRING_CONTEXT_CONFIG); + + StrTokenizer tokenizer = new StrTokenizer(configProperty); + List locations = tokenizer.getTokenList(); + locations.add(getSpringConfig()); + + springAppContext = new CubaCoreApplicationContext(locations.toArray(new String[locations.size()])); + AppContext.Internals.setApplicationContext(springAppContext); + } + + protected void cleanupContext() { + try { + TestContext.getInstance().unbind(AppContext.getProperty("cuba.dataSourceJndiName")); + } catch (NamingException e) { + throw new RuntimeException(e); + } + AppContext.Internals.setApplicationContext(null); + for (String name : AppContext.getPropertyNames()) { + AppContext.setProperty(name, null); + } + } + + protected void setupContext() { + AppContext.Internals.setApplicationContext(getSpringAppContext()); + for (Map.Entry entry : getAppProperties().entrySet()) { + AppContext.setProperty(entry.getKey(), entry.getValue()); + } + } +} diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestContext.java b/modules/core/test/com/haulmont/cuba/testsupport/TestContext.java index 259e70e494..734f174e56 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestContext.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestContext.java @@ -1,180 +1,180 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.testsupport; - -import javax.naming.*; -import java.util.Hashtable; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class TestContext implements Context { - - private Map store = new ConcurrentHashMap<>(); - - private static Context instance = new TestContext(); - - public static Context getInstance() { - return instance; - } - - private TestContext() { - } - - @Override - public Object lookup(Name name) throws NamingException { - return lookup(name.toString()); - } - - @Override - public Object lookup(String name) throws NamingException { - Object obj = store.get(name); - if (obj != null) - return obj; - else - throw new NamingException("Not bound: " + name); - } - - @Override - public void bind(Name name, Object obj) throws NamingException { - bind(name.toString(), obj); - } - - @Override - public void bind(String name, Object obj) throws NamingException { - store.put(name, obj); - } - - @Override - public void rebind(Name name, Object obj) throws NamingException { - rebind(name.toString(), obj); - } - - @Override - public void rebind(String name, Object obj) throws NamingException { - store.put(name, obj); - } - - @Override - public void unbind(Name name) throws NamingException { - unbind(name.toString()); - } - - @Override - public void unbind(String name) throws NamingException { - store.remove(name); - } - - @Override - public void rename(Name oldName, Name newName) throws NamingException { - } - - @Override - public void rename(String oldName, String newName) throws NamingException { - } - - @Override - public NamingEnumeration list(Name name) throws NamingException { - return null; - } - - @Override - public NamingEnumeration list(String name) throws NamingException { - return null; - } - - @Override - public NamingEnumeration listBindings(Name name) throws NamingException { - return null; - } - - @Override - public NamingEnumeration listBindings(String name) throws NamingException { - return null; - } - - @Override - public void destroySubcontext(Name name) throws NamingException { - } - - @Override - public void destroySubcontext(String name) throws NamingException { - } - - @Override - public Context createSubcontext(Name name) throws NamingException { - return null; - } - - @Override - public Context createSubcontext(String name) throws NamingException { - return null; - } - - @Override - public Object lookupLink(Name name) throws NamingException { - return null; - } - - @Override - public Object lookupLink(String name) throws NamingException { - return null; - } - - @Override - public NameParser getNameParser(Name name) throws NamingException { - return null; - } - - @Override - public NameParser getNameParser(String name) throws NamingException { - return null; - } - - @Override - public Name composeName(Name name, Name prefix) throws NamingException { - return null; - } - - @Override - public String composeName(String name, String prefix) throws NamingException { - return null; - } - - @Override - public Object addToEnvironment(String propName, Object propVal) throws NamingException { - return null; - } - - @Override - public Object removeFromEnvironment(String propName) throws NamingException { - return null; - } - - @Override - public Hashtable getEnvironment() throws NamingException { - return null; - } - - @Override - public void close() throws NamingException { - } - - @Override - public String getNameInNamespace() throws NamingException { - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.testsupport; + +import javax.naming.*; +import java.util.Hashtable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class TestContext implements Context { + + private Map store = new ConcurrentHashMap<>(); + + private static Context instance = new TestContext(); + + public static Context getInstance() { + return instance; + } + + private TestContext() { + } + + @Override + public Object lookup(Name name) throws NamingException { + return lookup(name.toString()); + } + + @Override + public Object lookup(String name) throws NamingException { + Object obj = store.get(name); + if (obj != null) + return obj; + else + throw new NamingException("Not bound: " + name); + } + + @Override + public void bind(Name name, Object obj) throws NamingException { + bind(name.toString(), obj); + } + + @Override + public void bind(String name, Object obj) throws NamingException { + store.put(name, obj); + } + + @Override + public void rebind(Name name, Object obj) throws NamingException { + rebind(name.toString(), obj); + } + + @Override + public void rebind(String name, Object obj) throws NamingException { + store.put(name, obj); + } + + @Override + public void unbind(Name name) throws NamingException { + unbind(name.toString()); + } + + @Override + public void unbind(String name) throws NamingException { + store.remove(name); + } + + @Override + public void rename(Name oldName, Name newName) throws NamingException { + } + + @Override + public void rename(String oldName, String newName) throws NamingException { + } + + @Override + public NamingEnumeration list(Name name) throws NamingException { + return null; + } + + @Override + public NamingEnumeration list(String name) throws NamingException { + return null; + } + + @Override + public NamingEnumeration listBindings(Name name) throws NamingException { + return null; + } + + @Override + public NamingEnumeration listBindings(String name) throws NamingException { + return null; + } + + @Override + public void destroySubcontext(Name name) throws NamingException { + } + + @Override + public void destroySubcontext(String name) throws NamingException { + } + + @Override + public Context createSubcontext(Name name) throws NamingException { + return null; + } + + @Override + public Context createSubcontext(String name) throws NamingException { + return null; + } + + @Override + public Object lookupLink(Name name) throws NamingException { + return null; + } + + @Override + public Object lookupLink(String name) throws NamingException { + return null; + } + + @Override + public NameParser getNameParser(Name name) throws NamingException { + return null; + } + + @Override + public NameParser getNameParser(String name) throws NamingException { + return null; + } + + @Override + public Name composeName(Name name, Name prefix) throws NamingException { + return null; + } + + @Override + public String composeName(String name, String prefix) throws NamingException { + return null; + } + + @Override + public Object addToEnvironment(String propName, Object propVal) throws NamingException { + return null; + } + + @Override + public Object removeFromEnvironment(String propName) throws NamingException { + return null; + } + + @Override + public Hashtable getEnvironment() throws NamingException { + return null; + } + + @Override + public void close() throws NamingException { + } + + @Override + public String getNameInNamespace() throws NamingException { + return null; + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestDataSource.java b/modules/core/test/com/haulmont/cuba/testsupport/TestDataSource.java index 7d88bb083f..36fba51031 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestDataSource.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestDataSource.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.testsupport; - -import org.apache.commons.dbcp2.BasicDataSource; - -import javax.sql.DataSource; -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.logging.Logger; - -public class TestDataSource implements DataSource { - - private BasicDataSource dataSource; - - public TestDataSource(String connUrl, String user, String password) { - dataSource = new BasicDataSource(); - dataSource.setUrl(connUrl); - dataSource.setUsername(user); - dataSource.setPassword(password); - dataSource.setMaxTotal(20); - } - - public BasicDataSource getBasicDataSource() { - return dataSource; - } - - @Override - public Connection getConnection() throws SQLException { - return dataSource.getConnection(); - } - - @Override - public Connection getConnection(String username, String password) throws SQLException { - return dataSource.getConnection(username, password); - } - - @Override - public PrintWriter getLogWriter() throws SQLException { - return null; - } - - @Override - public void setLogWriter(PrintWriter out) throws SQLException { - } - - @Override - public void setLoginTimeout(int seconds) throws SQLException { - } - - @Override - public int getLoginTimeout() throws SQLException { - return 0; - } - - @Override - public Logger getParentLogger() throws SQLFeatureNotSupportedException { - return null; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return null; - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return false; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.testsupport; + +import org.apache.commons.dbcp2.BasicDataSource; + +import javax.sql.DataSource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.logging.Logger; + +public class TestDataSource implements DataSource { + + private BasicDataSource dataSource; + + public TestDataSource(String connUrl, String user, String password) { + dataSource = new BasicDataSource(); + dataSource.setUrl(connUrl); + dataSource.setUsername(user); + dataSource.setPassword(password); + dataSource.setMaxTotal(20); + } + + public BasicDataSource getBasicDataSource() { + return dataSource; + } + + @Override + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return dataSource.getConnection(username, password); + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return null; + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + } + + @Override + public int getLoginTimeout() throws SQLException { + return 0; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return null; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestInitialContextFactory.java b/modules/core/test/com/haulmont/cuba/testsupport/TestInitialContextFactory.java index 0bd60a352d..12599670ce 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestInitialContextFactory.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestInitialContextFactory.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.testsupport; - -import javax.naming.spi.InitialContextFactory; -import javax.naming.Context; -import javax.naming.NamingException; -import java.util.Hashtable; - -public class TestInitialContextFactory implements InitialContextFactory { - - @Override - public Context getInitialContext(Hashtable environment) throws NamingException { - return TestContext.getInstance(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.testsupport; + +import javax.naming.spi.InitialContextFactory; +import javax.naming.Context; +import javax.naming.NamingException; +import java.util.Hashtable; + +public class TestInitialContextFactory implements InitialContextFactory { + + @Override + public Context getInitialContext(Hashtable environment) throws NamingException { + return TestContext.getInstance(); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestMBeanExporter.java b/modules/core/test/com/haulmont/cuba/testsupport/TestMBeanExporter.java index f2c6e5ca65..af11989c40 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestMBeanExporter.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestMBeanExporter.java @@ -1,20 +1,20 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.testsupport; - -public class TestMBeanExporter { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.testsupport; + +public class TestMBeanExporter { } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestMailSender.java b/modules/core/test/com/haulmont/cuba/testsupport/TestMailSender.java index 7c96871b95..6e0fff92aa 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestMailSender.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestMailSender.java @@ -1,71 +1,71 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.testsupport; - -import com.haulmont.cuba.core.sys.CubaMailSender; -import junit.framework.Assert; -import org.springframework.mail.MailException; -import org.springframework.mail.MailSendException; - -import javax.mail.internet.MimeMessage; -import java.util.ArrayList; -import java.util.List; - -/** - * Used by functional tests. - * Fakes real JavaMailSender. - * - */ -public class TestMailSender extends CubaMailSender { - private List myMessages = new ArrayList<>(); - - private boolean mustFail; - - public void clearBuffer() { - myMessages.clear(); - } - - public int getBufferSize() { - return myMessages.size(); - } - - public MimeMessage fetchSentEmail() { - Assert.assertFalse(myMessages.isEmpty()); - return myMessages.remove(0); - } - - @Override - public void send(MimeMessage mimeMessage) throws MailException { - if (mustFail) { - throw new MailSendException("Smtp server not available"); - } - myMessages.add(mimeMessage); - } - - public boolean isEmpty() { - return myMessages.isEmpty(); - } - - public void failPlease() { - this.mustFail = true; - } - - public void workNormallyPlease() { - this.mustFail = false; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.testsupport; + +import com.haulmont.cuba.core.sys.CubaMailSender; +import junit.framework.Assert; +import org.springframework.mail.MailException; +import org.springframework.mail.MailSendException; + +import javax.mail.internet.MimeMessage; +import java.util.ArrayList; +import java.util.List; + +/** + * Used by functional tests. + * Fakes real JavaMailSender. + * + */ +public class TestMailSender extends CubaMailSender { + private List myMessages = new ArrayList<>(); + + private boolean mustFail; + + public void clearBuffer() { + myMessages.clear(); + } + + public int getBufferSize() { + return myMessages.size(); + } + + public MimeMessage fetchSentEmail() { + Assert.assertFalse(myMessages.isEmpty()); + return myMessages.remove(0); + } + + @Override + public void send(MimeMessage mimeMessage) throws MailException { + if (mustFail) { + throw new MailSendException("Smtp server not available"); + } + myMessages.add(mimeMessage); + } + + public boolean isEmpty() { + return myMessages.isEmpty(); + } + + public void failPlease() { + this.mustFail = true; + } + + public void workNormallyPlease() { + this.mustFail = false; + } +} diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestNamePrinter.java b/modules/core/test/com/haulmont/cuba/testsupport/TestNamePrinter.java index 4126fda74e..0ec1a14795 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestNamePrinter.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestNamePrinter.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.testsupport; - -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -public class TestNamePrinter extends TestWatcher { - - @Override - protected void starting(Description description) { - System.out.println(">>>\n>>> Starting " + description.getMethodName() + "\n>>>"); - } - - @Override - protected void finished(Description description) { - System.out.println(">>>>\n>>> Finished " + description.getMethodName() + "\n>>>"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.testsupport; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +public class TestNamePrinter extends TestWatcher { + + @Override + protected void starting(Description description) { + System.out.println(">>>\n>>> Starting " + description.getMethodName() + "\n>>>"); + } + + @Override + protected void finished(Description description) { + System.out.println(">>>>\n>>> Finished " + description.getMethodName() + "\n>>>"); + } } \ No newline at end of file diff --git a/modules/core/test/com/haulmont/cuba/testsupport/TestTransaction.java b/modules/core/test/com/haulmont/cuba/testsupport/TestTransaction.java index 1102ed9a6f..4fe5888723 100644 --- a/modules/core/test/com/haulmont/cuba/testsupport/TestTransaction.java +++ b/modules/core/test/com/haulmont/cuba/testsupport/TestTransaction.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.testsupport; - -import javax.transaction.*; -import javax.transaction.xa.XAResource; -import java.util.List; -import java.util.ArrayList; -import java.sql.SQLException; -import java.sql.Connection; - -public class TestTransaction implements Transaction { - - private int status = Status.STATUS_ACTIVE; - - private List syncs = new ArrayList<>(); - - @Override - public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException { - if (status != Status.STATUS_ACTIVE) - throw new SystemException("Unable to commit: invalid tx status: " + status); - - Connection conn = null; - for (Synchronization sync : syncs) { - sync.beforeCompletion(); - } - if (conn != null) { - try { - conn.commit(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - status = Status.STATUS_COMMITTED; - for (Synchronization sync : syncs) { - sync.afterCompletion(Status.STATUS_COMMITTED); - } - } - - @Override - public void rollback() throws IllegalStateException, SystemException { - if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) - throw new SystemException("Unable to rollback: invalid tx status: " + status); - - status = Status.STATUS_ROLLEDBACK; - for (Synchronization sync : syncs) { - sync.afterCompletion(Status.STATUS_ROLLEDBACK); - } - } - - @Override - public void setRollbackOnly() throws IllegalStateException, SystemException { - status = Status.STATUS_MARKED_ROLLBACK; - } - - @Override - public int getStatus() throws SystemException { - return status; - } - - @Override - public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException { - return false; - } - - @Override - public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException { - return false; - } - - @Override - public void registerSynchronization(Synchronization synchronization) throws RollbackException, IllegalStateException, SystemException { - syncs.add(synchronization); - } - - @Override - public String toString() { - return super.toString() + ", status=" + status; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.testsupport; + +import javax.transaction.*; +import javax.transaction.xa.XAResource; +import java.util.List; +import java.util.ArrayList; +import java.sql.SQLException; +import java.sql.Connection; + +public class TestTransaction implements Transaction { + + private int status = Status.STATUS_ACTIVE; + + private List syncs = new ArrayList<>(); + + @Override + public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException { + if (status != Status.STATUS_ACTIVE) + throw new SystemException("Unable to commit: invalid tx status: " + status); + + Connection conn = null; + for (Synchronization sync : syncs) { + sync.beforeCompletion(); + } + if (conn != null) { + try { + conn.commit(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + status = Status.STATUS_COMMITTED; + for (Synchronization sync : syncs) { + sync.afterCompletion(Status.STATUS_COMMITTED); + } + } + + @Override + public void rollback() throws IllegalStateException, SystemException { + if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) + throw new SystemException("Unable to rollback: invalid tx status: " + status); + + status = Status.STATUS_ROLLEDBACK; + for (Synchronization sync : syncs) { + sync.afterCompletion(Status.STATUS_ROLLEDBACK); + } + } + + @Override + public void setRollbackOnly() throws IllegalStateException, SystemException { + status = Status.STATUS_MARKED_ROLLBACK; + } + + @Override + public int getStatus() throws SystemException { + return status; + } + + @Override + public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException { + return false; + } + + @Override + public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException { + return false; + } + + @Override + public void registerSynchronization(Synchronization synchronization) throws RollbackException, IllegalStateException, SystemException { + syncs.add(synchronization); + } + + @Override + public String toString() { + return super.toString() + ", status=" + status; + } } \ No newline at end of file diff --git a/modules/core/test/jndi.properties b/modules/core/test/jndi.properties index 7b9b033646..a621fd6c38 100644 --- a/modules/core/test/jndi.properties +++ b/modules/core/test/jndi.properties @@ -1,18 +1,18 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -java.naming.factory.initial=com.haulmont.cuba.testsupport.TestInitialContextFactory +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +java.naming.factory.initial=com.haulmont.cuba.testsupport.TestInitialContextFactory diff --git a/modules/core/test/test-app.properties b/modules/core/test/test-app.properties index 94b92ab079..243fafc7d4 100644 --- a/modules/core/test/test-app.properties +++ b/modules/core/test/test-app.properties @@ -1,29 +1,29 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -cuba.webHostName=localhost -cuba.webPort=8080 -cuba.webContextName=cuba - -cuba.confDir=${user.dir}/test-home/cuba/conf -cuba.logDir=${user.dir}/test-home/cuba/logs -cuba.tempDir=${user.dir}/test-home/cuba/temp -cuba.dataDir=${user.dir}/test-home/cuba/work - -cuba.trustedClientPermittedIpList=127.0.0.1, 10.17.*.* - +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +cuba.webHostName=localhost +cuba.webPort=8080 +cuba.webContextName=cuba + +cuba.confDir=${user.dir}/test-home/cuba/conf +cuba.logDir=${user.dir}/test-home/cuba/logs +cuba.tempDir=${user.dir}/test-home/cuba/temp +cuba.dataDir=${user.dir}/test-home/cuba/work + +cuba.trustedClientPermittedIpList=127.0.0.1, 10.17.*.* + cuba.availableLocales=English (GB)|en;English (US)|en_US;Russian|ru;French|fr;French (CA)|fr_CA \ No newline at end of file diff --git a/modules/core/test/test-spring.xml b/modules/core/test/test-spring.xml index 92a313a0d3..fcc2e98e75 100644 --- a/modules/core/test/test-spring.xml +++ b/modules/core/test/test-spring.xml @@ -1,30 +1,30 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/modules/core/web/META-INF/context.xml b/modules/core/web/META-INF/context.xml index c98eaf2e12..c1a17eaa41 100644 --- a/modules/core/web/META-INF/context.xml +++ b/modules/core/web/META-INF/context.xml @@ -1,34 +1,34 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/modules/core/web/WEB-INF/web.xml b/modules/core/web/WEB-INF/web.xml index 8e8e6f2589..8650028bfd 100644 --- a/modules/core/web/WEB-INF/web.xml +++ b/modules/core/web/WEB-INF/web.xml @@ -1,48 +1,48 @@ - - - - - - - - appPropertiesConfig - - classpath:cuba-app.properties - "file:${catalina.base}/conf/cuba-core/local.app.properties" - - - - - com.haulmont.cuba.core.sys.AppContextLoader - - - - remoting - com.haulmont.cuba.core.sys.remoting.RemotingServlet - 1 - - - - remoting - /remoting/* - + + + + + + + + appPropertiesConfig + + classpath:cuba-app.properties + "file:${catalina.base}/conf/cuba-core/local.app.properties" + + + + + com.haulmont.cuba.core.sys.AppContextLoader + + + + remoting + com.haulmont.cuba.core.sys.remoting.RemotingServlet + 1 + + + + remoting + /remoting/* + \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/App.java b/modules/desktop/src/com/haulmont/cuba/desktop/App.java index 5842f3518a..5055bc5618 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/App.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/App.java @@ -1,713 +1,713 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.cuba.client.sys.MessagesClientImpl; -import com.haulmont.cuba.client.sys.cache.ClientCacheManager; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; -import com.haulmont.cuba.desktop.exception.ExceptionHandlers; -import com.haulmont.cuba.desktop.gui.SessionMessagesNotifier; -import com.haulmont.cuba.desktop.sys.*; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareWindowClosingListener; -import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; -import com.haulmont.cuba.desktop.theme.DesktopTheme; -import com.haulmont.cuba.desktop.theme.DesktopThemeLoader; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.TestIdManager; -import com.haulmont.cuba.gui.WindowManager.OpenType; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.gui.config.WindowInfo; -import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import com.haulmont.cuba.gui.theme.ThemeConstants; -import com.haulmont.cuba.gui.theme.ThemeConstantsRepository; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrSubstitutor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.remoting.RemoteAccessException; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.plaf.InputMapUIResource; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.WindowEvent; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Locale; -import java.util.concurrent.ConcurrentHashMap; - -public class App implements ConnectionListener { - - protected static App app; - - private Logger log; - private Logger userActionsLog; - - protected TopLevelFrame mainFrame; - - protected JMenuBar menuBar; - - protected Connection connection; - - protected JTabbedPane tabsPane; - - protected DesktopTheme theme; - - protected ThemeConstants themeConstants; - - protected LinkedList topLevelFrames = new LinkedList<>(); - - protected Messages messages; - - protected Configuration configuration; - - protected UiEventsMulticaster uiEventsMulticaster; - - protected boolean exiting; - - protected boolean testMode; - protected TestIdManager testIdManager = new TestIdManager(); - - protected ApplicationSession applicationSession; - - static { - initEnvironment(); - } - - public static void main(final String[] args) { - SwingUtilities.invokeLater(() -> { - app = new App(); - app.init(args); - app.show(); - app.showLoginDialog(); - }); - } - - public static void initEnvironment() { - // Due to #PL-2421 - System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); - } - - public static App getInstance() { - return app; - } - - public void init(String[] args) { - try { - System.setSecurityManager(null); - initHomeDir(); - initLogging(); - } catch (Throwable t) { - //noinspection CallToPrintStackTrace - t.printStackTrace(); - System.exit(-1); - } - - try { - log.debug("Program arguments: " + Arrays.toString(args)); - - initConnection(); - - DesktopAppContextLoader contextLoader = new DesktopAppContextLoader(getDefaultAppComponents(), getDefaultAppPropertiesConfig(), args); - contextLoader.load(); - - messages = AppBeans.get(Messages.NAME); - configuration = AppBeans.get(Configuration.NAME); - uiEventsMulticaster = AppBeans.get(UiEventsMulticaster.class); - - initTheme(); - initLookAndFeelDefaults(); - initTestMode(); - initUI(); - initExceptionHandling(); - } catch (Throwable t) { - log.error("Error initializing application", t); - System.exit(-1); - } - } - - public void show() { - if (!mainFrame.isVisible()) { - mainFrame.setVisible(true); - } - } - - public Connection getConnection() { - return connection; - } - - public JTabbedPane getTabsPane() { - return tabsPane; - } - - public void showLoginDialog() { - if (exiting) - return; - - LoginDialog loginDialog = createLoginDialog(); - setLoginDialogLocation(loginDialog); - loginDialog.open(); - } - - protected void setLoginDialogLocation(LoginDialog loginDialog) { - Point ownerLocation = mainFrame.getLocationOnScreen(); - int mainX = ownerLocation.x; - int mainY = ownerLocation.y; - - Dimension ownerSize = mainFrame.getSize(); - int mainWidth = ownerSize.width; - int mainHeight = ownerSize.height; - - Dimension size = loginDialog.getSize(); - int width = size.width; - int height = size.height; - - loginDialog.setLocation(mainX + mainWidth / 2 - width / 2, mainY + mainHeight / 2 - height / 2); - } - - protected LoginDialog createLoginDialog() { - return new LoginDialog(mainFrame, connection); - } - - protected String getApplicationTitle() { - return messages.getMainMessage("application.caption"); - } - - protected String getDefaultAppComponents() { - return ""; - } - - protected String getDefaultAppPropertiesConfig() { - return "/cuba-desktop-app.properties"; - } - - protected String getDefaultHomeDir() { - return System.getProperty("user.home") + "/.haulmont/cuba"; - } - - protected String getDefaultLogConfig() { - return "cuba-logback.xml"; - } - - protected void initHomeDir() { - String homeDir = System.getProperty(DesktopAppContextLoader.HOME_DIR_SYS_PROP); - if (StringUtils.isBlank(homeDir)) { - homeDir = getDefaultHomeDir(); - } - homeDir = StrSubstitutor.replaceSystemProperties(homeDir); - System.setProperty(DesktopAppContextLoader.HOME_DIR_SYS_PROP, homeDir); - - File file = new File(homeDir); - if (!file.exists()) { - boolean success = file.mkdirs(); - if (!success) { - System.out.println("Unable to create home dir: " + homeDir); - System.exit(-1); - } - } - if (!file.isDirectory()) { - System.out.println("Invalid home dir: " + homeDir); - System.exit(-1); - } - } - - protected void initLogging() { - String property = System.getProperty("logback.configurationFile"); - if (StringUtils.isBlank(property)) { - System.setProperty("logback.configurationFile", getDefaultLogConfig()); - } - log = LoggerFactory.getLogger(App.class); - userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - } - - protected void initTestMode() { - this.testMode = configuration.getConfig(GlobalConfig.class).getTestMode(); - } - - protected void initTheme() throws Exception { - DesktopConfig config = configuration.getConfig(DesktopConfig.class); - String themeName = config.getTheme(); - DesktopThemeLoader desktopThemeLoader = AppBeans.get(DesktopThemeLoader.NAME); - theme = desktopThemeLoader.loadTheme(themeName); - theme.init(); - - ThemeConstantsRepository themeRepository = AppBeans.get(ThemeConstantsRepository.NAME); - ThemeConstants uiTheme = themeRepository.getConstants(themeName); - - if (uiTheme == null) { - throw new IllegalStateException("Unable to use theme constants '" + themeName + "'"); - } - - this.themeConstants = uiTheme; - } - - public DesktopTheme getTheme() { - return theme; - } - - public ThemeConstants getThemeConstants() { - return themeConstants; - } - - protected void initLookAndFeelDefaults() { - InputMapUIResource inputMap = - (InputMapUIResource) UIManager.getLookAndFeelDefaults().get("FormattedTextField.focusInputMap"); - inputMap.remove(KeyStroke.getKeyStroke("ESCAPE")); - } - - protected void initUI() { - ToolTipManager.sharedInstance().setEnabled(false); - mainFrame = createMainFrame(); - mainFrame.setName("MainFrame"); - mainFrame.addWindowListener(new ValidationAwareWindowClosingListener() { - @Override - public void windowClosingAfterValidation(WindowEvent e) { - exit(); - } - }); - - mainFrame.setContentPane(createStartContentPane()); - registerFrame(mainFrame); - createMainWindowProperties().load(); - } - - protected TopLevelFrame createMainFrame() { - return new TopLevelFrame(getApplicationTitle()); - } - - protected MainWindowProperties createMainWindowProperties() { - return new MainWindowProperties(mainFrame); - } - - protected void initConnection() { - connection = createConnection(); - connection.addListener(this); - } - - protected Connection createConnection() { - return new Connection(); - } - - protected void exit() { - try { - userActionsLog.trace("Closing application..."); - if (connection.isConnected()) { - recursiveClosingFrames(topLevelFrames.iterator(), () -> { - exiting = true; - connection.logout(); - forceExit(); - }); - } else { - forceExit(); - } - } catch (Throwable e) { - log.warn("Error closing application", e); - String title = messages.getMainMessage("errorPane.title"); - String text = messages.getMainMessage("unexpectedCloseException.message") + "\n"; - if (e instanceof RemoteAccessException) { - text = text + messages.getMainMessage("connectException.message"); - } else { - text = text + e.getClass().getSimpleName() + ": " + e.getMessage(); - } - JOptionPane.showMessageDialog(mainFrame, text, title, JOptionPane.WARNING_MESSAGE); - forceExit(); - } - } - - protected void forceExit() { - //noinspection finally - try { - createMainWindowProperties().save(); - AppContext.Internals.stopContext(); - userActionsLog.trace("Application was closed"); - } finally { - System.exit(0); - } - } - - protected Container createStartContentPane() { - JPanel pane = new JPanel(new BorderLayout()); - menuBar = new JMenuBar(); - pane.add(menuBar, BorderLayout.NORTH); - - Locale loc = Locale.getDefault(); - - JMenu menu = new JMenu(messages.getMainMessage("mainMenu.file", loc)); - menuBar.add(menu); - - JMenuItem item; - - item = new JMenuItem(messages.getMainMessage("mainMenu.connect", loc)); - item.addActionListener(e -> showLoginDialog()); - menu.add(item); - - item = new JMenuItem(messages.getMainMessage("mainMenu.exit", loc)); - item.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - exit(); - } - }); - menu.add(item); - - if (isTestMode()) { - menuBar.setName("startMenu"); - } - - return pane; - } - - protected Container createContentPane() { - JPanel pane = new JPanel(new BorderLayout()); - pane.add(createTopPane(), BorderLayout.NORTH); - pane.add(createCenterPane(), BorderLayout.CENTER); - pane.add(createBottomPane(), BorderLayout.SOUTH); - - if (isTestMode()) { - pane.setName("contentPane"); - } - - return pane; - } - - protected JComponent createTopPane() { - JPanel toolBar = new JPanel(new BorderLayout()); - toolBar.add(createMenuBar(), BorderLayout.CENTER); - - if (isTestMode()) { - toolBar.setName("toolBar"); - } - - return toolBar; - } - - protected JComponent createMenuBar() { - menuBar = new JMenuBar(); - - JMenu menu = new JMenu(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.file")); - menuBar.add(menu); - - JMenuItem item; - - item = new JMenuItem(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.disconnect")); - item.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - logout(); - } - }); - menu.add(item); - - item = new JMenuItem(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.exit")); - item.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - exit(); - } - }); - menu.add(item); - - MenuBuilder builder = new MenuBuilder(connection.getSession(), menuBar); - builder.build(); - - if (isTestMode()) { - menuBar.setName("menuBar"); - } - - return menuBar; - } - - protected void logout() { - final Iterator it = topLevelFrames.iterator(); - recursiveClosingFrames(it, () -> - connection.logout() - ); - } - - protected void recursiveClosingFrames(final Iterator it, final Runnable onSuccess) { - final TopLevelFrame frame = it.next(); - frame.getWindowManager() - .checkModificationsAndCloseAll(() -> { - if (!it.hasNext()) { - onSuccess.run(); - } else { - frame.getWindowManager().dispose(); - frame.dispose(); - it.remove(); - recursiveClosingFrames(it, onSuccess); - } - }, null); - } - - protected JComponent createBottomPane() { - JPanel panel = new JPanel(new BorderLayout()); - panel.setBorder(BorderFactory.createLineBorder(Color.gray)); - panel.setPreferredSize(new Dimension(0, 20)); - - ServerSelector serverSelector = AppBeans.get(ServerSelector.NAME); - String url = serverSelector.getUrl(serverSelector.initContext()); - if (url == null) - url = "?"; - - final JLabel connectionStateLab = new JLabel( - messages.formatMainMessage("statusBar.connected", getUserFriendlyConnectionUrl(url))); - - panel.add(connectionStateLab, BorderLayout.WEST); - - - JPanel rightPanel = new JPanel(); - BoxLayout rightLayout = new BoxLayout(rightPanel, BoxLayout.LINE_AXIS); - rightPanel.setLayout(rightLayout); - - UserSession session = connection.getSession(); - - JLabel userInfoLabel = new JLabel(); - String userInfo = messages.formatMainMessage("statusBar.user", - session.getUser().getName(), session.getUser().getLogin()); - userInfoLabel.setText(userInfo); - - rightPanel.add(userInfoLabel); - - JLabel timeZoneLabel = null; - if (session.getTimeZone() != null) { - timeZoneLabel = new JLabel(); - String timeZone = messages.formatMainMessage("statusBar.timeZone", - AppBeans.get(TimeZones.class).getDisplayNameShort(session.getTimeZone())); - timeZoneLabel.setText(timeZone); - - rightPanel.add(Box.createRigidArea(new Dimension(5, 0))); - rightPanel.add(timeZoneLabel); - } - - panel.add(rightPanel, BorderLayout.EAST); - - if (isTestMode()) { - panel.setName("bottomPane"); - userInfoLabel.setName("userInfoLabel"); - if (timeZoneLabel != null) - timeZoneLabel.setName("timeZoneLabel"); - connectionStateLab.setName("connectionStateLab"); - } - - return panel; - } - - protected String getUserFriendlyConnectionUrl(String urlString) { - try { - URL url = new URL(urlString); - return url.getHost() + (url.getPort() == -1 ? "" : ":" + url.getPort()); - } catch (MalformedURLException e) { - return urlString; - } - } - - protected JComponent createCenterPane() { - JPanel pane = new JPanel(new BorderLayout()); - pane.add(createTabsPane(), BorderLayout.CENTER); - if (isTestMode()) { - pane.setName("centerPane"); - } - return pane; - } - - protected JComponent createTabsPane() { - tabsPane = new JTabbedPaneExt(); - if (isTestMode()) { - tabsPane.setName("tabsPane"); - } - return tabsPane; - } - - protected void initExceptionHandling() { - Thread.setDefaultUncaughtExceptionHandler(this::handleException); - - System.setProperty("sun.awt.exception.handler", "com.haulmont.cuba.desktop.exception.AWTExceptionHandler"); - } - - public void handleException(Thread thread, Throwable throwable) { - if (!(throwable instanceof SilentException)) { - Logging annotation = throwable.getClass().getAnnotation(Logging.class); - Logging.Type loggingType = annotation == null ? Logging.Type.FULL : annotation.value(); - if (loggingType != Logging.Type.NONE) { - if (loggingType == Logging.Type.BRIEF) - log.error("Uncaught exception in thread " + thread + ": " + throwable.toString()); - else - log.error("Uncaught exception in thread " + thread, throwable); - } - } - - ExceptionHandlers handlers = AppBeans.get("cuba_ExceptionHandlers", ExceptionHandlers.class); - handlers.handle(thread, throwable, app.getMainFrame().getWindowManager()); - } - - /** - * Initializes exception handlers immediately after login and logout. - * Can be overridden in descendants to manipulate exception handlers programmatically. - * - * @param isConnected true after login, false after logout - */ - protected void initExceptionHandlers(boolean isConnected) { - ExceptionHandlers handlers = AppBeans.get("cuba_ExceptionHandlers", ExceptionHandlers.class); - if (isConnected) { - handlers.createByConfiguration(); - } else { - handlers.createMinimalSet(); - } - } - - @Override - public void connectionStateChanged(Connection connection) throws LoginException { - MessagesClientImpl messagesClient = AppBeans.get(Messages.NAME); - SessionMessagesNotifier messagesNotifier = AppBeans.get(SessionMessagesNotifier.NAME); - - ClientCacheManager clientCacheManager = AppBeans.get(ClientCacheManager.NAME); - clientCacheManager.initialize(); - - if (connection.isConnected()) { - applicationSession = new ApplicationSession(new ConcurrentHashMap<>()); - - messagesClient.setRemoteSearch(true); - initExceptionHandlers(true); - - DesktopWindowManager windowManager = mainFrame.getWindowManager(); - mainFrame.setContentPane(createContentPane()); - mainFrame.repaint(); - windowManager.setTabsPane(tabsPane); - - initClientTime(); - - messagesNotifier.activate(); - - SwingUtilities.invokeLater(this::afterLoggedIn); - } else { - messagesNotifier.deactivate(); - - messagesClient.setRemoteSearch(false); - Iterator it = topLevelFrames.iterator(); - while (it.hasNext()) { - TopLevelFrame frame = it.next(); - if (frame != mainFrame) { - DesktopWindowManager windowManager = frame.getWindowManager(); - if (windowManager != null) - windowManager.dispose(); - frame.dispose(); - it.remove(); - } - } - - DesktopWindowManager windowManager = mainFrame.getWindowManager(); - if (windowManager != null) - windowManager.dispose(); - - applicationSession = null; - - mainFrame.setContentPane(createStartContentPane()); - mainFrame.repaint(); - - initExceptionHandlers(false); - showLoginDialog(); - } - } - - @Nullable - public ApplicationSession getApplicationSession() { - return applicationSession; - } - - /** - * Perform actions after success login - */ - protected void afterLoggedIn() { - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - User user = sessionSource.getUserSession().getUser(); - // Change password on logon - if (Boolean.TRUE.equals(user.getChangePasswordAtNextLogon())) { - mainFrame.deactivate(""); - final DesktopWindowManager wm = mainFrame.getWindowManager(); - for (Window window : wm.getOpenWindows()) { - window.setEnabled(false); - } - - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - WindowInfo changePasswordDialog = windowConfig.getWindowInfo("sec$User.changePassword"); - Window changePasswordWindow = wm.openEditor(changePasswordDialog, user, - OpenType.DIALOG.closeable(false), - ParamsMap.of("cancelEnabled", false)); - changePasswordWindow.addCloseListener(actionId -> { - for (Window window : wm.getOpenWindows()) { - window.setEnabled(true); - } - }); - } - } - - protected void initClientTime() { - ClientTimeSynchronizer clientTimeSynchronizer = AppBeans.get(ClientTimeSynchronizer.NAME); - clientTimeSynchronizer.syncTimeZone(); - clientTimeSynchronizer.syncTime(); - } - - public TopLevelFrame getMainFrame() { - return mainFrame; - } - - public void registerFrame(TopLevelFrame frame) { - topLevelFrames.addFirst(frame); - } - - public void unregisterFrame(TopLevelFrame frame) { - topLevelFrames.remove(frame); - } - - public DesktopResources getResources() { - return theme.getResources(); - } - - public Locale getLocale() { - if (getConnection().getSession() == null) - return Locale.getDefault(); - else - return getConnection().getSession().getLocale(); - } - - public boolean isTestMode() { - return testMode; - } - - public TestIdManager getTestIdManager() { - return testIdManager; - } - - public UiEventsMulticaster getUiEventsMulticaster() { - return uiEventsMulticaster; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.cuba.client.sys.MessagesClientImpl; +import com.haulmont.cuba.client.sys.cache.ClientCacheManager; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; +import com.haulmont.cuba.desktop.exception.ExceptionHandlers; +import com.haulmont.cuba.desktop.gui.SessionMessagesNotifier; +import com.haulmont.cuba.desktop.sys.*; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareWindowClosingListener; +import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; +import com.haulmont.cuba.desktop.theme.DesktopTheme; +import com.haulmont.cuba.desktop.theme.DesktopThemeLoader; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.TestIdManager; +import com.haulmont.cuba.gui.WindowManager.OpenType; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.gui.config.WindowInfo; +import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import com.haulmont.cuba.gui.theme.ThemeConstants; +import com.haulmont.cuba.gui.theme.ThemeConstantsRepository; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrSubstitutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.remoting.RemoteAccessException; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.plaf.InputMapUIResource; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Locale; +import java.util.concurrent.ConcurrentHashMap; + +public class App implements ConnectionListener { + + protected static App app; + + private Logger log; + private Logger userActionsLog; + + protected TopLevelFrame mainFrame; + + protected JMenuBar menuBar; + + protected Connection connection; + + protected JTabbedPane tabsPane; + + protected DesktopTheme theme; + + protected ThemeConstants themeConstants; + + protected LinkedList topLevelFrames = new LinkedList<>(); + + protected Messages messages; + + protected Configuration configuration; + + protected UiEventsMulticaster uiEventsMulticaster; + + protected boolean exiting; + + protected boolean testMode; + protected TestIdManager testIdManager = new TestIdManager(); + + protected ApplicationSession applicationSession; + + static { + initEnvironment(); + } + + public static void main(final String[] args) { + SwingUtilities.invokeLater(() -> { + app = new App(); + app.init(args); + app.show(); + app.showLoginDialog(); + }); + } + + public static void initEnvironment() { + // Due to #PL-2421 + System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); + } + + public static App getInstance() { + return app; + } + + public void init(String[] args) { + try { + System.setSecurityManager(null); + initHomeDir(); + initLogging(); + } catch (Throwable t) { + //noinspection CallToPrintStackTrace + t.printStackTrace(); + System.exit(-1); + } + + try { + log.debug("Program arguments: " + Arrays.toString(args)); + + initConnection(); + + DesktopAppContextLoader contextLoader = new DesktopAppContextLoader(getDefaultAppComponents(), getDefaultAppPropertiesConfig(), args); + contextLoader.load(); + + messages = AppBeans.get(Messages.NAME); + configuration = AppBeans.get(Configuration.NAME); + uiEventsMulticaster = AppBeans.get(UiEventsMulticaster.class); + + initTheme(); + initLookAndFeelDefaults(); + initTestMode(); + initUI(); + initExceptionHandling(); + } catch (Throwable t) { + log.error("Error initializing application", t); + System.exit(-1); + } + } + + public void show() { + if (!mainFrame.isVisible()) { + mainFrame.setVisible(true); + } + } + + public Connection getConnection() { + return connection; + } + + public JTabbedPane getTabsPane() { + return tabsPane; + } + + public void showLoginDialog() { + if (exiting) + return; + + LoginDialog loginDialog = createLoginDialog(); + setLoginDialogLocation(loginDialog); + loginDialog.open(); + } + + protected void setLoginDialogLocation(LoginDialog loginDialog) { + Point ownerLocation = mainFrame.getLocationOnScreen(); + int mainX = ownerLocation.x; + int mainY = ownerLocation.y; + + Dimension ownerSize = mainFrame.getSize(); + int mainWidth = ownerSize.width; + int mainHeight = ownerSize.height; + + Dimension size = loginDialog.getSize(); + int width = size.width; + int height = size.height; + + loginDialog.setLocation(mainX + mainWidth / 2 - width / 2, mainY + mainHeight / 2 - height / 2); + } + + protected LoginDialog createLoginDialog() { + return new LoginDialog(mainFrame, connection); + } + + protected String getApplicationTitle() { + return messages.getMainMessage("application.caption"); + } + + protected String getDefaultAppComponents() { + return ""; + } + + protected String getDefaultAppPropertiesConfig() { + return "/cuba-desktop-app.properties"; + } + + protected String getDefaultHomeDir() { + return System.getProperty("user.home") + "/.haulmont/cuba"; + } + + protected String getDefaultLogConfig() { + return "cuba-logback.xml"; + } + + protected void initHomeDir() { + String homeDir = System.getProperty(DesktopAppContextLoader.HOME_DIR_SYS_PROP); + if (StringUtils.isBlank(homeDir)) { + homeDir = getDefaultHomeDir(); + } + homeDir = StrSubstitutor.replaceSystemProperties(homeDir); + System.setProperty(DesktopAppContextLoader.HOME_DIR_SYS_PROP, homeDir); + + File file = new File(homeDir); + if (!file.exists()) { + boolean success = file.mkdirs(); + if (!success) { + System.out.println("Unable to create home dir: " + homeDir); + System.exit(-1); + } + } + if (!file.isDirectory()) { + System.out.println("Invalid home dir: " + homeDir); + System.exit(-1); + } + } + + protected void initLogging() { + String property = System.getProperty("logback.configurationFile"); + if (StringUtils.isBlank(property)) { + System.setProperty("logback.configurationFile", getDefaultLogConfig()); + } + log = LoggerFactory.getLogger(App.class); + userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + } + + protected void initTestMode() { + this.testMode = configuration.getConfig(GlobalConfig.class).getTestMode(); + } + + protected void initTheme() throws Exception { + DesktopConfig config = configuration.getConfig(DesktopConfig.class); + String themeName = config.getTheme(); + DesktopThemeLoader desktopThemeLoader = AppBeans.get(DesktopThemeLoader.NAME); + theme = desktopThemeLoader.loadTheme(themeName); + theme.init(); + + ThemeConstantsRepository themeRepository = AppBeans.get(ThemeConstantsRepository.NAME); + ThemeConstants uiTheme = themeRepository.getConstants(themeName); + + if (uiTheme == null) { + throw new IllegalStateException("Unable to use theme constants '" + themeName + "'"); + } + + this.themeConstants = uiTheme; + } + + public DesktopTheme getTheme() { + return theme; + } + + public ThemeConstants getThemeConstants() { + return themeConstants; + } + + protected void initLookAndFeelDefaults() { + InputMapUIResource inputMap = + (InputMapUIResource) UIManager.getLookAndFeelDefaults().get("FormattedTextField.focusInputMap"); + inputMap.remove(KeyStroke.getKeyStroke("ESCAPE")); + } + + protected void initUI() { + ToolTipManager.sharedInstance().setEnabled(false); + mainFrame = createMainFrame(); + mainFrame.setName("MainFrame"); + mainFrame.addWindowListener(new ValidationAwareWindowClosingListener() { + @Override + public void windowClosingAfterValidation(WindowEvent e) { + exit(); + } + }); + + mainFrame.setContentPane(createStartContentPane()); + registerFrame(mainFrame); + createMainWindowProperties().load(); + } + + protected TopLevelFrame createMainFrame() { + return new TopLevelFrame(getApplicationTitle()); + } + + protected MainWindowProperties createMainWindowProperties() { + return new MainWindowProperties(mainFrame); + } + + protected void initConnection() { + connection = createConnection(); + connection.addListener(this); + } + + protected Connection createConnection() { + return new Connection(); + } + + protected void exit() { + try { + userActionsLog.trace("Closing application..."); + if (connection.isConnected()) { + recursiveClosingFrames(topLevelFrames.iterator(), () -> { + exiting = true; + connection.logout(); + forceExit(); + }); + } else { + forceExit(); + } + } catch (Throwable e) { + log.warn("Error closing application", e); + String title = messages.getMainMessage("errorPane.title"); + String text = messages.getMainMessage("unexpectedCloseException.message") + "\n"; + if (e instanceof RemoteAccessException) { + text = text + messages.getMainMessage("connectException.message"); + } else { + text = text + e.getClass().getSimpleName() + ": " + e.getMessage(); + } + JOptionPane.showMessageDialog(mainFrame, text, title, JOptionPane.WARNING_MESSAGE); + forceExit(); + } + } + + protected void forceExit() { + //noinspection finally + try { + createMainWindowProperties().save(); + AppContext.Internals.stopContext(); + userActionsLog.trace("Application was closed"); + } finally { + System.exit(0); + } + } + + protected Container createStartContentPane() { + JPanel pane = new JPanel(new BorderLayout()); + menuBar = new JMenuBar(); + pane.add(menuBar, BorderLayout.NORTH); + + Locale loc = Locale.getDefault(); + + JMenu menu = new JMenu(messages.getMainMessage("mainMenu.file", loc)); + menuBar.add(menu); + + JMenuItem item; + + item = new JMenuItem(messages.getMainMessage("mainMenu.connect", loc)); + item.addActionListener(e -> showLoginDialog()); + menu.add(item); + + item = new JMenuItem(messages.getMainMessage("mainMenu.exit", loc)); + item.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + exit(); + } + }); + menu.add(item); + + if (isTestMode()) { + menuBar.setName("startMenu"); + } + + return pane; + } + + protected Container createContentPane() { + JPanel pane = new JPanel(new BorderLayout()); + pane.add(createTopPane(), BorderLayout.NORTH); + pane.add(createCenterPane(), BorderLayout.CENTER); + pane.add(createBottomPane(), BorderLayout.SOUTH); + + if (isTestMode()) { + pane.setName("contentPane"); + } + + return pane; + } + + protected JComponent createTopPane() { + JPanel toolBar = new JPanel(new BorderLayout()); + toolBar.add(createMenuBar(), BorderLayout.CENTER); + + if (isTestMode()) { + toolBar.setName("toolBar"); + } + + return toolBar; + } + + protected JComponent createMenuBar() { + menuBar = new JMenuBar(); + + JMenu menu = new JMenu(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.file")); + menuBar.add(menu); + + JMenuItem item; + + item = new JMenuItem(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.disconnect")); + item.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + logout(); + } + }); + menu.add(item); + + item = new JMenuItem(messages.getMessage(AppConfig.getMessagesPack(), "mainMenu.exit")); + item.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + exit(); + } + }); + menu.add(item); + + MenuBuilder builder = new MenuBuilder(connection.getSession(), menuBar); + builder.build(); + + if (isTestMode()) { + menuBar.setName("menuBar"); + } + + return menuBar; + } + + protected void logout() { + final Iterator it = topLevelFrames.iterator(); + recursiveClosingFrames(it, () -> + connection.logout() + ); + } + + protected void recursiveClosingFrames(final Iterator it, final Runnable onSuccess) { + final TopLevelFrame frame = it.next(); + frame.getWindowManager() + .checkModificationsAndCloseAll(() -> { + if (!it.hasNext()) { + onSuccess.run(); + } else { + frame.getWindowManager().dispose(); + frame.dispose(); + it.remove(); + recursiveClosingFrames(it, onSuccess); + } + }, null); + } + + protected JComponent createBottomPane() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createLineBorder(Color.gray)); + panel.setPreferredSize(new Dimension(0, 20)); + + ServerSelector serverSelector = AppBeans.get(ServerSelector.NAME); + String url = serverSelector.getUrl(serverSelector.initContext()); + if (url == null) + url = "?"; + + final JLabel connectionStateLab = new JLabel( + messages.formatMainMessage("statusBar.connected", getUserFriendlyConnectionUrl(url))); + + panel.add(connectionStateLab, BorderLayout.WEST); + + + JPanel rightPanel = new JPanel(); + BoxLayout rightLayout = new BoxLayout(rightPanel, BoxLayout.LINE_AXIS); + rightPanel.setLayout(rightLayout); + + UserSession session = connection.getSession(); + + JLabel userInfoLabel = new JLabel(); + String userInfo = messages.formatMainMessage("statusBar.user", + session.getUser().getName(), session.getUser().getLogin()); + userInfoLabel.setText(userInfo); + + rightPanel.add(userInfoLabel); + + JLabel timeZoneLabel = null; + if (session.getTimeZone() != null) { + timeZoneLabel = new JLabel(); + String timeZone = messages.formatMainMessage("statusBar.timeZone", + AppBeans.get(TimeZones.class).getDisplayNameShort(session.getTimeZone())); + timeZoneLabel.setText(timeZone); + + rightPanel.add(Box.createRigidArea(new Dimension(5, 0))); + rightPanel.add(timeZoneLabel); + } + + panel.add(rightPanel, BorderLayout.EAST); + + if (isTestMode()) { + panel.setName("bottomPane"); + userInfoLabel.setName("userInfoLabel"); + if (timeZoneLabel != null) + timeZoneLabel.setName("timeZoneLabel"); + connectionStateLab.setName("connectionStateLab"); + } + + return panel; + } + + protected String getUserFriendlyConnectionUrl(String urlString) { + try { + URL url = new URL(urlString); + return url.getHost() + (url.getPort() == -1 ? "" : ":" + url.getPort()); + } catch (MalformedURLException e) { + return urlString; + } + } + + protected JComponent createCenterPane() { + JPanel pane = new JPanel(new BorderLayout()); + pane.add(createTabsPane(), BorderLayout.CENTER); + if (isTestMode()) { + pane.setName("centerPane"); + } + return pane; + } + + protected JComponent createTabsPane() { + tabsPane = new JTabbedPaneExt(); + if (isTestMode()) { + tabsPane.setName("tabsPane"); + } + return tabsPane; + } + + protected void initExceptionHandling() { + Thread.setDefaultUncaughtExceptionHandler(this::handleException); + + System.setProperty("sun.awt.exception.handler", "com.haulmont.cuba.desktop.exception.AWTExceptionHandler"); + } + + public void handleException(Thread thread, Throwable throwable) { + if (!(throwable instanceof SilentException)) { + Logging annotation = throwable.getClass().getAnnotation(Logging.class); + Logging.Type loggingType = annotation == null ? Logging.Type.FULL : annotation.value(); + if (loggingType != Logging.Type.NONE) { + if (loggingType == Logging.Type.BRIEF) + log.error("Uncaught exception in thread " + thread + ": " + throwable.toString()); + else + log.error("Uncaught exception in thread " + thread, throwable); + } + } + + ExceptionHandlers handlers = AppBeans.get("cuba_ExceptionHandlers", ExceptionHandlers.class); + handlers.handle(thread, throwable, app.getMainFrame().getWindowManager()); + } + + /** + * Initializes exception handlers immediately after login and logout. + * Can be overridden in descendants to manipulate exception handlers programmatically. + * + * @param isConnected true after login, false after logout + */ + protected void initExceptionHandlers(boolean isConnected) { + ExceptionHandlers handlers = AppBeans.get("cuba_ExceptionHandlers", ExceptionHandlers.class); + if (isConnected) { + handlers.createByConfiguration(); + } else { + handlers.createMinimalSet(); + } + } + + @Override + public void connectionStateChanged(Connection connection) throws LoginException { + MessagesClientImpl messagesClient = AppBeans.get(Messages.NAME); + SessionMessagesNotifier messagesNotifier = AppBeans.get(SessionMessagesNotifier.NAME); + + ClientCacheManager clientCacheManager = AppBeans.get(ClientCacheManager.NAME); + clientCacheManager.initialize(); + + if (connection.isConnected()) { + applicationSession = new ApplicationSession(new ConcurrentHashMap<>()); + + messagesClient.setRemoteSearch(true); + initExceptionHandlers(true); + + DesktopWindowManager windowManager = mainFrame.getWindowManager(); + mainFrame.setContentPane(createContentPane()); + mainFrame.repaint(); + windowManager.setTabsPane(tabsPane); + + initClientTime(); + + messagesNotifier.activate(); + + SwingUtilities.invokeLater(this::afterLoggedIn); + } else { + messagesNotifier.deactivate(); + + messagesClient.setRemoteSearch(false); + Iterator it = topLevelFrames.iterator(); + while (it.hasNext()) { + TopLevelFrame frame = it.next(); + if (frame != mainFrame) { + DesktopWindowManager windowManager = frame.getWindowManager(); + if (windowManager != null) + windowManager.dispose(); + frame.dispose(); + it.remove(); + } + } + + DesktopWindowManager windowManager = mainFrame.getWindowManager(); + if (windowManager != null) + windowManager.dispose(); + + applicationSession = null; + + mainFrame.setContentPane(createStartContentPane()); + mainFrame.repaint(); + + initExceptionHandlers(false); + showLoginDialog(); + } + } + + @Nullable + public ApplicationSession getApplicationSession() { + return applicationSession; + } + + /** + * Perform actions after success login + */ + protected void afterLoggedIn() { + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + User user = sessionSource.getUserSession().getUser(); + // Change password on logon + if (Boolean.TRUE.equals(user.getChangePasswordAtNextLogon())) { + mainFrame.deactivate(""); + final DesktopWindowManager wm = mainFrame.getWindowManager(); + for (Window window : wm.getOpenWindows()) { + window.setEnabled(false); + } + + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + WindowInfo changePasswordDialog = windowConfig.getWindowInfo("sec$User.changePassword"); + Window changePasswordWindow = wm.openEditor(changePasswordDialog, user, + OpenType.DIALOG.closeable(false), + ParamsMap.of("cancelEnabled", false)); + changePasswordWindow.addCloseListener(actionId -> { + for (Window window : wm.getOpenWindows()) { + window.setEnabled(true); + } + }); + } + } + + protected void initClientTime() { + ClientTimeSynchronizer clientTimeSynchronizer = AppBeans.get(ClientTimeSynchronizer.NAME); + clientTimeSynchronizer.syncTimeZone(); + clientTimeSynchronizer.syncTime(); + } + + public TopLevelFrame getMainFrame() { + return mainFrame; + } + + public void registerFrame(TopLevelFrame frame) { + topLevelFrames.addFirst(frame); + } + + public void unregisterFrame(TopLevelFrame frame) { + topLevelFrames.remove(frame); + } + + public DesktopResources getResources() { + return theme.getResources(); + } + + public Locale getLocale() { + if (getConnection().getSession() == null) + return Locale.getDefault(); + else + return getConnection().getSession().getLocale(); + } + + public boolean isTestMode() { + return testMode; + } + + public TestIdManager getTestIdManager() { + return testIdManager; + } + + public UiEventsMulticaster getUiEventsMulticaster() { + return uiEventsMulticaster; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/Connection.java b/modules/desktop/src/com/haulmont/cuba/desktop/Connection.java index 0f92788c4f..41ca7df55b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/Connection.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/Connection.java @@ -1,189 +1,189 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.cuba.client.ClientUserSession; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.auth.AbstractClientCredentials; -import com.haulmont.cuba.security.auth.AuthenticationService; -import com.haulmont.cuba.security.auth.LoginPasswordCredentials; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.SessionParams; -import com.haulmont.cuba.security.global.UserSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.*; - -public class Connection { - - private final Logger log = LoggerFactory.getLogger(Connection.class); - - private List listeners = new ArrayList<>(); - - protected boolean connected; - - protected UserSession session; - - public void login(String login, String password, Locale locale) throws LoginException { - UserSession userSession = doLogin(login, password, locale, getLoginParams()); - ClientUserSession clientUserSession = new ClientUserSession(userSession); - clientUserSession.setAuthenticated(true); - - session = clientUserSession; - AppContext.setSecurityContext(new SecurityContext(session)); - log.info("Logged in: {}", session); - - updateSessionClientInfo(); - - connected = true; - fireConnectionListeners(); - } - - /** - * Forward login logic to {@link com.haulmont.cuba.security.auth.AuthenticationService}. - * Can be overridden to change login logic. - * - * @param login login name - * @param password encrypted password - * @param locale client locale - * @param loginParams login parameters - * @return created user session - * @throws LoginException in case of unsuccessful login - */ - protected UserSession doLogin(String login, String password, Locale locale, Map loginParams) - throws LoginException { - AbstractClientCredentials credentials = new LoginPasswordCredentials(login, password, locale); - setCredentialsParams(credentials, loginParams); - - AuthenticationService authenticationService = AppBeans.get(AuthenticationService.NAME); - return authenticationService.login(credentials).getSession(); - } - - protected void setCredentialsParams(AbstractClientCredentials credentials, Map loginParams) { - credentials.setClientInfo(makeClientInfo()); - credentials.setClientType(ClientType.DESKTOP); - - Optional address = Optional.empty(); - try { - address = Optional.ofNullable(InetAddress.getLocalHost()); - } catch (UnknownHostException e) { - log.warn("Unable to obtain local IP address", e); - } - - if (address.isPresent()) { - credentials.setIpAddress(address.get().getHostAddress()); - credentials.setHostName(address.get().getHostName()); - } - - credentials.setParams(loginParams); - - Configuration configuration = AppBeans.get(Configuration.class); - GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); - if (!globalConfig.getLocaleSelectVisible()) { - credentials.setOverrideLocale(false); - } - } - - protected Map getLoginParams() { - Optional address = Optional.empty(); - try { - address = Optional.ofNullable(InetAddress.getLocalHost()); - } catch (UnknownHostException e) { - log.warn("Unable to obtain local IP address", e); - } - - return ParamsMap.of( - ClientType.class.getName(), ClientType.DESKTOP.name(), - SessionParams.HOST_NAME.getId(), address.map(InetAddress::getHostName).orElse(null), - SessionParams.IP_ADDERSS.getId(), address.map(InetAddress::getHostAddress).orElse(null), - SessionParams.CLIENT_INFO.getId(), makeClientInfo() - ); - } - - protected void updateSessionClientInfo() { - if (Boolean.TRUE.equals(session.getUser().getTimeZoneAuto())) { - session.setTimeZone(TimeZone.getDefault()); - } - } - - protected String makeClientInfo() { - StringBuilder sb = new StringBuilder(); - sb.append("Desktop ") - .append("os{") - .append("name=").append(System.getProperty("os.name")) - .append(", arch=").append(System.getProperty("os.arch")) - .append(", version=").append(System.getProperty("os.version")) - .append("}, ") - .append("java{") - .append("vendor=").append(System.getProperty("java.vendor")) - .append(", version=").append(System.getProperty("java.version")) - .append("}"); - return sb.toString(); - } - - public void logout() { - try { - AuthenticationService authenticationService = AppBeans.get(AuthenticationService.NAME); - authenticationService.logout(); - AppContext.setSecurityContext(null); - log.info("Logged out: " + session); - } catch (Exception e) { - log.warn("Error on logout", e); - } - - connected = false; - try { - fireConnectionListeners(); - } catch (LoginException e) { - log.warn("Error on logout", e); - } - session = null; - } - - public boolean isConnected() { - return connected; - } - - public UserSession getSession() { - return session; - } - - public void addListener(ConnectionListener listener) { - if (!listeners.contains(listener)) - listeners.add(listener); - } - - public void removeListener(ConnectionListener listener) { - listeners.remove(listener); - } - - protected void fireConnectionListeners() throws LoginException { - for (ConnectionListener listener : listeners) { - listener.connectionStateChanged(this); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.cuba.client.ClientUserSession; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.auth.AbstractClientCredentials; +import com.haulmont.cuba.security.auth.AuthenticationService; +import com.haulmont.cuba.security.auth.LoginPasswordCredentials; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.SessionParams; +import com.haulmont.cuba.security.global.UserSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.*; + +public class Connection { + + private final Logger log = LoggerFactory.getLogger(Connection.class); + + private List listeners = new ArrayList<>(); + + protected boolean connected; + + protected UserSession session; + + public void login(String login, String password, Locale locale) throws LoginException { + UserSession userSession = doLogin(login, password, locale, getLoginParams()); + ClientUserSession clientUserSession = new ClientUserSession(userSession); + clientUserSession.setAuthenticated(true); + + session = clientUserSession; + AppContext.setSecurityContext(new SecurityContext(session)); + log.info("Logged in: {}", session); + + updateSessionClientInfo(); + + connected = true; + fireConnectionListeners(); + } + + /** + * Forward login logic to {@link com.haulmont.cuba.security.auth.AuthenticationService}. + * Can be overridden to change login logic. + * + * @param login login name + * @param password encrypted password + * @param locale client locale + * @param loginParams login parameters + * @return created user session + * @throws LoginException in case of unsuccessful login + */ + protected UserSession doLogin(String login, String password, Locale locale, Map loginParams) + throws LoginException { + AbstractClientCredentials credentials = new LoginPasswordCredentials(login, password, locale); + setCredentialsParams(credentials, loginParams); + + AuthenticationService authenticationService = AppBeans.get(AuthenticationService.NAME); + return authenticationService.login(credentials).getSession(); + } + + protected void setCredentialsParams(AbstractClientCredentials credentials, Map loginParams) { + credentials.setClientInfo(makeClientInfo()); + credentials.setClientType(ClientType.DESKTOP); + + Optional address = Optional.empty(); + try { + address = Optional.ofNullable(InetAddress.getLocalHost()); + } catch (UnknownHostException e) { + log.warn("Unable to obtain local IP address", e); + } + + if (address.isPresent()) { + credentials.setIpAddress(address.get().getHostAddress()); + credentials.setHostName(address.get().getHostName()); + } + + credentials.setParams(loginParams); + + Configuration configuration = AppBeans.get(Configuration.class); + GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); + if (!globalConfig.getLocaleSelectVisible()) { + credentials.setOverrideLocale(false); + } + } + + protected Map getLoginParams() { + Optional address = Optional.empty(); + try { + address = Optional.ofNullable(InetAddress.getLocalHost()); + } catch (UnknownHostException e) { + log.warn("Unable to obtain local IP address", e); + } + + return ParamsMap.of( + ClientType.class.getName(), ClientType.DESKTOP.name(), + SessionParams.HOST_NAME.getId(), address.map(InetAddress::getHostName).orElse(null), + SessionParams.IP_ADDERSS.getId(), address.map(InetAddress::getHostAddress).orElse(null), + SessionParams.CLIENT_INFO.getId(), makeClientInfo() + ); + } + + protected void updateSessionClientInfo() { + if (Boolean.TRUE.equals(session.getUser().getTimeZoneAuto())) { + session.setTimeZone(TimeZone.getDefault()); + } + } + + protected String makeClientInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("Desktop ") + .append("os{") + .append("name=").append(System.getProperty("os.name")) + .append(", arch=").append(System.getProperty("os.arch")) + .append(", version=").append(System.getProperty("os.version")) + .append("}, ") + .append("java{") + .append("vendor=").append(System.getProperty("java.vendor")) + .append(", version=").append(System.getProperty("java.version")) + .append("}"); + return sb.toString(); + } + + public void logout() { + try { + AuthenticationService authenticationService = AppBeans.get(AuthenticationService.NAME); + authenticationService.logout(); + AppContext.setSecurityContext(null); + log.info("Logged out: " + session); + } catch (Exception e) { + log.warn("Error on logout", e); + } + + connected = false; + try { + fireConnectionListeners(); + } catch (LoginException e) { + log.warn("Error on logout", e); + } + session = null; + } + + public boolean isConnected() { + return connected; + } + + public UserSession getSession() { + return session; + } + + public void addListener(ConnectionListener listener) { + if (!listeners.contains(listener)) + listeners.add(listener); + } + + public void removeListener(ConnectionListener listener) { + listeners.remove(listener); + } + + protected void fireConnectionListeners() throws LoginException { + for (ConnectionListener listener : listeners) { + listener.connectionStateChanged(this); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/ConnectionListener.java b/modules/desktop/src/com/haulmont/cuba/desktop/ConnectionListener.java index 190b544d20..d48d0ea9a7 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/ConnectionListener.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/ConnectionListener.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.security.global.LoginException; - -public interface ConnectionListener { - void connectionStateChanged(Connection connection) throws LoginException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.security.global.LoginException; + +public interface ConnectionListener { + void connectionStateChanged(Connection connection) throws LoginException; } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/DesktopConfig.java b/modules/desktop/src/com/haulmont/cuba/desktop/DesktopConfig.java index aa1e0e8709..42d882c139 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/DesktopConfig.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/DesktopConfig.java @@ -1,118 +1,118 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.Default; -import com.haulmont.cuba.core.config.defaults.DefaultBoolean; -import com.haulmont.cuba.core.config.defaults.DefaultInt; -import com.haulmont.cuba.core.config.type.Factory; -import com.haulmont.cuba.core.config.type.IntegerListTypeFactory; - -import java.util.List; - -/** - * Desktop UI configuration parameters. - * - */ -@Source(type = SourceType.APP) -public interface DesktopConfig extends Config { - - /** - * List of root directories where resources (icons, images, theme config) are located. - * Resources are local to each desktop theme. - * For each root directory must exist subdirectory with name of current theme. - * - * @return list of root resource directories - */ - @Property("cuba.desktop.resourceLocations") - @Default("com/haulmont/cuba/desktop/res") - String getResourceLocations(); - - @Property("cuba.desktop.mainTabCaptionLength") - @DefaultInt(25) - int getMainTabCaptionLength(); - - @Property("cuba.desktop.windowIcon") - String getWindowIcon(); - - /** - * Desktop theme name. - * Theme configuration file is located as ${resourceLocation}/${themeName}/${themeName}.xml. - * - * @return desktop theme name - */ - @Property("cuba.desktop.theme") - @Default("nimbus") - String getTheme(); - - @Property("cuba.desktop.dialogNotificationsEnabled") - @DefaultBoolean(false) - boolean isDialogNotificationsEnabled(); - - @Property("cuba.desktop.availableFontSizes") - @Factory(factory = IntegerListTypeFactory.class) - @Default("6 8 10 12 14 16 18 20 22 24 28 32 36 48 54 60 72") - List getAvailableFontSizes(); - - /** - * @return true if application should change time zone to that which is used by server - */ - @Property("cuba.desktop.useServerTimeZone") - @DefaultBoolean(true) - boolean isUseServerTimeZone(); - - /** - * @return true if application should synchronize its time source with server time - */ - @Property("cuba.desktop.useServerTime") - @DefaultBoolean(true) - boolean isUseServerTime(); - - /** - * @return Timeout of loading session messages from server in seconds - */ - @Property("cuba.desktop.sessionMessagesIntervalSec") - @DefaultInt(60) - int getSessionMessagesIntervalSec(); - - /** - * @deprecated Use {@link ClientConfig#getSuggestionFieldAsyncSearchDelayMs()} instead - */ - @Property("cuba.desktop.searchField.asyncTimeoutMs") - @DefaultInt(200) - int getSearchFieldAsyncTimeoutMs(); - - /** - * @return Default user login to set in the login dialog. - */ - @Property("cuba.desktop.loginDialogDefaultUser") - @Default("admin") - String getLoginDialogDefaultUser(); - - /** - * @return Default user password to set in the login dialog. - */ - @Property("cuba.desktop.loginDialogDefaultPassword") - @Default("admin") - String getLoginDialogDefaultPassword(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.Default; +import com.haulmont.cuba.core.config.defaults.DefaultBoolean; +import com.haulmont.cuba.core.config.defaults.DefaultInt; +import com.haulmont.cuba.core.config.type.Factory; +import com.haulmont.cuba.core.config.type.IntegerListTypeFactory; + +import java.util.List; + +/** + * Desktop UI configuration parameters. + * + */ +@Source(type = SourceType.APP) +public interface DesktopConfig extends Config { + + /** + * List of root directories where resources (icons, images, theme config) are located. + * Resources are local to each desktop theme. + * For each root directory must exist subdirectory with name of current theme. + * + * @return list of root resource directories + */ + @Property("cuba.desktop.resourceLocations") + @Default("com/haulmont/cuba/desktop/res") + String getResourceLocations(); + + @Property("cuba.desktop.mainTabCaptionLength") + @DefaultInt(25) + int getMainTabCaptionLength(); + + @Property("cuba.desktop.windowIcon") + String getWindowIcon(); + + /** + * Desktop theme name. + * Theme configuration file is located as ${resourceLocation}/${themeName}/${themeName}.xml. + * + * @return desktop theme name + */ + @Property("cuba.desktop.theme") + @Default("nimbus") + String getTheme(); + + @Property("cuba.desktop.dialogNotificationsEnabled") + @DefaultBoolean(false) + boolean isDialogNotificationsEnabled(); + + @Property("cuba.desktop.availableFontSizes") + @Factory(factory = IntegerListTypeFactory.class) + @Default("6 8 10 12 14 16 18 20 22 24 28 32 36 48 54 60 72") + List getAvailableFontSizes(); + + /** + * @return true if application should change time zone to that which is used by server + */ + @Property("cuba.desktop.useServerTimeZone") + @DefaultBoolean(true) + boolean isUseServerTimeZone(); + + /** + * @return true if application should synchronize its time source with server time + */ + @Property("cuba.desktop.useServerTime") + @DefaultBoolean(true) + boolean isUseServerTime(); + + /** + * @return Timeout of loading session messages from server in seconds + */ + @Property("cuba.desktop.sessionMessagesIntervalSec") + @DefaultInt(60) + int getSessionMessagesIntervalSec(); + + /** + * @deprecated Use {@link ClientConfig#getSuggestionFieldAsyncSearchDelayMs()} instead + */ + @Property("cuba.desktop.searchField.asyncTimeoutMs") + @DefaultInt(200) + int getSearchFieldAsyncTimeoutMs(); + + /** + * @return Default user login to set in the login dialog. + */ + @Property("cuba.desktop.loginDialogDefaultUser") + @Default("admin") + String getLoginDialogDefaultUser(); + + /** + * @return Default user password to set in the login dialog. + */ + @Property("cuba.desktop.loginDialogDefaultPassword") + @Default("admin") + String getLoginDialogDefaultPassword(); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/DesktopResources.java b/modules/desktop/src/com/haulmont/cuba/desktop/DesktopResources.java index fb7edf3efa..e449afba2e 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/DesktopResources.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/DesktopResources.java @@ -1,104 +1,104 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.core.global.Resources; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; -import java.util.List; - -public class DesktopResources { - - private Logger log = LoggerFactory.getLogger(DesktopResources.class); - - protected List roots; - - protected Map cache = new HashMap<>(); - - protected Resources resources; - - public DesktopResources(List roots, Resources resources) { - this.resources = resources; - this.roots = new ArrayList<>(roots); - - Collections.reverse(this.roots); - } - - public Image getImage(String name) { - byte[] bytes = getImageBytes(name); - - try { - return ImageIO.read(new ByteArrayInputStream(bytes)); - } catch (IOException e) { - log.warn("Unable to read image from bytes", e); - return null; - } - } - - public Icon getIcon(String name) { - byte[] bytes = getImageBytes(name); - - return new ImageIcon(bytes); - } - - protected byte[] getImageBytes(String name) { - if (!name.startsWith("/")) - name = "/" + name; - - byte[] bytes = cache.get(name); - if (bytes == null) { - for (String root : roots) { - InputStream stream = resources.getResourceAsStream(root + name); - if (stream != null) { - try { - bytes = IOUtils.toByteArray(stream); - cache.put(name, bytes); - break; - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(stream); - } - } - } - if (bytes == null) { - log.warn("Resource " + name + " not found in " + roots); - InputStream stream = resources.getResourceAsStream("/com/haulmont/cuba/desktop/res/nimbus/icons/attention.png"); - if (stream != null) { - try { - bytes = IOUtils.toByteArray(stream); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(stream); - } - } - } - } - return bytes; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.core.global.Resources; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.List; + +public class DesktopResources { + + private Logger log = LoggerFactory.getLogger(DesktopResources.class); + + protected List roots; + + protected Map cache = new HashMap<>(); + + protected Resources resources; + + public DesktopResources(List roots, Resources resources) { + this.resources = resources; + this.roots = new ArrayList<>(roots); + + Collections.reverse(this.roots); + } + + public Image getImage(String name) { + byte[] bytes = getImageBytes(name); + + try { + return ImageIO.read(new ByteArrayInputStream(bytes)); + } catch (IOException e) { + log.warn("Unable to read image from bytes", e); + return null; + } + } + + public Icon getIcon(String name) { + byte[] bytes = getImageBytes(name); + + return new ImageIcon(bytes); + } + + protected byte[] getImageBytes(String name) { + if (!name.startsWith("/")) + name = "/" + name; + + byte[] bytes = cache.get(name); + if (bytes == null) { + for (String root : roots) { + InputStream stream = resources.getResourceAsStream(root + name); + if (stream != null) { + try { + bytes = IOUtils.toByteArray(stream); + cache.put(name, bytes); + break; + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } + } + if (bytes == null) { + log.warn("Resource " + name + " not found in " + roots); + InputStream stream = resources.getResourceAsStream("/com/haulmont/cuba/desktop/res/nimbus/icons/attention.png"); + if (stream != null) { + try { + bytes = IOUtils.toByteArray(stream); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } + } + } + return bytes; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/DetachedFrame.java b/modules/desktop/src/com/haulmont/cuba/desktop/DetachedFrame.java index caff5f21c2..39dfbd2ac8 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/DetachedFrame.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/DetachedFrame.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.sys.DisabledGlassPane; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; - -/** - * Container for detached inner tab or frame - * - */ -public class DetachedFrame extends JFrame { - - private Container parentContainer; - - private DisabledGlassPane glassPane; - - public DetachedFrame(String caption, Container parentContainer) { - super(caption); - this.parentContainer = parentContainer; - initUI(); - } - - public Container getParentContainer() { - return parentContainer; - } - - private void initUI() { - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - glassPane = new DisabledGlassPane(); - JRootPane rootPane = SwingUtilities.getRootPane(this); - rootPane.setGlassPane(glassPane); - - final java.awt.Component topLevelGlassPane = DesktopComponentsHelper.getTopLevelFrame(parentContainer).getGlassPane(); - topLevelGlassPane.addHierarchyListener(new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) == HierarchyEvent.SHOWING_CHANGED) { - if (topLevelGlassPane.isVisible()) { - glassPane.activate(null); - } else { - glassPane.deactivate(); - } - } - } - }); - } - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.sys.DisabledGlassPane; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; + +/** + * Container for detached inner tab or frame + * + */ +public class DetachedFrame extends JFrame { + + private Container parentContainer; + + private DisabledGlassPane glassPane; + + public DetachedFrame(String caption, Container parentContainer) { + super(caption); + this.parentContainer = parentContainer; + initUI(); + } + + public Container getParentContainer() { + return parentContainer; + } + + private void initUI() { + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + glassPane = new DisabledGlassPane(); + JRootPane rootPane = SwingUtilities.getRootPane(this); + rootPane.setGlassPane(glassPane); + + final java.awt.Component topLevelGlassPane = DesktopComponentsHelper.getTopLevelFrame(parentContainer).getGlassPane(); + topLevelGlassPane.addHierarchyListener(new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) == HierarchyEvent.SHOWING_CHANGED) { + if (topLevelGlassPane.isVisible()) { + glassPane.activate(null); + } else { + glassPane.deactivate(); + } + } + } + }); + } + +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/LoginDialog.java b/modules/desktop/src/com/haulmont/cuba/desktop/LoginDialog.java index e76cc82b22..ea8eb21f93 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/LoginDialog.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/LoginDialog.java @@ -1,222 +1,222 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.sys.LoginProperties; -import com.haulmont.cuba.gui.components.Frame.NotificationType; -import com.haulmont.cuba.security.global.LoginException; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang.LocaleUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.Locale; -import java.util.Map; - -public class LoginDialog extends JDialog { - - private final Logger log = LoggerFactory.getLogger(LoginDialog.class); - private final DesktopConfig desktopConfig; - - protected Connection connection; - protected Locale resolvedLocale; - protected Map locales; - protected Messages messages = AppBeans.get(Messages.NAME); - protected PasswordEncryption passwordEncryption = AppBeans.get(PasswordEncryption.NAME); - - protected JTextField nameField; - protected JTextField passwordField; - protected JComboBox localeCombo; - protected JButton loginBtn; - protected LoginProperties loginProperties; - - public LoginDialog(JFrame owner, Connection connection) { - super(owner); - this.connection = connection; - this.loginProperties = new LoginProperties(); - Configuration configuration = AppBeans.get(Configuration.NAME); - desktopConfig = configuration.getConfig(DesktopConfig.class); - this.locales = configuration.getConfig(GlobalConfig.class).getAvailableLocales(); - resolvedLocale = resolveLocale(); - addWindowListener( - new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - DesktopComponentsHelper.getTopLevelFrame(LoginDialog.this).activate(); - } - } - ); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - setTitle(messages.getMainMessage("loginWindow.caption", resolvedLocale)); - setContentPane(createContentPane()); - setResizable(false); - pack(); - } - - protected Container createContentPane() { - MigLayout layout = new MigLayout("fillx, insets dialog", "[right][]"); - JPanel panel = new JPanel(layout); - - panel.add(new JLabel(messages.getMainMessage("loginWindow.loginField", resolvedLocale))); - - nameField = new JTextField(); - passwordField = new JPasswordField(); - - String defaultName = desktopConfig.getLoginDialogDefaultUser(); - String lastLogin = loginProperties.loadLastLogin(); - if (!StringUtils.isBlank(lastLogin)) { - nameField.setText(lastLogin); - SwingUtilities.invokeLater(() -> - passwordField.requestFocus() - ); - } else if (!StringUtils.isBlank(defaultName)) { - nameField.setText(defaultName); - } - - panel.add(nameField, "width 150!, wrap"); - - panel.add(new JLabel(messages.getMainMessage("loginWindow.passwordField", resolvedLocale))); - String defaultPassword = desktopConfig.getLoginDialogDefaultPassword(); - if (!StringUtils.isBlank(defaultPassword)) - passwordField.setText(defaultPassword); - panel.add(passwordField, "width 150!, wrap"); - - Configuration configuration = AppBeans.get(Configuration.NAME); - - localeCombo = new JComboBox<>(); - initLocales(localeCombo); - if (configuration.getConfig(GlobalConfig.class).getLocaleSelectVisible()) { - panel.add(new JLabel(messages.getMainMessage("loginWindow.localesSelect", resolvedLocale))); - panel.add(localeCombo, "width 150!, wrap"); - } - - loginBtn = new JButton(messages.getMainMessage("loginWindow.okButton", resolvedLocale)); - loginBtn.setIcon(App.getInstance().getResources().getIcon("icons/ok.png")); - loginBtn.addActionListener(e -> - doLogin() - ); - DesktopComponentsHelper.adjustSize(loginBtn); - panel.add(loginBtn, "span, align center"); - - getRootPane().setDefaultButton(loginBtn); - - assignTestIdsIfNeeded(panel); - - return panel; - } - - protected void assignTestIdsIfNeeded(JPanel panel) { - if (App.getInstance().isTestMode()) { - panel.setName("contentPane"); - nameField.setName("nameField"); - passwordField.setName("passwordField"); - loginBtn.setName("loginBtn"); - localeCombo.setName("localeCombo"); - } - } - - protected void doLogin() { - String name = nameField.getText(); - String password = passwordField.getText(); - - String selectedItem = (String) localeCombo.getSelectedItem(); - Locale locale = locales.get(selectedItem); - try { - connection.login(name, passwordEncryption.getPlainHash(password), locale); - setVisible(false); - loginProperties.save(name, messages.getTools().localeToString(locale)); - DesktopComponentsHelper.getTopLevelFrame(this).activate(); - } catch (LoginException ex) { - log.info("Login failed: " + ex.toString()); - String caption = messages.getMainMessage("loginWindow.loginFailed", locale); - - TopLevelFrame mainFrame = App.getInstance().getMainFrame(); - mainFrame.showNotification(caption, ex.getMessage(), NotificationType.ERROR); - } - } - - @Deprecated - protected boolean bruteForceProtectionCheck(String login, String ipAddress) { - return true; - } - - @Deprecated - @Nullable - protected String registerUnsuccessfulLoginAttempt(String login, String ipAddress) { - return null; - } - - protected void initLocales(JComboBox localeCombo) { - String currLocale = loginProperties.loadLastLocale(); - if (StringUtils.isBlank(currLocale)) { - currLocale = messages.getTools().localeToString(resolvedLocale); - } - String selected = null; - for (Map.Entry entry : locales.entrySet()) { - localeCombo.addItem(entry.getKey()); - if (messages.getTools().localeToString(entry.getValue()).equals(currLocale)) - selected = entry.getKey(); - } - if (selected == null) - selected = locales.keySet().iterator().next(); - - localeCombo.setSelectedItem(selected); - } - - public void open() { - DesktopComponentsHelper.getTopLevelFrame(this).deactivate(null); - setVisible(true); - } - - protected Locale resolveLocale() { - Locale appLocale; - String lastLocale = this.loginProperties.loadLastLocale(); - if (StringUtils.isNotEmpty(lastLocale)) { - appLocale = LocaleUtils.toLocale(lastLocale); - } else { - appLocale = Locale.getDefault(); - } - - for (Locale locale : locales.values()) { - if (locale.equals(appLocale)) { - return locale; - } - } - - // if not found and application locale contains country, try to match by language only - if (StringUtils.isNotEmpty(appLocale.getCountry())) { - Locale languageTagLocale = Locale.forLanguageTag(appLocale.getLanguage()); - for (Locale locale : locales.values()) { - if (Locale.forLanguageTag(locale.getLanguage()).equals(languageTagLocale)) { - return locale; - } - } - } - - // return first locale set in the cuba.availableLocales app property - return locales.values().iterator().next(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.sys.LoginProperties; +import com.haulmont.cuba.gui.components.Frame.NotificationType; +import com.haulmont.cuba.security.global.LoginException; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang.LocaleUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Locale; +import java.util.Map; + +public class LoginDialog extends JDialog { + + private final Logger log = LoggerFactory.getLogger(LoginDialog.class); + private final DesktopConfig desktopConfig; + + protected Connection connection; + protected Locale resolvedLocale; + protected Map locales; + protected Messages messages = AppBeans.get(Messages.NAME); + protected PasswordEncryption passwordEncryption = AppBeans.get(PasswordEncryption.NAME); + + protected JTextField nameField; + protected JTextField passwordField; + protected JComboBox localeCombo; + protected JButton loginBtn; + protected LoginProperties loginProperties; + + public LoginDialog(JFrame owner, Connection connection) { + super(owner); + this.connection = connection; + this.loginProperties = new LoginProperties(); + Configuration configuration = AppBeans.get(Configuration.NAME); + desktopConfig = configuration.getConfig(DesktopConfig.class); + this.locales = configuration.getConfig(GlobalConfig.class).getAvailableLocales(); + resolvedLocale = resolveLocale(); + addWindowListener( + new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + DesktopComponentsHelper.getTopLevelFrame(LoginDialog.this).activate(); + } + } + ); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setTitle(messages.getMainMessage("loginWindow.caption", resolvedLocale)); + setContentPane(createContentPane()); + setResizable(false); + pack(); + } + + protected Container createContentPane() { + MigLayout layout = new MigLayout("fillx, insets dialog", "[right][]"); + JPanel panel = new JPanel(layout); + + panel.add(new JLabel(messages.getMainMessage("loginWindow.loginField", resolvedLocale))); + + nameField = new JTextField(); + passwordField = new JPasswordField(); + + String defaultName = desktopConfig.getLoginDialogDefaultUser(); + String lastLogin = loginProperties.loadLastLogin(); + if (!StringUtils.isBlank(lastLogin)) { + nameField.setText(lastLogin); + SwingUtilities.invokeLater(() -> + passwordField.requestFocus() + ); + } else if (!StringUtils.isBlank(defaultName)) { + nameField.setText(defaultName); + } + + panel.add(nameField, "width 150!, wrap"); + + panel.add(new JLabel(messages.getMainMessage("loginWindow.passwordField", resolvedLocale))); + String defaultPassword = desktopConfig.getLoginDialogDefaultPassword(); + if (!StringUtils.isBlank(defaultPassword)) + passwordField.setText(defaultPassword); + panel.add(passwordField, "width 150!, wrap"); + + Configuration configuration = AppBeans.get(Configuration.NAME); + + localeCombo = new JComboBox<>(); + initLocales(localeCombo); + if (configuration.getConfig(GlobalConfig.class).getLocaleSelectVisible()) { + panel.add(new JLabel(messages.getMainMessage("loginWindow.localesSelect", resolvedLocale))); + panel.add(localeCombo, "width 150!, wrap"); + } + + loginBtn = new JButton(messages.getMainMessage("loginWindow.okButton", resolvedLocale)); + loginBtn.setIcon(App.getInstance().getResources().getIcon("icons/ok.png")); + loginBtn.addActionListener(e -> + doLogin() + ); + DesktopComponentsHelper.adjustSize(loginBtn); + panel.add(loginBtn, "span, align center"); + + getRootPane().setDefaultButton(loginBtn); + + assignTestIdsIfNeeded(panel); + + return panel; + } + + protected void assignTestIdsIfNeeded(JPanel panel) { + if (App.getInstance().isTestMode()) { + panel.setName("contentPane"); + nameField.setName("nameField"); + passwordField.setName("passwordField"); + loginBtn.setName("loginBtn"); + localeCombo.setName("localeCombo"); + } + } + + protected void doLogin() { + String name = nameField.getText(); + String password = passwordField.getText(); + + String selectedItem = (String) localeCombo.getSelectedItem(); + Locale locale = locales.get(selectedItem); + try { + connection.login(name, passwordEncryption.getPlainHash(password), locale); + setVisible(false); + loginProperties.save(name, messages.getTools().localeToString(locale)); + DesktopComponentsHelper.getTopLevelFrame(this).activate(); + } catch (LoginException ex) { + log.info("Login failed: " + ex.toString()); + String caption = messages.getMainMessage("loginWindow.loginFailed", locale); + + TopLevelFrame mainFrame = App.getInstance().getMainFrame(); + mainFrame.showNotification(caption, ex.getMessage(), NotificationType.ERROR); + } + } + + @Deprecated + protected boolean bruteForceProtectionCheck(String login, String ipAddress) { + return true; + } + + @Deprecated + @Nullable + protected String registerUnsuccessfulLoginAttempt(String login, String ipAddress) { + return null; + } + + protected void initLocales(JComboBox localeCombo) { + String currLocale = loginProperties.loadLastLocale(); + if (StringUtils.isBlank(currLocale)) { + currLocale = messages.getTools().localeToString(resolvedLocale); + } + String selected = null; + for (Map.Entry entry : locales.entrySet()) { + localeCombo.addItem(entry.getKey()); + if (messages.getTools().localeToString(entry.getValue()).equals(currLocale)) + selected = entry.getKey(); + } + if (selected == null) + selected = locales.keySet().iterator().next(); + + localeCombo.setSelectedItem(selected); + } + + public void open() { + DesktopComponentsHelper.getTopLevelFrame(this).deactivate(null); + setVisible(true); + } + + protected Locale resolveLocale() { + Locale appLocale; + String lastLocale = this.loginProperties.loadLastLocale(); + if (StringUtils.isNotEmpty(lastLocale)) { + appLocale = LocaleUtils.toLocale(lastLocale); + } else { + appLocale = Locale.getDefault(); + } + + for (Locale locale : locales.values()) { + if (locale.equals(appLocale)) { + return locale; + } + } + + // if not found and application locale contains country, try to match by language only + if (StringUtils.isNotEmpty(appLocale.getCountry())) { + Locale languageTagLocale = Locale.forLanguageTag(appLocale.getLanguage()); + for (Locale locale : locales.values()) { + if (Locale.forLanguageTag(locale.getLanguage()).equals(languageTagLocale)) { + return locale; + } + } + } + + // return first locale set in the cuba.availableLocales app property + return locales.values().iterator().next(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/TopLevelFrame.java b/modules/desktop/src/com/haulmont/cuba/desktop/TopLevelFrame.java index 1558f13844..1cdb2761d6 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/TopLevelFrame.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/TopLevelFrame.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.desktop.sys.DesktopWindowManager; -import com.haulmont.cuba.desktop.sys.DisabledGlassPane; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.swing.*; - -import static com.haulmont.cuba.gui.components.Frame.NotificationType; - -/** - * Represents Top level application frame - * - */ -public class TopLevelFrame extends JFrame { - - protected DisabledGlassPane glassPane; - - protected DesktopWindowManager windowManager; - - public TopLevelFrame(String applicationTitle) { - super(applicationTitle); - initUI(); - } - - protected void initUI() { - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - glassPane = new DisabledGlassPane(); - JRootPane rootPane = SwingUtilities.getRootPane(this); - rootPane.setGlassPane(glassPane); - - Configuration configuration = AppBeans.get(Configuration.NAME); - DesktopConfig config = configuration.getConfig(DesktopConfig.class); - - DesktopResources resources = App.getInstance().getResources(); - if (StringUtils.isNotEmpty(config.getWindowIcon())) { - setIconImage(resources.getImage(config.getWindowIcon())); - } - } - - public void deactivate(@Nullable String message) { - glassPane.activate(message); - } - - public void activate() { - glassPane.deactivate(); - } - - public DesktopWindowManager getWindowManager() { - if (windowManager == null) - initWindowManager(); - - return windowManager; - } - - protected void initWindowManager() { - windowManager = new DesktopWindowManager(this); - } - - public void showNotification(String caption, String description, NotificationType type) { - getWindowManager().showNotification(caption, description, type); - } - - public void showNotification(String caption, NotificationType type) { - getWindowManager().showNotification(caption, type); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.desktop.sys.DesktopWindowManager; +import com.haulmont.cuba.desktop.sys.DisabledGlassPane; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.swing.*; + +import static com.haulmont.cuba.gui.components.Frame.NotificationType; + +/** + * Represents Top level application frame + * + */ +public class TopLevelFrame extends JFrame { + + protected DisabledGlassPane glassPane; + + protected DesktopWindowManager windowManager; + + public TopLevelFrame(String applicationTitle) { + super(applicationTitle); + initUI(); + } + + protected void initUI() { + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + glassPane = new DisabledGlassPane(); + JRootPane rootPane = SwingUtilities.getRootPane(this); + rootPane.setGlassPane(glassPane); + + Configuration configuration = AppBeans.get(Configuration.NAME); + DesktopConfig config = configuration.getConfig(DesktopConfig.class); + + DesktopResources resources = App.getInstance().getResources(); + if (StringUtils.isNotEmpty(config.getWindowIcon())) { + setIconImage(resources.getImage(config.getWindowIcon())); + } + } + + public void deactivate(@Nullable String message) { + glassPane.activate(message); + } + + public void activate() { + glassPane.deactivate(); + } + + public DesktopWindowManager getWindowManager() { + if (windowManager == null) + initWindowManager(); + + return windowManager; + } + + protected void initWindowManager() { + windowManager = new DesktopWindowManager(this); + } + + public void showNotification(String caption, String description, NotificationType type) { + getWindowManager().showNotification(caption, description, type); + } + + public void showNotification(String caption, NotificationType type) { + getWindowManager().showNotification(caption, type); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/core/entityinspector/EntityInspectorBrowseCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/core/entityinspector/EntityInspectorBrowseCompanion.java index c495ea2c71..00bbbc8f4c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/core/entityinspector/EntityInspectorBrowseCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/core/entityinspector/EntityInspectorBrowseCompanion.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.core.entityinspector; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.app.core.entityinspector.EntityInspectorBrowse; -import com.haulmont.cuba.gui.components.Table; -import org.jdesktop.swingx.JXTable; - -public class EntityInspectorBrowseCompanion implements EntityInspectorBrowse.Companion { - @Override - public void setHorizontalScrollEnabled(Table table, boolean enabled) { - JXTable jxTable = (JXTable) DesktopComponentsHelper.unwrap(table); - jxTable.setHorizontalScrollEnabled(enabled); - } - - @Override - public void setTextSelectionEnabled(Table table, boolean enabled) { - // For desktop coping text from cell works by hotkey - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.core.entityinspector; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.app.core.entityinspector.EntityInspectorBrowse; +import com.haulmont.cuba.gui.components.Table; +import org.jdesktop.swingx.JXTable; + +public class EntityInspectorBrowseCompanion implements EntityInspectorBrowse.Companion { + @Override + public void setHorizontalScrollEnabled(Table table, boolean enabled) { + JXTable jxTable = (JXTable) DesktopComponentsHelper.unwrap(table); + jxTable.setHorizontalScrollEnabled(enabled); + } + + @Override + public void setTextSelectionEnabled(Table table, boolean enabled) { + // For desktop coping text from cell works by hotkey + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/AttributePermissionsFrameCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/AttributePermissionsFrameCompanion.java index e1dd6f4961..09b6c35e1d 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/AttributePermissionsFrameCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/AttributePermissionsFrameCompanion.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.role; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.app.security.entity.AttributePermissionVariant; -import com.haulmont.cuba.gui.app.security.entity.AttributeTarget; -import com.haulmont.cuba.gui.app.security.entity.MultiplePermissionTarget; -import com.haulmont.cuba.gui.app.security.role.edit.tabs.AttributePermissionsFrame; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.Table; - -import javax.swing.*; -import java.util.Iterator; - -public class AttributePermissionsFrameCompanion implements AttributePermissionsFrame.Companion { - @Override - public void initPermissionColoredColumn(final Table propertyPermissionsTable) { - propertyPermissionsTable.addGeneratedColumn("permissionsInfo", new Table.ColumnGenerator() { - @Override - public Component generateCell(MultiplePermissionTarget target) { - Label label = AppConfig.getFactory().createComponent(Label.class); - JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); - - int i = 0; - StringBuilder builder = new StringBuilder(""); - Iterator iterator = target.getPermissions().iterator(); - while (iterator.hasNext() && i < MultiplePermissionTarget.SHOW_PERMISSIONS_COUNT) { - AttributeTarget attributeTarget = iterator.next(); - AttributePermissionVariant permissionVariant = attributeTarget.getPermissionVariant(); - if (permissionVariant != AttributePermissionVariant.NOTSET) { - if (i < MultiplePermissionTarget.SHOW_PERMISSIONS_COUNT - 1) { - if (i > 0) - builder.append(", "); - - builder.append("") - .append(attributeTarget.getId()).append(""); - } else { - builder.append(", ..."); - } - i++; - } - } - builder.append(""); - jLabel.setText(builder.toString()); - - return label; - } - }, Label.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.role; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.app.security.entity.AttributePermissionVariant; +import com.haulmont.cuba.gui.app.security.entity.AttributeTarget; +import com.haulmont.cuba.gui.app.security.entity.MultiplePermissionTarget; +import com.haulmont.cuba.gui.app.security.role.edit.tabs.AttributePermissionsFrame; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.Table; + +import javax.swing.*; +import java.util.Iterator; + +public class AttributePermissionsFrameCompanion implements AttributePermissionsFrame.Companion { + @Override + public void initPermissionColoredColumn(final Table propertyPermissionsTable) { + propertyPermissionsTable.addGeneratedColumn("permissionsInfo", new Table.ColumnGenerator() { + @Override + public Component generateCell(MultiplePermissionTarget target) { + Label label = AppConfig.getFactory().createComponent(Label.class); + JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); + + int i = 0; + StringBuilder builder = new StringBuilder(""); + Iterator iterator = target.getPermissions().iterator(); + while (iterator.hasNext() && i < MultiplePermissionTarget.SHOW_PERMISSIONS_COUNT) { + AttributeTarget attributeTarget = iterator.next(); + AttributePermissionVariant permissionVariant = attributeTarget.getPermissionVariant(); + if (permissionVariant != AttributePermissionVariant.NOTSET) { + if (i < MultiplePermissionTarget.SHOW_PERMISSIONS_COUNT - 1) { + if (i > 0) + builder.append(", "); + + builder.append("") + .append(attributeTarget.getId()).append(""); + } else { + builder.append(", ..."); + } + i++; + } + } + builder.append(""); + jLabel.setText(builder.toString()); + + return label; + } + }, Label.class); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/EntityPermissionsFrameCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/EntityPermissionsFrameCompanion.java index 08f81c0c99..a215e8ca97 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/EntityPermissionsFrameCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/EntityPermissionsFrameCompanion.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.role; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.app.security.entity.OperationPermissionTarget; -import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; -import com.haulmont.cuba.gui.app.security.role.edit.tabs.EntityPermissionsFrame; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.Table; - -import javax.swing.*; - -public class EntityPermissionsFrameCompanion implements EntityPermissionsFrame.Companion { - - protected Messages messages = AppBeans.get(Messages.NAME); - - @Override - public void initPermissionColoredColumns(Table entityPermissionsTable) { - entityPermissionsTable.addGeneratedColumn("createPermissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(OperationPermissionTarget target) { - return generateLabelByPermissionVariant(target.getCreatePermissionVariant()); - } - }, Label.class); - - entityPermissionsTable.addGeneratedColumn("readPermissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(OperationPermissionTarget target) { - return generateLabelByPermissionVariant(target.getReadPermissionVariant()); - } - }, Label.class); - - entityPermissionsTable.addGeneratedColumn("updatePermissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(OperationPermissionTarget target) { - return generateLabelByPermissionVariant(target.getUpdatePermissionVariant()); - } - }, Label.class); - - entityPermissionsTable.addGeneratedColumn("deletePermissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(OperationPermissionTarget target) { - return generateLabelByPermissionVariant(target.getDeletePermissionVariant()); - } - }, Label.class); - } - - protected Label generateLabelByPermissionVariant(PermissionVariant permissionVariant) { - Label label = AppConfig.getFactory().createComponent(Label.class); - JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); - - StringBuilder builder = new StringBuilder(); - - if (permissionVariant != PermissionVariant.NOTSET) { - builder.append(""); - builder.append("") - .append(messages.getMessage(permissionVariant)).append(""); - - builder.append(""); - } - - jLabel.setText(builder.toString()); - - return label; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.role; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.app.security.entity.OperationPermissionTarget; +import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; +import com.haulmont.cuba.gui.app.security.role.edit.tabs.EntityPermissionsFrame; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.Table; + +import javax.swing.*; + +public class EntityPermissionsFrameCompanion implements EntityPermissionsFrame.Companion { + + protected Messages messages = AppBeans.get(Messages.NAME); + + @Override + public void initPermissionColoredColumns(Table entityPermissionsTable) { + entityPermissionsTable.addGeneratedColumn("createPermissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(OperationPermissionTarget target) { + return generateLabelByPermissionVariant(target.getCreatePermissionVariant()); + } + }, Label.class); + + entityPermissionsTable.addGeneratedColumn("readPermissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(OperationPermissionTarget target) { + return generateLabelByPermissionVariant(target.getReadPermissionVariant()); + } + }, Label.class); + + entityPermissionsTable.addGeneratedColumn("updatePermissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(OperationPermissionTarget target) { + return generateLabelByPermissionVariant(target.getUpdatePermissionVariant()); + } + }, Label.class); + + entityPermissionsTable.addGeneratedColumn("deletePermissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(OperationPermissionTarget target) { + return generateLabelByPermissionVariant(target.getDeletePermissionVariant()); + } + }, Label.class); + } + + protected Label generateLabelByPermissionVariant(PermissionVariant permissionVariant) { + Label label = AppConfig.getFactory().createComponent(Label.class); + JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); + + StringBuilder builder = new StringBuilder(); + + if (permissionVariant != PermissionVariant.NOTSET) { + builder.append(""); + builder.append("") + .append(messages.getMessage(permissionVariant)).append(""); + + builder.append(""); + } + + jLabel.setText(builder.toString()); + + return label; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/ScreenPermissionsFrameCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/ScreenPermissionsFrameCompanion.java index a77c9ff505..c693693380 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/ScreenPermissionsFrameCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/ScreenPermissionsFrameCompanion.java @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.role; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.app.security.role.edit.tabs.ScreenPermissionsFrame; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.components.TreeTable; -import com.haulmont.cuba.gui.app.security.entity.BasicPermissionTarget; -import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; - -import javax.swing.*; - -public class ScreenPermissionsFrameCompanion implements ScreenPermissionsFrame.Companion { - - protected Messages messages = AppBeans.get(Messages.NAME); - - @Override - public void initPermissionColoredColumns(TreeTable screenPermissionsTree) { - screenPermissionsTree.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(BasicPermissionTarget entity) { - Label label = AppConfig.getFactory().createComponent(Label.class); - JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); - - StringBuilder builder = new StringBuilder(); - - PermissionVariant permissionVariant = entity.getPermissionVariant(); - - if (permissionVariant != PermissionVariant.NOTSET) { - builder.append(""); - builder.append("") - .append(messages.getMessage(permissionVariant)).append(""); - - builder.append(""); - } - - jLabel.setText(builder.toString()); - - return label; - } - }, Label.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.role; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.app.security.role.edit.tabs.ScreenPermissionsFrame; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.components.TreeTable; +import com.haulmont.cuba.gui.app.security.entity.BasicPermissionTarget; +import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; + +import javax.swing.*; + +public class ScreenPermissionsFrameCompanion implements ScreenPermissionsFrame.Companion { + + protected Messages messages = AppBeans.get(Messages.NAME); + + @Override + public void initPermissionColoredColumns(TreeTable screenPermissionsTree) { + screenPermissionsTree.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(BasicPermissionTarget entity) { + Label label = AppConfig.getFactory().createComponent(Label.class); + JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); + + StringBuilder builder = new StringBuilder(); + + PermissionVariant permissionVariant = entity.getPermissionVariant(); + + if (permissionVariant != PermissionVariant.NOTSET) { + builder.append(""); + builder.append("") + .append(messages.getMessage(permissionVariant)).append(""); + + builder.append(""); + } + + jLabel.setText(builder.toString()); + + return label; + } + }, Label.class); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/SpecificPermissionsFrameCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/SpecificPermissionsFrameCompanion.java index d3b13e445e..50e2522ed6 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/SpecificPermissionsFrameCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/SpecificPermissionsFrameCompanion.java @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.role; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.app.security.role.edit.tabs.SpecificPermissionsFrame; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.components.TreeTable; -import com.haulmont.cuba.gui.app.security.entity.BasicPermissionTarget; -import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; - -import javax.swing.*; - -public class SpecificPermissionsFrameCompanion implements SpecificPermissionsFrame.Companion { - - protected Messages messages = AppBeans.get(Messages.NAME); - - @Override - public void initPermissionColoredColumns(TreeTable specificPermissionsTree) { - specificPermissionsTree.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(BasicPermissionTarget entity) { - Label label = AppConfig.getFactory().createComponent(Label.class); - JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); - - StringBuilder builder = new StringBuilder(); - - PermissionVariant permissionVariant = entity.getPermissionVariant(); - - if (permissionVariant != PermissionVariant.NOTSET) { - builder.append(""); - builder.append("") - .append(messages.getMessage(permissionVariant)).append(""); - - builder.append(""); - } - - jLabel.setText(builder.toString()); - - return label; - } - }, Label.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.role; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.app.security.role.edit.tabs.SpecificPermissionsFrame; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.components.TreeTable; +import com.haulmont.cuba.gui.app.security.entity.BasicPermissionTarget; +import com.haulmont.cuba.gui.app.security.entity.PermissionVariant; + +import javax.swing.*; + +public class SpecificPermissionsFrameCompanion implements SpecificPermissionsFrame.Companion { + + protected Messages messages = AppBeans.get(Messages.NAME); + + @Override + public void initPermissionColoredColumns(TreeTable specificPermissionsTree) { + specificPermissionsTree.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(BasicPermissionTarget entity) { + Label label = AppConfig.getFactory().createComponent(Label.class); + JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); + + StringBuilder builder = new StringBuilder(); + + PermissionVariant permissionVariant = entity.getPermissionVariant(); + + if (permissionVariant != PermissionVariant.NOTSET) { + builder.append(""); + builder.append("") + .append(messages.getMessage(permissionVariant)).append(""); + + builder.append(""); + } + + jLabel.setText(builder.toString()); + + return label; + } + }, Label.class); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/UiPermissionsFrameCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/UiPermissionsFrameCompanion.java index ba2ce78874..3cf3402ccc 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/UiPermissionsFrameCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/role/UiPermissionsFrameCompanion.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.role; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.app.security.role.edit.tabs.UiPermissionsFrame; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.app.security.entity.UiPermissionTarget; -import com.haulmont.cuba.gui.app.security.entity.UiPermissionVariant; - -import javax.swing.*; - -public class UiPermissionsFrameCompanion implements UiPermissionsFrame.Companion { - - protected Messages messages = AppBeans.get(Messages.NAME); - - @Override - public void initPermissionsColoredColumns(Table uiPermissionsTable) { - uiPermissionsTable.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { - @Override - public Component generateCell(UiPermissionTarget entity) { - Label label = AppConfig.getFactory().createComponent(Label.class); - JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); - - StringBuilder builder = new StringBuilder(); - - UiPermissionVariant permissionVariant = entity.getPermissionVariant(); - - if (permissionVariant != UiPermissionVariant.NOTSET) { - builder.append(""); - builder.append("") - .append(messages.getMessage(permissionVariant)).append(""); - - builder.append(""); - } - - jLabel.setText(builder.toString()); - - return label; - } - }, Label.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.role; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.app.security.role.edit.tabs.UiPermissionsFrame; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.app.security.entity.UiPermissionTarget; +import com.haulmont.cuba.gui.app.security.entity.UiPermissionVariant; + +import javax.swing.*; + +public class UiPermissionsFrameCompanion implements UiPermissionsFrame.Companion { + + protected Messages messages = AppBeans.get(Messages.NAME); + + @Override + public void initPermissionsColoredColumns(Table uiPermissionsTable) { + uiPermissionsTable.addGeneratedColumn("permissionVariant", new Table.ColumnGenerator() { + @Override + public Component generateCell(UiPermissionTarget entity) { + Label label = AppConfig.getFactory().createComponent(Label.class); + JLabel jLabel = (JLabel) DesktopComponentsHelper.unwrap(label); + + StringBuilder builder = new StringBuilder(); + + UiPermissionVariant permissionVariant = entity.getPermissionVariant(); + + if (permissionVariant != UiPermissionVariant.NOTSET) { + builder.append(""); + builder.append("") + .append(messages.getMessage(permissionVariant)).append(""); + + builder.append(""); + } + + jLabel.setText(builder.toString()); + + return label; + } + }, Label.class); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/user/ChangePasswordLauncher.java b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/user/ChangePasswordLauncher.java index 850a5f43e5..630cc14a07 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/app/security/user/ChangePasswordLauncher.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/app/security/user/ChangePasswordLauncher.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.app.security.user; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.WindowManager.OpenType; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.gui.config.WindowInfo; - -public class ChangePasswordLauncher implements Runnable { - @Override - public void run() { - WindowManager wm = App.getInstance().getMainFrame().getWindowManager(); - - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - WindowInfo windowInfo = windowConfig.getWindowInfo("sec$User.changePassword"); - - wm.openWindow(windowInfo, OpenType.DIALOG, ParamsMap.of("currentPasswordRequired", true)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.app.security.user; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.WindowManager.OpenType; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.gui.config.WindowInfo; + +public class ChangePasswordLauncher implements Runnable { + @Override + public void run() { + WindowManager wm = App.getInstance().getMainFrame().getWindowManager(); + + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + WindowInfo windowInfo = windowConfig.getWindowInfo("sec$User.changePassword"); + + wm.openWindow(windowInfo, OpenType.DIALOG, ParamsMap.of("currentPasswordRequired", true)); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/desktop-theme.xsd b/modules/desktop/src/com/haulmont/cuba/desktop/desktop-theme.xsd index 8d9f61c6bc..c1098ecd80 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/desktop-theme.xsd +++ b/modules/desktop/src/com/haulmont/cuba/desktop/desktop-theme.xsd @@ -1,147 +1,147 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/AWTExceptionHandler.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/AWTExceptionHandler.java index db0dd588b6..08716e9362 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/AWTExceptionHandler.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/AWTExceptionHandler.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -import com.haulmont.cuba.desktop.App; - -public class AWTExceptionHandler { - - public void handle(Throwable throwable) { - App.getInstance().handleException(Thread.currentThread(), throwable); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +import com.haulmont.cuba.desktop.App; + +public class AWTExceptionHandler { + + public void handle(Throwable throwable) { + App.getInstance().handleException(Thread.currentThread(), throwable); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/AbstractExceptionHandler.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/AbstractExceptionHandler.java index c434588a4d..04003ae7aa 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/AbstractExceptionHandler.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/AbstractExceptionHandler.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -import com.haulmont.cuba.core.global.RemoteException; -import org.apache.commons.lang.exception.ExceptionUtils; - -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; - -/** - * Base class for exception handlers determining their ability to handle an exception by its class name and optional - * implementation of {@link #canHandle(String, String, Throwable)} method. - * - *

If you need to handle a specific exception, create a descendant of this class, - * pass handling exception class names into constructor, implement - * {@link #doHandle(Thread, String, String, Throwable)} method - * and register the new handler in the definition of {@link ExceptionHandlersConfiguration} bean in the client's - * spring.xml. - * - */ -public abstract class AbstractExceptionHandler implements ExceptionHandler { - - private List classNames; - - protected AbstractExceptionHandler(String... classNames) { - this.classNames = Arrays.asList(classNames); - } - - @Override - public boolean handle(Thread thread, Throwable exception) { - //noinspection unchecked - List list = ExceptionUtils.getThrowableList(exception); - for (Throwable throwable : list) { - if (classNames.contains(throwable.getClass().getName()) - && canHandle(throwable.getClass().getName(), throwable.getMessage(), throwable)) { - doHandle(thread, throwable.getClass().getName(), throwable.getMessage(), throwable); - return true; - } - if (throwable instanceof RemoteException) { - RemoteException remoteException = (RemoteException) throwable; - for (RemoteException.Cause cause : remoteException.getCauses()) { - if (classNames.contains(cause.getClassName()) - && canHandle(throwable.getClass().getName(), throwable.getMessage(), throwable)) { - doHandle(thread, cause.getClassName(), cause.getMessage(), cause.getThrowable()); - return true; - } - } - } - } - return false; - } - - /** - * Should be implemented in subclasses if the exception class name is not enough to determine the ability to - * handle the exception. - * - * @param className exception class name - * @param message exception message - * @param throwable exception instance. Can be null if the exception occured on the server side and this - * exception class isn't accessible by the client. - * @return true if the exception can be handled by this handler - */ - protected boolean canHandle(String className, String message, @Nullable Throwable throwable) { - return true; - } - - /** - * Perform exception handling. - * - * @param thread current thread - * @param className actual exception class name - * @param message exception message - * @param throwable exception instance. Can be null if the exception occured on the server side and this - * exception class isn't accessible by the client. - */ - protected abstract void doHandle(Thread thread, String className, String message, @Nullable Throwable throwable); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +import com.haulmont.cuba.core.global.RemoteException; +import org.apache.commons.lang.exception.ExceptionUtils; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + +/** + * Base class for exception handlers determining their ability to handle an exception by its class name and optional + * implementation of {@link #canHandle(String, String, Throwable)} method. + * + *

If you need to handle a specific exception, create a descendant of this class, + * pass handling exception class names into constructor, implement + * {@link #doHandle(Thread, String, String, Throwable)} method + * and register the new handler in the definition of {@link ExceptionHandlersConfiguration} bean in the client's + * spring.xml. + * + */ +public abstract class AbstractExceptionHandler implements ExceptionHandler { + + private List classNames; + + protected AbstractExceptionHandler(String... classNames) { + this.classNames = Arrays.asList(classNames); + } + + @Override + public boolean handle(Thread thread, Throwable exception) { + //noinspection unchecked + List list = ExceptionUtils.getThrowableList(exception); + for (Throwable throwable : list) { + if (classNames.contains(throwable.getClass().getName()) + && canHandle(throwable.getClass().getName(), throwable.getMessage(), throwable)) { + doHandle(thread, throwable.getClass().getName(), throwable.getMessage(), throwable); + return true; + } + if (throwable instanceof RemoteException) { + RemoteException remoteException = (RemoteException) throwable; + for (RemoteException.Cause cause : remoteException.getCauses()) { + if (classNames.contains(cause.getClassName()) + && canHandle(throwable.getClass().getName(), throwable.getMessage(), throwable)) { + doHandle(thread, cause.getClassName(), cause.getMessage(), cause.getThrowable()); + return true; + } + } + } + } + return false; + } + + /** + * Should be implemented in subclasses if the exception class name is not enough to determine the ability to + * handle the exception. + * + * @param className exception class name + * @param message exception message + * @param throwable exception instance. Can be null if the exception occured on the server side and this + * exception class isn't accessible by the client. + * @return true if the exception can be handled by this handler + */ + protected boolean canHandle(String className, String message, @Nullable Throwable throwable) { + return true; + } + + /** + * Perform exception handling. + * + * @param thread current thread + * @param className actual exception class name + * @param message exception message + * @param throwable exception instance. Can be null if the exception occured on the server side and this + * exception class isn't accessible by the client. + */ + protected abstract void doHandle(Thread thread, String className, String message, @Nullable Throwable throwable); +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/DefaultExceptionHandler.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/DefaultExceptionHandler.java index f6ed3c775b..542ead2e40 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/DefaultExceptionHandler.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/DefaultExceptionHandler.java @@ -1,152 +1,152 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.sys.DialogWindow; -import com.haulmont.cuba.desktop.sys.JXErrorPaneExt; -import com.haulmont.cuba.gui.GuiDevelopmentException; -import com.haulmont.cuba.gui.config.WindowConfig; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.jdesktop.swingx.JXErrorPane; -import org.jdesktop.swingx.error.ErrorInfo; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.LinkedHashMap; -import java.util.Map; - -public class DefaultExceptionHandler implements ExceptionHandler { - - @Override - public boolean handle(Thread thread, Throwable exception) { - JXErrorPane errorPane = new JXErrorPaneExt(); - - errorPane.setErrorInfo(createErrorInfo(exception)); - JDialog dialog = JXErrorPane.createDialog(App.getInstance().getMainFrame(), errorPane); - dialog.setMinimumSize(new Dimension(600, (int) dialog.getMinimumSize().getHeight())); - - final DialogWindow lastDialogWindow = getLastDialogWindow(); - dialog.addWindowListener( - new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - if (lastDialogWindow != null) - lastDialogWindow.enableWindow(); - else - App.getInstance().getMainFrame().activate(); - } - } - ); - dialog.setModal(false); - - if (lastDialogWindow != null) - lastDialogWindow.disableWindow(null); - else - App.getInstance().getMainFrame().deactivate(null); - - dialog.setVisible(true); - return true; - } - - protected ErrorInfo createErrorInfo(Throwable exception) { - UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - Security security = AppBeans.get(Security.NAME); - if (userSessionSource.getUserSession() == null - || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { - return new ErrorInfo( - getMessage("errorPane.title"), getMessage("exceptionDialog.contactAdmin"), - null, null, null, null, null); - } - - Throwable rootCause = ExceptionUtils.getRootCause(exception); - if (rootCause == null) - rootCause = exception; - - StringBuilder msg = new StringBuilder(); - if (rootCause instanceof RemoteException) { - RemoteException re = (RemoteException) rootCause; - if (!re.getCauses().isEmpty()) { - RemoteException.Cause cause = re.getCauses().get(re.getCauses().size() - 1); - if (cause.getThrowable() != null) - rootCause = cause.getThrowable(); - else { - // root cause is not supported by client - String className = cause.getClassName(); - if (className != null && className.indexOf('.') > 0) { - className = className.substring(className.lastIndexOf('.') + 1); - } - msg.append(className).append(": ").append(cause.getMessage()); - } - } - } - - if (msg.length() == 0) { - msg.append(rootCause.getClass().getSimpleName()); - if (!StringUtils.isBlank(rootCause.getMessage())) - msg.append(": ").append(rootCause.getMessage()); - - if (rootCause instanceof DevelopmentException) { - Map params = new LinkedHashMap<>(); - if (rootCause instanceof GuiDevelopmentException) { - GuiDevelopmentException guiDevException = (GuiDevelopmentException) rootCause; - if (guiDevException.getFrameId() != null) { - params.put("Frame ID", guiDevException.getFrameId()); - try { - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - params.put("XML descriptor", - windowConfig.getWindowInfo(guiDevException.getFrameId()).getTemplate()); - } catch (Exception e) { - params.put("XML descriptor", "not found for " + guiDevException.getFrameId()); - } - } - } - params.putAll(((DevelopmentException) rootCause).getParams()); - - if (!params.isEmpty()) { - msg.append("\n\n"); - for (Map.Entry entry : params.entrySet()) { - msg.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } - } - } - } - - return new ErrorInfo( - getMessage("errorPane.title"), msg.toString(), - null, null, rootCause, null, null); - } - - private DialogWindow getLastDialogWindow() { - try { - return App.getInstance().getMainFrame().getWindowManager().getLastDialogWindow(); - } catch (Exception e) { - // this may happen in case of initialization error - return null; - } - } - - protected String getMessage(String key) { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage(key, App.getInstance().getLocale()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.sys.DialogWindow; +import com.haulmont.cuba.desktop.sys.JXErrorPaneExt; +import com.haulmont.cuba.gui.GuiDevelopmentException; +import com.haulmont.cuba.gui.config.WindowConfig; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.jdesktop.swingx.JXErrorPane; +import org.jdesktop.swingx.error.ErrorInfo; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.LinkedHashMap; +import java.util.Map; + +public class DefaultExceptionHandler implements ExceptionHandler { + + @Override + public boolean handle(Thread thread, Throwable exception) { + JXErrorPane errorPane = new JXErrorPaneExt(); + + errorPane.setErrorInfo(createErrorInfo(exception)); + JDialog dialog = JXErrorPane.createDialog(App.getInstance().getMainFrame(), errorPane); + dialog.setMinimumSize(new Dimension(600, (int) dialog.getMinimumSize().getHeight())); + + final DialogWindow lastDialogWindow = getLastDialogWindow(); + dialog.addWindowListener( + new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + if (lastDialogWindow != null) + lastDialogWindow.enableWindow(); + else + App.getInstance().getMainFrame().activate(); + } + } + ); + dialog.setModal(false); + + if (lastDialogWindow != null) + lastDialogWindow.disableWindow(null); + else + App.getInstance().getMainFrame().deactivate(null); + + dialog.setVisible(true); + return true; + } + + protected ErrorInfo createErrorInfo(Throwable exception) { + UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + Security security = AppBeans.get(Security.NAME); + if (userSessionSource.getUserSession() == null + || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { + return new ErrorInfo( + getMessage("errorPane.title"), getMessage("exceptionDialog.contactAdmin"), + null, null, null, null, null); + } + + Throwable rootCause = ExceptionUtils.getRootCause(exception); + if (rootCause == null) + rootCause = exception; + + StringBuilder msg = new StringBuilder(); + if (rootCause instanceof RemoteException) { + RemoteException re = (RemoteException) rootCause; + if (!re.getCauses().isEmpty()) { + RemoteException.Cause cause = re.getCauses().get(re.getCauses().size() - 1); + if (cause.getThrowable() != null) + rootCause = cause.getThrowable(); + else { + // root cause is not supported by client + String className = cause.getClassName(); + if (className != null && className.indexOf('.') > 0) { + className = className.substring(className.lastIndexOf('.') + 1); + } + msg.append(className).append(": ").append(cause.getMessage()); + } + } + } + + if (msg.length() == 0) { + msg.append(rootCause.getClass().getSimpleName()); + if (!StringUtils.isBlank(rootCause.getMessage())) + msg.append(": ").append(rootCause.getMessage()); + + if (rootCause instanceof DevelopmentException) { + Map params = new LinkedHashMap<>(); + if (rootCause instanceof GuiDevelopmentException) { + GuiDevelopmentException guiDevException = (GuiDevelopmentException) rootCause; + if (guiDevException.getFrameId() != null) { + params.put("Frame ID", guiDevException.getFrameId()); + try { + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + params.put("XML descriptor", + windowConfig.getWindowInfo(guiDevException.getFrameId()).getTemplate()); + } catch (Exception e) { + params.put("XML descriptor", "not found for " + guiDevException.getFrameId()); + } + } + } + params.putAll(((DevelopmentException) rootCause).getParams()); + + if (!params.isEmpty()) { + msg.append("\n\n"); + for (Map.Entry entry : params.entrySet()) { + msg.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } + } + } + + return new ErrorInfo( + getMessage("errorPane.title"), msg.toString(), + null, null, rootCause, null, null); + } + + private DialogWindow getLastDialogWindow() { + try { + return App.getInstance().getMainFrame().getWindowManager().getLastDialogWindow(); + } catch (Exception e) { + // this may happen in case of initialization error + return null; + } + } + + protected String getMessage(String key) { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage(key, App.getInstance().getLocale()); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandler.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandler.java index 9fe21a241c..283f4123d5 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandler.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandler.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -/** - * Interface of all unhandled exception handlers in desktop UI
- */ -public interface ExceptionHandler { - - /** - * Handles exception if can - * - * @param thread thread - * @param exception exception - * @return true if the exception has been handled, false otherwise - */ - boolean handle(Thread thread, Throwable exception); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +/** + * Interface of all unhandled exception handlers in desktop UI
+ */ +public interface ExceptionHandler { + + /** + * Handles exception if can + * + * @param thread thread + * @param exception exception + * @return true if the exception has been handled, false otherwise + */ + boolean handle(Thread thread, Throwable exception); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandlers.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandlers.java index 8db198b558..aa4af6e8e1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandlers.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/ExceptionHandlers.java @@ -1,160 +1,160 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.desktop.sys.DesktopWindowManager; -import com.haulmont.cuba.gui.exception.GenericExceptionHandler; -import com.haulmont.cuba.gui.exception.SilentExceptionHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.OrderComparator; - -import org.springframework.stereotype.Component; -import java.util.*; - -/** - * Class that holds the collection of exception handlers and delegates unhandled exception processing to them. Handlers - * form the chain of responsibility. - * - *

A set of exception handlers is configured by defining ExceptionHandlersConfiguration beans - * in spring.xml. If a project needs specific handlers, it should define a bean of such type with its own - * id, e.g. refapp_ExceptionHandlersConfiguration

- */ -@Component("cuba_ExceptionHandlers") -public class ExceptionHandlers { - - private final Logger log = LoggerFactory.getLogger(ExceptionHandlers.class); - - protected LinkedList handlers = new LinkedList<>(); - - protected LinkedList genericHandlers = new LinkedList<>(); - - protected ExceptionHandler defaultHandler; - - public ExceptionHandlers() { - this.defaultHandler = new DefaultExceptionHandler(); - createMinimalSet(); - } - - /** - * @return default exception handler which is used when none of registered handlers have handled an exception - */ - public ExceptionHandler getDefaultHandler() { - return defaultHandler; - } - - /** - * Set the default handler instead of initialized in constructor. - * @param defaultHandler default handler instance - */ - public void setDefaultHandler(ExceptionHandler defaultHandler) { - this.defaultHandler = defaultHandler; - } - - /** - * Adds new Web-level handler if it is not yet registered. - * @param handler handler instance - */ - public void addHandler(ExceptionHandler handler) { - if (!handlers.contains(handler)) - handlers.add(handler); - } - - /** - * Adds new GUI-level handler if it is not yet registered. - * @param handler handler instance - */ - private void addHandler(GenericExceptionHandler handler) { - if (!genericHandlers.contains(handler)) - genericHandlers.add(handler); - } - - /** - * Delegates exception handling to registered handlers. - * @param thread current thread - * @param exception exception instance - * @param windowManager - */ - public void handle(Thread thread, Throwable exception, DesktopWindowManager windowManager) { - for (ExceptionHandler handler : handlers) { - if (handler.handle(thread, exception)) - return; - } - for (GenericExceptionHandler handler : genericHandlers) { - if (handler.handle(exception, windowManager)) - return; - } - defaultHandler.handle(thread, exception); - } - - /** - * Create all handlers defined by ExceptionHandlersConfiguration beans in spring.xml and - * GUI handlers defined as Spring-beans. - */ - public void createByConfiguration() { - removeAll(); - - // Desktop handlers - Map map = AppBeans.getAll(ExceptionHandlersConfiguration.class); - - // Project-level handlers must run before platform-level - List configurations = new ArrayList<>(map.values()); - Collections.reverse(configurations); - - for (ExceptionHandlersConfiguration conf : configurations) { - for (Class aClass : conf.getHandlerClasses()) { - try { - handlers.add(ReflectionHelper.newInstance(aClass)); - } catch (NoSuchMethodException e) { - log.error("Unable to instantiate " + aClass, e); - } - } - } - - // GUI handlers - Map handlerMap = AppBeans.getAll(GenericExceptionHandler.class); - - List handlers = new ArrayList<>(handlerMap.values()); - Collections.sort(handlers, new OrderComparator()); - - for (GenericExceptionHandler handler : handlers) { - addHandler(handler); - } - } - - /** - * Create a minimal set of handlers for disconnected client. - */ - public void createMinimalSet() { - removeAll(); - addHandler(new SilentExceptionHandler()); - addHandler(new EntitySerializationExceptionHandler()); - addHandler(new ConnectExceptionHandler()); - addHandler(new IllegalComponentStateExceptionHandler()); - } - - /** - * Remove all handlers. - */ - public void removeAll() { - handlers.clear(); - genericHandlers.clear(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.desktop.sys.DesktopWindowManager; +import com.haulmont.cuba.gui.exception.GenericExceptionHandler; +import com.haulmont.cuba.gui.exception.SilentExceptionHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.OrderComparator; + +import org.springframework.stereotype.Component; +import java.util.*; + +/** + * Class that holds the collection of exception handlers and delegates unhandled exception processing to them. Handlers + * form the chain of responsibility. + * + *

A set of exception handlers is configured by defining ExceptionHandlersConfiguration beans + * in spring.xml. If a project needs specific handlers, it should define a bean of such type with its own + * id, e.g. refapp_ExceptionHandlersConfiguration

+ */ +@Component("cuba_ExceptionHandlers") +public class ExceptionHandlers { + + private final Logger log = LoggerFactory.getLogger(ExceptionHandlers.class); + + protected LinkedList handlers = new LinkedList<>(); + + protected LinkedList genericHandlers = new LinkedList<>(); + + protected ExceptionHandler defaultHandler; + + public ExceptionHandlers() { + this.defaultHandler = new DefaultExceptionHandler(); + createMinimalSet(); + } + + /** + * @return default exception handler which is used when none of registered handlers have handled an exception + */ + public ExceptionHandler getDefaultHandler() { + return defaultHandler; + } + + /** + * Set the default handler instead of initialized in constructor. + * @param defaultHandler default handler instance + */ + public void setDefaultHandler(ExceptionHandler defaultHandler) { + this.defaultHandler = defaultHandler; + } + + /** + * Adds new Web-level handler if it is not yet registered. + * @param handler handler instance + */ + public void addHandler(ExceptionHandler handler) { + if (!handlers.contains(handler)) + handlers.add(handler); + } + + /** + * Adds new GUI-level handler if it is not yet registered. + * @param handler handler instance + */ + private void addHandler(GenericExceptionHandler handler) { + if (!genericHandlers.contains(handler)) + genericHandlers.add(handler); + } + + /** + * Delegates exception handling to registered handlers. + * @param thread current thread + * @param exception exception instance + * @param windowManager + */ + public void handle(Thread thread, Throwable exception, DesktopWindowManager windowManager) { + for (ExceptionHandler handler : handlers) { + if (handler.handle(thread, exception)) + return; + } + for (GenericExceptionHandler handler : genericHandlers) { + if (handler.handle(exception, windowManager)) + return; + } + defaultHandler.handle(thread, exception); + } + + /** + * Create all handlers defined by ExceptionHandlersConfiguration beans in spring.xml and + * GUI handlers defined as Spring-beans. + */ + public void createByConfiguration() { + removeAll(); + + // Desktop handlers + Map map = AppBeans.getAll(ExceptionHandlersConfiguration.class); + + // Project-level handlers must run before platform-level + List configurations = new ArrayList<>(map.values()); + Collections.reverse(configurations); + + for (ExceptionHandlersConfiguration conf : configurations) { + for (Class aClass : conf.getHandlerClasses()) { + try { + handlers.add(ReflectionHelper.newInstance(aClass)); + } catch (NoSuchMethodException e) { + log.error("Unable to instantiate " + aClass, e); + } + } + } + + // GUI handlers + Map handlerMap = AppBeans.getAll(GenericExceptionHandler.class); + + List handlers = new ArrayList<>(handlerMap.values()); + Collections.sort(handlers, new OrderComparator()); + + for (GenericExceptionHandler handler : handlers) { + addHandler(handler); + } + } + + /** + * Create a minimal set of handlers for disconnected client. + */ + public void createMinimalSet() { + removeAll(); + addHandler(new SilentExceptionHandler()); + addHandler(new EntitySerializationExceptionHandler()); + addHandler(new ConnectExceptionHandler()); + addHandler(new IllegalComponentStateExceptionHandler()); + } + + /** + * Remove all handlers. + */ + public void removeAll() { + handlers.clear(); + genericHandlers.clear(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/exception/NoUserSessionHandler.java b/modules/desktop/src/com/haulmont/cuba/desktop/exception/NoUserSessionHandler.java index dc2a0bed7a..3fa5190b72 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/exception/NoUserSessionHandler.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/exception/NoUserSessionHandler.java @@ -1,97 +1,97 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.exception; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.security.global.NoUserSessionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; - -/** - * Handles {@link NoUserSessionException}. - * - */ -public class NoUserSessionHandler extends AbstractExceptionHandler { - - private static Logger log = LoggerFactory.getLogger(NoUserSessionHandler.class); - - private boolean fired; - - public NoUserSessionHandler() { - super(NoUserSessionException.class.getName()); - } - - @Override - protected void doHandle(Thread thread, String className, String message, @Nullable Throwable throwable) { - if (fired) // This handler should fire only once in a session - return; - - try { - App.getInstance().getMainFrame().getWindowManager().showOptionDialog( - getMessage("dialogs.Information"), - getMessage("noUserSession.message"), - Frame.MessageType.CONFIRMATION, - new Action[] { - new LoginAction(), - new ExitAction() - } - ); - fired = true; - } catch (Throwable th) { - log.error("Error handling exception", th); - } - } - - protected String getMessage(String key) { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage(key, App.getInstance().getLocale()); - } - - private class LoginAction extends DialogAction { - protected LoginAction() { - super(DialogAction.Type.OK, Status.PRIMARY); - } - - @Override - public void actionPerform(Component component) { - App app = App.getInstance(); - app.getConnection().logout(); - } - } - - private class ExitAction extends AbstractAction { - protected ExitAction() { - super("exit"); - } - - @Override - public void actionPerform(Component component) { - System.exit(0); - } - - @Override - public String getCaption() { - return getMessage("noUserSession.exit"); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.exception; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.security.global.NoUserSessionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; + +/** + * Handles {@link NoUserSessionException}. + * + */ +public class NoUserSessionHandler extends AbstractExceptionHandler { + + private static Logger log = LoggerFactory.getLogger(NoUserSessionHandler.class); + + private boolean fired; + + public NoUserSessionHandler() { + super(NoUserSessionException.class.getName()); + } + + @Override + protected void doHandle(Thread thread, String className, String message, @Nullable Throwable throwable) { + if (fired) // This handler should fire only once in a session + return; + + try { + App.getInstance().getMainFrame().getWindowManager().showOptionDialog( + getMessage("dialogs.Information"), + getMessage("noUserSession.message"), + Frame.MessageType.CONFIRMATION, + new Action[] { + new LoginAction(), + new ExitAction() + } + ); + fired = true; + } catch (Throwable th) { + log.error("Error handling exception", th); + } + } + + protected String getMessage(String key) { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage(key, App.getInstance().getLocale()); + } + + private class LoginAction extends DialogAction { + protected LoginAction() { + super(DialogAction.Type.OK, Status.PRIMARY); + } + + @Override + public void actionPerform(Component component) { + App app = App.getInstance(); + app.getConnection().logout(); + } + } + + private class ExitAction extends AbstractAction { + protected ExitAction() { + super("exit"); + } + + @Override + public void actionPerform(Component component) { + System.exit(0); + } + + @Override + public String getCaption() { + return getMessage("noUserSession.exit"); + } + } +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopComponentsFactory.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopComponentsFactory.java index f396e410a1..a1bf7d471b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopComponentsFactory.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopComponentsFactory.java @@ -1,146 +1,146 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui; - -import com.haulmont.cuba.core.global.DevelopmentException; -import com.haulmont.cuba.desktop.gui.components.*; -import com.haulmont.cuba.gui.ComponentPalette; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -@org.springframework.stereotype.Component(ComponentsFactory.NAME) -public class DesktopComponentsFactory implements ComponentsFactory { - - private static Map> classes = new HashMap<>(); - - private static Map names = new ConcurrentHashMap<>(); - - static { - classes.put(Window.NAME, DesktopWindow.class); - classes.put(Window.Editor.NAME, DesktopWindow.Editor.class); - classes.put(Window.Lookup.NAME, DesktopWindow.Lookup.class); - - classes.put(Frame.NAME, DesktopFrame.class); - classes.put(HBoxLayout.NAME, DesktopHBox.class); - classes.put(VBoxLayout.NAME, DesktopVBox.class); - classes.put(GridLayout.NAME, DesktopGridLayout.class); - classes.put(ScrollBoxLayout.NAME, DesktopScrollBoxLayout.class); - classes.put(SplitPanel.NAME, DesktopSplitPanel.class); - - classes.put(Button.NAME, DesktopButton.class); - classes.put(LinkButton.NAME, DesktopLinkButton.class); - classes.put(Label.NAME, DesktopLabel.class); - classes.put(CheckBox.NAME, DesktopCheckBox.class); - classes.put(Link.NAME, DesktopLink.class); - - //Use resizable text area instead of text field - classes.put(ResizableTextArea.NAME, DesktopResizableTextArea.class); - classes.put(SourceCodeEditor.NAME, DesktopSourceCodeEditor.class); - classes.put(PasswordField.NAME, DesktopPasswordField.class); - classes.put(TextField.NAME, DesktopTextField.class); - - classes.put(DateField.NAME, DesktopDateField.class); - classes.put(Table.NAME, DesktopTable.class); - classes.put(GroupTable.NAME, DesktopGroupTable.class); - classes.put(Tree.NAME, DesktopTree.class); - classes.put(TreeTable.NAME, DesktopTreeTable.class); - classes.put(ButtonsPanel.NAME, DesktopButtonsPanel.class); - classes.put(Filter.NAME, DesktopFilter.class); - classes.put(FieldGroup.NAME, DesktopFieldGroup.class); - classes.put(RowsCount.NAME, DesktopRowsCount.class); - classes.put(PopupButton.NAME, DesktopPopupButton.class); - classes.put(LookupField.NAME, DesktopLookupField.class); - classes.put(PickerField.NAME, DesktopPickerField.class); - classes.put(SuggestionField.NAME, DesktopSuggestionField.class); - classes.put(SuggestionPickerField.NAME, DesktopSuggestionPickerField.class); - classes.put(LookupPickerField.NAME, DesktopLookupPickerField.class); - classes.put(MaskedField.NAME, DesktopMaskedField.class); - classes.put(CurrencyField.NAME, DesktopCurrencyField.class); - - classes.put(SearchField.NAME, DesktopSearchField.class); - classes.put(SearchPickerField.NAME, DesktopSearchPickerField.class); - - classes.put(OptionsGroup.NAME, DesktopOptionsGroup.class); - classes.put(FileUploadField.NAME, DesktopFileUploadField.class); - classes.put(FileMultiUploadField.NAME, DesktopFileMultiUploadField.class); - classes.put(TabSheet.NAME, DesktopTabSheet.class); - classes.put(Embedded.NAME, DesktopEmbedded.class); - classes.put(WidgetsTree.NAME, DesktopWidgetsTree.class); - classes.put(GroupBoxLayout.NAME, DesktopGroupBox.class); - classes.put(ProgressBar.NAME, DesktopProgressBar.class); - classes.put(TimeField.NAME, DesktopTimeField.class); - classes.put(TokenList.NAME, DesktopTokenList.class); - classes.put(RelatedEntities.NAME, DesktopRelatedEntities.class); - classes.put(BulkEditor.NAME, DesktopBulkEditor.class); - classes.put(ListEditor.NAME, DesktopListEditor.class); - } - - public static void registerComponent(String element, Class componentClass) { - classes.put(element, componentClass); - } - - public static void registerComponents(ComponentPalette... palettes) { - for (ComponentPalette palette : palettes) { - Map> loaders = palette.getComponents(); - for (Map.Entry> loaderEntry : loaders.entrySet()) { - classes.put(loaderEntry.getKey(), loaderEntry.getValue()); - } - } - } - - @Override - public Component createComponent(String name) { - final Class componentClass = classes.get(name); - if (componentClass == null) { - throw new IllegalStateException(String.format("Can't find component class for '%s'", name)); - } - - try { - return componentClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Error creating the '" + name + "' component instance", e); - } - } - - @Override - public T createComponent(Class type) { - String name = names.get(type); - if (name == null) { - java.lang.reflect.Field nameField; - try { - nameField = type.getField("NAME"); - name = (String) nameField.get(null); - } catch (NoSuchFieldException | IllegalAccessException ignore) { - } - if (name == null) - throw new DevelopmentException(String.format("Class '%s' doesn't have NAME field", type.getName())); - else - names.put(type, name); - } - return type.cast(createComponent(name)); - } - - @Override - public Timer createTimer() { - return new DesktopTimer(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui; + +import com.haulmont.cuba.core.global.DevelopmentException; +import com.haulmont.cuba.desktop.gui.components.*; +import com.haulmont.cuba.gui.ComponentPalette; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@org.springframework.stereotype.Component(ComponentsFactory.NAME) +public class DesktopComponentsFactory implements ComponentsFactory { + + private static Map> classes = new HashMap<>(); + + private static Map names = new ConcurrentHashMap<>(); + + static { + classes.put(Window.NAME, DesktopWindow.class); + classes.put(Window.Editor.NAME, DesktopWindow.Editor.class); + classes.put(Window.Lookup.NAME, DesktopWindow.Lookup.class); + + classes.put(Frame.NAME, DesktopFrame.class); + classes.put(HBoxLayout.NAME, DesktopHBox.class); + classes.put(VBoxLayout.NAME, DesktopVBox.class); + classes.put(GridLayout.NAME, DesktopGridLayout.class); + classes.put(ScrollBoxLayout.NAME, DesktopScrollBoxLayout.class); + classes.put(SplitPanel.NAME, DesktopSplitPanel.class); + + classes.put(Button.NAME, DesktopButton.class); + classes.put(LinkButton.NAME, DesktopLinkButton.class); + classes.put(Label.NAME, DesktopLabel.class); + classes.put(CheckBox.NAME, DesktopCheckBox.class); + classes.put(Link.NAME, DesktopLink.class); + + //Use resizable text area instead of text field + classes.put(ResizableTextArea.NAME, DesktopResizableTextArea.class); + classes.put(SourceCodeEditor.NAME, DesktopSourceCodeEditor.class); + classes.put(PasswordField.NAME, DesktopPasswordField.class); + classes.put(TextField.NAME, DesktopTextField.class); + + classes.put(DateField.NAME, DesktopDateField.class); + classes.put(Table.NAME, DesktopTable.class); + classes.put(GroupTable.NAME, DesktopGroupTable.class); + classes.put(Tree.NAME, DesktopTree.class); + classes.put(TreeTable.NAME, DesktopTreeTable.class); + classes.put(ButtonsPanel.NAME, DesktopButtonsPanel.class); + classes.put(Filter.NAME, DesktopFilter.class); + classes.put(FieldGroup.NAME, DesktopFieldGroup.class); + classes.put(RowsCount.NAME, DesktopRowsCount.class); + classes.put(PopupButton.NAME, DesktopPopupButton.class); + classes.put(LookupField.NAME, DesktopLookupField.class); + classes.put(PickerField.NAME, DesktopPickerField.class); + classes.put(SuggestionField.NAME, DesktopSuggestionField.class); + classes.put(SuggestionPickerField.NAME, DesktopSuggestionPickerField.class); + classes.put(LookupPickerField.NAME, DesktopLookupPickerField.class); + classes.put(MaskedField.NAME, DesktopMaskedField.class); + classes.put(CurrencyField.NAME, DesktopCurrencyField.class); + + classes.put(SearchField.NAME, DesktopSearchField.class); + classes.put(SearchPickerField.NAME, DesktopSearchPickerField.class); + + classes.put(OptionsGroup.NAME, DesktopOptionsGroup.class); + classes.put(FileUploadField.NAME, DesktopFileUploadField.class); + classes.put(FileMultiUploadField.NAME, DesktopFileMultiUploadField.class); + classes.put(TabSheet.NAME, DesktopTabSheet.class); + classes.put(Embedded.NAME, DesktopEmbedded.class); + classes.put(WidgetsTree.NAME, DesktopWidgetsTree.class); + classes.put(GroupBoxLayout.NAME, DesktopGroupBox.class); + classes.put(ProgressBar.NAME, DesktopProgressBar.class); + classes.put(TimeField.NAME, DesktopTimeField.class); + classes.put(TokenList.NAME, DesktopTokenList.class); + classes.put(RelatedEntities.NAME, DesktopRelatedEntities.class); + classes.put(BulkEditor.NAME, DesktopBulkEditor.class); + classes.put(ListEditor.NAME, DesktopListEditor.class); + } + + public static void registerComponent(String element, Class componentClass) { + classes.put(element, componentClass); + } + + public static void registerComponents(ComponentPalette... palettes) { + for (ComponentPalette palette : palettes) { + Map> loaders = palette.getComponents(); + for (Map.Entry> loaderEntry : loaders.entrySet()) { + classes.put(loaderEntry.getKey(), loaderEntry.getValue()); + } + } + } + + @Override + public Component createComponent(String name) { + final Class componentClass = classes.get(name); + if (componentClass == null) { + throw new IllegalStateException(String.format("Can't find component class for '%s'", name)); + } + + try { + return componentClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Error creating the '" + name + "' component instance", e); + } + } + + @Override + public T createComponent(Class type) { + String name = names.get(type); + if (name == null) { + java.lang.reflect.Field nameField; + try { + nameField = type.getField("NAME"); + name = (String) nameField.get(null); + } catch (NoSuchFieldException | IllegalAccessException ignore) { + } + if (name == null) + throw new DevelopmentException(String.format("Class '%s' doesn't have NAME field", type.getName())); + else + names.put(type, name); + } + return type.cast(createComponent(name)); + } + + @Override + public Timer createTimer() { + return new DesktopTimer(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopUIPaletteManager.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopUIPaletteManager.java index e022059c4c..d5510d1bcc 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopUIPaletteManager.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/DesktopUIPaletteManager.java @@ -1,29 +1,29 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui; - -import com.haulmont.cuba.gui.ComponentPalette; -import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig; - -public class DesktopUIPaletteManager { - - public static void registerPalettes(ComponentPalette... palettes) { - LayoutLoaderConfig.registerLoaders(palettes); - DesktopComponentsFactory.registerComponents(palettes); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui; + +import com.haulmont.cuba.gui.ComponentPalette; +import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig; + +public class DesktopUIPaletteManager { + + public static void registerPalettes(ComponentPalette... palettes) { + LayoutLoaderConfig.registerLoaders(palettes); + DesktopComponentsFactory.registerComponents(palettes); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/AutoExpanding.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/AutoExpanding.java index 02b498923d..83e45142e9 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/AutoExpanding.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/AutoExpanding.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -/** - * - * Returns, whether component is trying to gain all available space by default, - * when size isn't set explicitly. - * Components not implementing this interface, considered non-expanding by default. - * - * In vaadin, this logic is built into client GWT side of components. - * - */ -public interface AutoExpanding { - boolean expandsWidth(); - boolean expandsHeight(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +/** + * + * Returns, whether component is trying to gain all available space by default, + * when size isn't set explicitly. + * Components not implementing this interface, considered non-expanding by default. + * + * In vaadin, this logic is built into client GWT side of components. + * + */ +public interface AutoExpanding { + boolean expandsWidth(); + boolean expandsHeight(); +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/ComponentCaption.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/ComponentCaption.java index abb3d7519c..c1353d9e65 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/ComponentCaption.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/ComponentCaption.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; -import com.haulmont.cuba.gui.components.Component; - -import javax.swing.*; - -public class ComponentCaption extends JPanel { - - private Component owner; - private JLabel label; - private ToolTipButton toolTipButton; - - public ComponentCaption(Component owner) { - BoxLayoutAdapter.create(this); - this.owner = owner; - takeOwnerProperties(); - } - - private void takeOwnerProperties() { - if (label == null) { - label = new JLabel(); - add(label); - } - - label.setText(((Component.HasCaption) owner).getCaption()); - if (((Component.HasCaption) owner).getDescription() != null) { - if (toolTipButton == null) { - toolTipButton = new ToolTipButton(); - toolTipButton.setFocusable(false); - DesktopToolTipManager.getInstance().registerTooltip(toolTipButton); - add(toolTipButton); - } - toolTipButton.setToolTipText(((Component.HasCaption) owner).getDescription()); - } else if (toolTipButton != null) { - remove(toolTipButton); - toolTipButton = null; - } - - setVisible(owner.isVisible()); - setEnabled(owner.isEnabled()); - } - - public void update() { - takeOwnerProperties(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; +import com.haulmont.cuba.gui.components.Component; + +import javax.swing.*; + +public class ComponentCaption extends JPanel { + + private Component owner; + private JLabel label; + private ToolTipButton toolTipButton; + + public ComponentCaption(Component owner) { + BoxLayoutAdapter.create(this); + this.owner = owner; + takeOwnerProperties(); + } + + private void takeOwnerProperties() { + if (label == null) { + label = new JLabel(); + add(label); + } + + label.setText(((Component.HasCaption) owner).getCaption()); + if (((Component.HasCaption) owner).getDescription() != null) { + if (toolTipButton == null) { + toolTipButton = new ToolTipButton(); + toolTipButton.setFocusable(false); + DesktopToolTipManager.getInstance().registerTooltip(toolTipButton); + add(toolTipButton); + } + toolTipButton.setToolTipText(((Component.HasCaption) owner).getDescription()); + } else if (toolTipButton != null) { + remove(toolTipButton); + toolTipButton = null; + } + + setVisible(owner.isVisible()); + setEnabled(owner.isEnabled()); + } + + public void update() { + takeOwnerProperties(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractActionsHolderComponent.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractActionsHolderComponent.java index 2721e3489a..f8ee22b8a1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractActionsHolderComponent.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractActionsHolderComponent.java @@ -1,148 +1,148 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.*; -import org.apache.commons.lang.ObjectUtils; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.util.*; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; -import static com.haulmont.cuba.gui.ComponentsHelper.findActionById; - -public class DesktopAbstractActionsHolderComponent extends DesktopAbstractComponent - implements Component.SecuredActionsHolder { - - protected List actionList = new LinkedList<>(); - - protected final ShortcutsDelegate shortcutsDelegate; - protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); - - public DesktopAbstractActionsHolderComponent() { - shortcutsDelegate = new ShortcutsDelegate() { - @Override - protected KeyCombination attachShortcut(final String actionId, KeyCombination keyCombination) { - impl.getInputMap().put(DesktopComponentsHelper.convertKeyCombination(keyCombination), actionId); - impl.getActionMap().put(actionId, new ValidationAwareAction() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - Action action = getAction(actionId); - if ((action != null) && (action.isEnabled()) && (action.isVisible())) { - action.actionPerform(DesktopAbstractActionsHolderComponent.this); - } - } - }); - return keyCombination; - } - - @Override - protected void detachShortcut(Action action, KeyCombination shortcutDescriptor) { - impl.getInputMap().remove(DesktopComponentsHelper.convertKeyCombination(shortcutDescriptor)); - impl.getActionMap().remove(action.getId()); - } - - @Override - protected Collection getActions() { - return DesktopAbstractActionsHolderComponent.this.getActions(); - } - }; - } - - @Override - public void addAction(Action action) { - int index = findActionById(actionList, action.getId()); - if (index < 0) { - index = actionList.size(); - } - - addAction(action, index); - } - - @Override - public void addAction(Action action, int index) { - checkNotNullArgument(action, "action must be non null"); - - int oldIndex = findActionById(actionList, action.getId()); - if (oldIndex >= 0) { - removeAction(actionList.get(oldIndex)); - if (index > oldIndex) { - index--; - } - } - - actionList.add(index, action); - - shortcutsDelegate.addAction(null, action); - - attachAction(action); - - actionsPermissions.apply(action); - } - - protected void attachAction(Action action) { - action.refreshState(); - } - - @Override - public void removeAction(@Nullable Action action) { - if (actionList.remove(action)) { - shortcutsDelegate.removeAction(action); - } - } - - @Override - public void removeAction(@Nullable String id) { - Action action = getAction(id); - if (action != null) { - removeAction(action); - } - } - - @Override - public void removeAllActions() { - for (Action action : new ArrayList<>(actionList)) { - removeAction(action); - } - } - - @Override - public Collection getActions() { - return Collections.unmodifiableCollection(actionList); - } - - @Override - @Nullable - public Action getAction(String id) { - for (Action action : getActions()) { - if (ObjectUtils.equals(action.getId(), id)) { - return action; - } - } - return null; - } - - @Override - public ActionsPermissions getActionsPermissions() { - return actionsPermissions; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.*; +import org.apache.commons.lang.ObjectUtils; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.util.*; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; +import static com.haulmont.cuba.gui.ComponentsHelper.findActionById; + +public class DesktopAbstractActionsHolderComponent extends DesktopAbstractComponent + implements Component.SecuredActionsHolder { + + protected List actionList = new LinkedList<>(); + + protected final ShortcutsDelegate shortcutsDelegate; + protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); + + public DesktopAbstractActionsHolderComponent() { + shortcutsDelegate = new ShortcutsDelegate() { + @Override + protected KeyCombination attachShortcut(final String actionId, KeyCombination keyCombination) { + impl.getInputMap().put(DesktopComponentsHelper.convertKeyCombination(keyCombination), actionId); + impl.getActionMap().put(actionId, new ValidationAwareAction() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + Action action = getAction(actionId); + if ((action != null) && (action.isEnabled()) && (action.isVisible())) { + action.actionPerform(DesktopAbstractActionsHolderComponent.this); + } + } + }); + return keyCombination; + } + + @Override + protected void detachShortcut(Action action, KeyCombination shortcutDescriptor) { + impl.getInputMap().remove(DesktopComponentsHelper.convertKeyCombination(shortcutDescriptor)); + impl.getActionMap().remove(action.getId()); + } + + @Override + protected Collection getActions() { + return DesktopAbstractActionsHolderComponent.this.getActions(); + } + }; + } + + @Override + public void addAction(Action action) { + int index = findActionById(actionList, action.getId()); + if (index < 0) { + index = actionList.size(); + } + + addAction(action, index); + } + + @Override + public void addAction(Action action, int index) { + checkNotNullArgument(action, "action must be non null"); + + int oldIndex = findActionById(actionList, action.getId()); + if (oldIndex >= 0) { + removeAction(actionList.get(oldIndex)); + if (index > oldIndex) { + index--; + } + } + + actionList.add(index, action); + + shortcutsDelegate.addAction(null, action); + + attachAction(action); + + actionsPermissions.apply(action); + } + + protected void attachAction(Action action) { + action.refreshState(); + } + + @Override + public void removeAction(@Nullable Action action) { + if (actionList.remove(action)) { + shortcutsDelegate.removeAction(action); + } + } + + @Override + public void removeAction(@Nullable String id) { + Action action = getAction(id); + if (action != null) { + removeAction(action); + } + } + + @Override + public void removeAllActions() { + for (Action action : new ArrayList<>(actionList)) { + removeAction(action); + } + } + + @Override + public Collection getActions() { + return Collections.unmodifiableCollection(actionList); + } + + @Override + @Nullable + public Action getAction(String id) { + for (Action action : getActions()) { + if (ObjectUtils.equals(action.getId(), id)) { + return action; + } + } + return null; + } + + @Override + public ActionsPermissions getActionsPermissions() { + return actionsPermissions; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractBox.java index a663b9c026..4b7b107823 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractBox.java @@ -1,459 +1,459 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.google.common.collect.Iterables; -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.MarginInfo; -import net.miginfocom.layout.CC; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.util.*; - -public abstract class DesktopAbstractBox - extends DesktopAbstractComponent - implements com.haulmont.cuba.gui.components.BoxLayout, DesktopContainer { - - protected BoxLayoutAdapter layoutAdapter; - - protected Collection ownComponents = new LinkedHashSet<>(); - protected Map componentByIds = new HashMap<>(); - - protected Component expandedComponent; - protected Map captions = new HashMap<>(); - protected Map> wrappers = new HashMap<>(); - - protected boolean scheduledRepaint = false; - - public DesktopAbstractBox() { - impl = new JPanel(); - impl.setFocusable(false); - assignClassDebugProperty(impl); - layoutAdapter = BoxLayoutAdapter.create(impl); - } - - @Override - public void add(Component component) { - add(component, ownComponents.size()); - } - - @Override - public void add(Component component, int index) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - if (ownComponents.contains(component)) { - int existingIndex = new ArrayList<>(ownComponents).indexOf(component); - if (index > existingIndex) { - index--; - } - - remove(component); - } - - int implIndex = getActualIndex(index); - - // add caption first - ComponentCaption caption = null; - boolean haveDescription = false; - if (DesktopContainerHelper.hasExternalCaption(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - impl.add(caption, layoutAdapter.getCaptionConstraints(component), implIndex); // CAUTION this dramatically wrong - implIndex++; - } else if (DesktopContainerHelper.hasExternalDescription(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - haveDescription = true; - } - - JComponent composition = DesktopComponentsHelper.getComposition(component); - //if component have description without caption, we need to wrap - // component to view Description button horizontally after component - if (haveDescription) { - JPanel wrapper = new JPanel(); - BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); - adapter.setExpandLayout(true); - adapter.setSpacing(false); - adapter.setMargin(false); - wrapper.add(composition); - wrapper.add(caption,new CC().alignY("top")); - impl.add(wrapper, layoutAdapter.getConstraints(component), implIndex); - wrappers.put(component, new Pair<>(wrapper, adapter)); - } else { - impl.add(composition, layoutAdapter.getConstraints(component), implIndex); - } - - if (component.getId() != null) { - componentByIds.put(component.getId(), component); - } - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - attachToFrame(component); - } - } - - if (index == ownComponents.size()) { - ownComponents.add(component); - } else { - List componentsTempList = new ArrayList<>(ownComponents); - componentsTempList.add(index, component); - - ownComponents.clear(); - ownComponents.addAll(componentsTempList); - } - - DesktopContainerHelper.assignContainer(component, this); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - component.setParent(this); - - requestContainerUpdate(); - - requestRepaint(); - } - - @Override - public int indexOf(Component child) { - return Iterables.indexOf(ownComponents, c -> c == child); - } - - protected void attachToFrame(Component component) { - frame.registerComponent(component); - } - - protected int getActualIndex(int originalIndex) { - int index = originalIndex; - Object[] components = ownComponents.toArray(); - for (int i = 0; i < originalIndex; i++) { - if (DesktopContainerHelper.hasExternalCaption((Component)components[i])) - index++; - } - return index; - } - - @Override - public void remove(Component component) { - JComponent composition = DesktopComponentsHelper.getComposition(component); - if (wrappers.containsKey(component)) { - impl.remove(wrappers.get(component).getFirst()); - wrappers.remove(component); - } else { - impl.remove(composition); - } - if (captions.containsKey(component)) { - impl.remove(captions.get(component)); - captions.remove(component); - } - - if (component.getId() != null) { - componentByIds.remove(component.getId()); - } - ownComponents.remove(component); - - DesktopContainerHelper.assignContainer(component, null); - if (expandedComponent == component) { - expandedComponent = null; - } - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - - requestContainerUpdate(); - - requestRepaint(); - } - - @Override - public void removeAll() { - wrappers.clear(); - impl.removeAll(); - componentByIds.clear(); - captions.clear(); - - List components = new ArrayList<>(ownComponents); - ownComponents.clear(); - - for (Component component : components) { - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - if (expandedComponent == component) { - expandedComponent = null; - } - - component.setParent(null); - - DesktopContainerHelper.assignContainer(component, null); - } - - requestRepaint(); - } - - @Override - public void setFrame(Frame frame) { - super.setFrame(frame); - - if (frame != null) { - for (Component childComponent : ownComponents) { - if (childComponent instanceof BelongToFrame - && ((BelongToFrame) childComponent).getFrame() == null) { - ((BelongToFrame) childComponent).setFrame(frame); - } - } - } - } - - protected void requestRepaint() { - if (!scheduledRepaint) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (expandedComponent != null) { - updateComponentInternal(expandedComponent); - } - - impl.revalidate(); - impl.repaint(); - - scheduledRepaint = false; - } - }); - - scheduledRepaint = true; - } - } - - @Override - public void updateComponent(Component child) { - updateComponentInternal(child); - - requestRepaint(); - - requestContainerUpdate(); - } - - protected void updateComponentInternal(Component child) { - boolean componentReAdded = false; - if (DesktopContainerHelper.mayHaveExternalCaption(child)) { - if (captions.containsKey(child) - && !DesktopContainerHelper.hasExternalCaption(child) - && !DesktopContainerHelper.hasExternalDescription(child)) { - reAddChild(child); - componentReAdded = true; - } else if (!captions.containsKey(child) - && (DesktopContainerHelper.hasExternalCaption(child) - || DesktopContainerHelper.hasExternalDescription(child))) { - reAddChild(child); - componentReAdded = true; - } else if (captions.containsKey(child)) { - ComponentCaption caption = captions.get(child); - caption.update(); - BoxLayoutAdapter adapterForCaption = layoutAdapter; - if (wrappers.containsKey(child)) { - adapterForCaption = wrappers.get(child).getSecond(); - } - adapterForCaption.updateConstraints(caption, adapterForCaption.getCaptionConstraints(child)); - } - } - - if (!componentReAdded) { - JComponent composition; - if (wrappers.containsKey(child)) { - composition = wrappers.get(child).getFirst(); - } else { - composition = DesktopComponentsHelper.getComposition(child); - } - layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); - } - } - - protected void reAddChild(Component child) { - int index = indexOf(child); - - boolean expanded = expandedComponent == child; - remove(child); - add(child, index); - - if (expanded) { - expand(child); - } - } - - @Override - public Component getOwnComponent(String id) { - return componentByIds.get(id); - } - - @Nullable - @Override - public Component getComponent(String id) { - return ComponentsHelper.getComponent(this, id); - } - - @Nullable - @Override - public Component getComponent(int index) { - return Iterables.get(ownComponents, index); - } - - @Override - public Collection getOwnComponents() { - return Collections.unmodifiableCollection(ownComponents); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public void expand(Component component, String height, String width) { - if (expandedComponent != null - && expandedComponent instanceof DesktopComponent) { - ((DesktopComponent) expandedComponent).setExpanded(false); - } - - if (layoutAdapter.getFlowDirection() == BoxLayoutAdapter.FlowDirection.Y) { - if (StringUtils.isEmpty(height) || AUTO_SIZE.equals(height) || height.endsWith("%")) { - component.setHeight("100%"); - } - } else if (layoutAdapter.getFlowDirection() == BoxLayoutAdapter.FlowDirection.X) { - if (StringUtils.isEmpty(width) || AUTO_SIZE.equals(width) || width.endsWith("%")) { - component.setWidth("100%"); - } - } - - JComponent expandingChild = DesktopComponentsHelper.getComposition(component); - - Pair wrapperInfo = wrappers.get(component); - if (wrapperInfo != null) { - expandingChild = wrapperInfo.getFirst(); - } - - layoutAdapter.expand(expandingChild, height, width); - - if (component instanceof DesktopComponent) { - ((DesktopComponent) component).setExpanded(true); - } - - expandedComponent = component; - } - - @Override - public void expand(Component component) { - expand(component, "", ""); - } - - @Override - public void resetExpanded() { - expandedComponent = null; - layoutAdapter.resetExpanded(); - - requestRepaint(); - } - - @Override - public boolean isExpanded(Component component) { - return expandedComponent == component; - } - - @Override - public void setMargin(MarginInfo marginInfo) { - layoutAdapter.setMargin(marginInfo); - } - - @Override - public MarginInfo getMargin() { - return layoutAdapter.getMargin(); - } - - @Override - public void setSpacing(boolean enabled) { - layoutAdapter.setSpacing(enabled); - } - - @Override - public boolean getSpacing() { - return layoutAdapter.getSpacing(); - } - - @Override - public void setExpanded(boolean expanded) { - layoutAdapter.setExpandLayout(expanded); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - for (Component component : ownComponents) { - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); - } - } - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - @Override - public void addLayoutClickListener(LayoutClickListener listener) { - } - - @Override - public void removeLayoutClickListener(LayoutClickListener listener) { - } - - @Override - public void addShortcutAction(ShortcutAction action) { - // do nothing - } - - @Override - public void removeShortcutAction(ShortcutAction action) { - // do nothing - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.google.common.collect.Iterables; +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.MarginInfo; +import net.miginfocom.layout.CC; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.util.*; + +public abstract class DesktopAbstractBox + extends DesktopAbstractComponent + implements com.haulmont.cuba.gui.components.BoxLayout, DesktopContainer { + + protected BoxLayoutAdapter layoutAdapter; + + protected Collection ownComponents = new LinkedHashSet<>(); + protected Map componentByIds = new HashMap<>(); + + protected Component expandedComponent; + protected Map captions = new HashMap<>(); + protected Map> wrappers = new HashMap<>(); + + protected boolean scheduledRepaint = false; + + public DesktopAbstractBox() { + impl = new JPanel(); + impl.setFocusable(false); + assignClassDebugProperty(impl); + layoutAdapter = BoxLayoutAdapter.create(impl); + } + + @Override + public void add(Component component) { + add(component, ownComponents.size()); + } + + @Override + public void add(Component component, int index) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + if (ownComponents.contains(component)) { + int existingIndex = new ArrayList<>(ownComponents).indexOf(component); + if (index > existingIndex) { + index--; + } + + remove(component); + } + + int implIndex = getActualIndex(index); + + // add caption first + ComponentCaption caption = null; + boolean haveDescription = false; + if (DesktopContainerHelper.hasExternalCaption(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + impl.add(caption, layoutAdapter.getCaptionConstraints(component), implIndex); // CAUTION this dramatically wrong + implIndex++; + } else if (DesktopContainerHelper.hasExternalDescription(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + haveDescription = true; + } + + JComponent composition = DesktopComponentsHelper.getComposition(component); + //if component have description without caption, we need to wrap + // component to view Description button horizontally after component + if (haveDescription) { + JPanel wrapper = new JPanel(); + BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); + adapter.setExpandLayout(true); + adapter.setSpacing(false); + adapter.setMargin(false); + wrapper.add(composition); + wrapper.add(caption,new CC().alignY("top")); + impl.add(wrapper, layoutAdapter.getConstraints(component), implIndex); + wrappers.put(component, new Pair<>(wrapper, adapter)); + } else { + impl.add(composition, layoutAdapter.getConstraints(component), implIndex); + } + + if (component.getId() != null) { + componentByIds.put(component.getId(), component); + } + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + attachToFrame(component); + } + } + + if (index == ownComponents.size()) { + ownComponents.add(component); + } else { + List componentsTempList = new ArrayList<>(ownComponents); + componentsTempList.add(index, component); + + ownComponents.clear(); + ownComponents.addAll(componentsTempList); + } + + DesktopContainerHelper.assignContainer(component, this); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + component.setParent(this); + + requestContainerUpdate(); + + requestRepaint(); + } + + @Override + public int indexOf(Component child) { + return Iterables.indexOf(ownComponents, c -> c == child); + } + + protected void attachToFrame(Component component) { + frame.registerComponent(component); + } + + protected int getActualIndex(int originalIndex) { + int index = originalIndex; + Object[] components = ownComponents.toArray(); + for (int i = 0; i < originalIndex; i++) { + if (DesktopContainerHelper.hasExternalCaption((Component)components[i])) + index++; + } + return index; + } + + @Override + public void remove(Component component) { + JComponent composition = DesktopComponentsHelper.getComposition(component); + if (wrappers.containsKey(component)) { + impl.remove(wrappers.get(component).getFirst()); + wrappers.remove(component); + } else { + impl.remove(composition); + } + if (captions.containsKey(component)) { + impl.remove(captions.get(component)); + captions.remove(component); + } + + if (component.getId() != null) { + componentByIds.remove(component.getId()); + } + ownComponents.remove(component); + + DesktopContainerHelper.assignContainer(component, null); + if (expandedComponent == component) { + expandedComponent = null; + } + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + + requestContainerUpdate(); + + requestRepaint(); + } + + @Override + public void removeAll() { + wrappers.clear(); + impl.removeAll(); + componentByIds.clear(); + captions.clear(); + + List components = new ArrayList<>(ownComponents); + ownComponents.clear(); + + for (Component component : components) { + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + if (expandedComponent == component) { + expandedComponent = null; + } + + component.setParent(null); + + DesktopContainerHelper.assignContainer(component, null); + } + + requestRepaint(); + } + + @Override + public void setFrame(Frame frame) { + super.setFrame(frame); + + if (frame != null) { + for (Component childComponent : ownComponents) { + if (childComponent instanceof BelongToFrame + && ((BelongToFrame) childComponent).getFrame() == null) { + ((BelongToFrame) childComponent).setFrame(frame); + } + } + } + } + + protected void requestRepaint() { + if (!scheduledRepaint) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (expandedComponent != null) { + updateComponentInternal(expandedComponent); + } + + impl.revalidate(); + impl.repaint(); + + scheduledRepaint = false; + } + }); + + scheduledRepaint = true; + } + } + + @Override + public void updateComponent(Component child) { + updateComponentInternal(child); + + requestRepaint(); + + requestContainerUpdate(); + } + + protected void updateComponentInternal(Component child) { + boolean componentReAdded = false; + if (DesktopContainerHelper.mayHaveExternalCaption(child)) { + if (captions.containsKey(child) + && !DesktopContainerHelper.hasExternalCaption(child) + && !DesktopContainerHelper.hasExternalDescription(child)) { + reAddChild(child); + componentReAdded = true; + } else if (!captions.containsKey(child) + && (DesktopContainerHelper.hasExternalCaption(child) + || DesktopContainerHelper.hasExternalDescription(child))) { + reAddChild(child); + componentReAdded = true; + } else if (captions.containsKey(child)) { + ComponentCaption caption = captions.get(child); + caption.update(); + BoxLayoutAdapter adapterForCaption = layoutAdapter; + if (wrappers.containsKey(child)) { + adapterForCaption = wrappers.get(child).getSecond(); + } + adapterForCaption.updateConstraints(caption, adapterForCaption.getCaptionConstraints(child)); + } + } + + if (!componentReAdded) { + JComponent composition; + if (wrappers.containsKey(child)) { + composition = wrappers.get(child).getFirst(); + } else { + composition = DesktopComponentsHelper.getComposition(child); + } + layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); + } + } + + protected void reAddChild(Component child) { + int index = indexOf(child); + + boolean expanded = expandedComponent == child; + remove(child); + add(child, index); + + if (expanded) { + expand(child); + } + } + + @Override + public Component getOwnComponent(String id) { + return componentByIds.get(id); + } + + @Nullable + @Override + public Component getComponent(String id) { + return ComponentsHelper.getComponent(this, id); + } + + @Nullable + @Override + public Component getComponent(int index) { + return Iterables.get(ownComponents, index); + } + + @Override + public Collection getOwnComponents() { + return Collections.unmodifiableCollection(ownComponents); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public void expand(Component component, String height, String width) { + if (expandedComponent != null + && expandedComponent instanceof DesktopComponent) { + ((DesktopComponent) expandedComponent).setExpanded(false); + } + + if (layoutAdapter.getFlowDirection() == BoxLayoutAdapter.FlowDirection.Y) { + if (StringUtils.isEmpty(height) || AUTO_SIZE.equals(height) || height.endsWith("%")) { + component.setHeight("100%"); + } + } else if (layoutAdapter.getFlowDirection() == BoxLayoutAdapter.FlowDirection.X) { + if (StringUtils.isEmpty(width) || AUTO_SIZE.equals(width) || width.endsWith("%")) { + component.setWidth("100%"); + } + } + + JComponent expandingChild = DesktopComponentsHelper.getComposition(component); + + Pair wrapperInfo = wrappers.get(component); + if (wrapperInfo != null) { + expandingChild = wrapperInfo.getFirst(); + } + + layoutAdapter.expand(expandingChild, height, width); + + if (component instanceof DesktopComponent) { + ((DesktopComponent) component).setExpanded(true); + } + + expandedComponent = component; + } + + @Override + public void expand(Component component) { + expand(component, "", ""); + } + + @Override + public void resetExpanded() { + expandedComponent = null; + layoutAdapter.resetExpanded(); + + requestRepaint(); + } + + @Override + public boolean isExpanded(Component component) { + return expandedComponent == component; + } + + @Override + public void setMargin(MarginInfo marginInfo) { + layoutAdapter.setMargin(marginInfo); + } + + @Override + public MarginInfo getMargin() { + return layoutAdapter.getMargin(); + } + + @Override + public void setSpacing(boolean enabled) { + layoutAdapter.setSpacing(enabled); + } + + @Override + public boolean getSpacing() { + return layoutAdapter.getSpacing(); + } + + @Override + public void setExpanded(boolean expanded) { + layoutAdapter.setExpandLayout(expanded); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + for (Component component : ownComponents) { + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); + } + } + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + @Override + public void addLayoutClickListener(LayoutClickListener listener) { + } + + @Override + public void removeLayoutClickListener(LayoutClickListener listener) { + } + + @Override + public void addShortcutAction(ShortcutAction action) { + // do nothing + } + + @Override + public void removeShortcutAction(ShortcutAction action) { + // do nothing + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractComponent.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractComponent.java index aa31dffadb..bfc7a8738b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractComponent.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractComponent.java @@ -1,528 +1,528 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.data.ComponentSize; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.theme.DesktopTheme; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Field; -import com.haulmont.cuba.gui.components.Formatter; -import com.haulmont.cuba.gui.components.Frame; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import javax.swing.*; -import java.util.*; - -public abstract class DesktopAbstractComponent - implements - DesktopComponent, Component.Wrapper, Component.HasXmlDescriptor, Component.BelongToFrame, Component.HasIcon { - - public static final String SWING_PROPERTY_CLASS = "cubaClass"; - public static final String SWING_PROPERTY_ID = "cubaId"; - - protected C impl; - - protected DesktopContainer container; - - protected String id; - protected Frame frame; - protected Component parent; - - protected Element xmlDescriptor; - - protected ComponentSize widthSize; - protected ComponentSize heightSize; - - protected Alignment alignment; - - protected boolean visible = true; - protected boolean enabled = true; - protected boolean responsive = false; - - protected boolean parentEnabled = true; - - protected int tabIndex = 0; // just stub - - protected String debugId; - - // lazily initialized list - protected List styles; - - protected String caption; - - protected C getImpl() { - return impl; - } - - protected String getSwingPropertyId() { - return SWING_PROPERTY_ID; - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - if (!Objects.equals(getCaption(), caption)) { - this.caption = caption; - - setCaptionToComponent(caption); - - if (this instanceof Field - && parent instanceof DesktopFieldGroup) { - ((DesktopFieldGroup) parent).updateCaptionText(this); - } - } - } - - protected void setCaptionToComponent(String caption) { - } - - @Override - public Component getParent() { - return parent; - } - - @Override - public void setParent(Component parent) { - this.parent = parent; - } - - @Override - public Frame getFrame() { - return frame; - } - - @Override - public void setFrame(Frame frame) { - this.frame = frame; - if (frame != null) { - frame.registerComponent(this); - } - - assignAutoDebugId(); - } - - @Override - public String getId() { - return id; - } - - @Override - public void setId(String id) { - if (!ObjectUtils.equals(this.id, id)) { - if (frame != null) { - frame.unregisterComponent(this); - } - - this.id = id; - C impl = getImpl(); - if (impl != null) { - impl.putClientProperty(getSwingPropertyId(), id); - impl.setName(id); - } - - if (frame != null) { - frame.registerComponent(this); - } - } - } - - public void assignAutoDebugId() { - App app = App.getInstance(); - if (app != null && app.isTestMode()) { - C impl = getImpl(); - // always change name, do not assign auto id for components - if (getId() == null && impl != null) { - String alternativeDebugId = getAlternativeDebugId(); - - impl.setName(alternativeDebugId); - } - } - } - - /** - * @return id that is suitable for auto debug id - */ - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - - return getClass().getSimpleName(); - } - - protected void assignClassDebugProperty(JComponent c) { - c.putClientProperty(SWING_PROPERTY_CLASS, getClass().getSimpleName()); - } - - @Override - public String getDebugId() { - return debugId; - } - - @Override - public void setDebugId(String id) { - this.debugId = id; - } - - @Override - public boolean isEnabled() { - return DesktopComponentsHelper.isRecursivelyEnabled(getComposition()); - } - - @Override - public void setEnabled(boolean enabled) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (this.enabled != enabled) { - this.enabled = enabled; - - updateEnabled(); - } - } - - @Override - public boolean isResponsive() { - return responsive; - } - - @Override - public void setResponsive(boolean responsive) { - this.responsive = responsive; - } - - protected void updateEnabled() { - getComposition().setEnabled(isEnabledWithParent()); - - requestContainerUpdate(); - - if (parent instanceof DesktopFieldGroup) { - ((DesktopFieldGroup) parent).updateChildEnabled(this); - } - } - - protected boolean isEnabledWithParent() { - return enabled && parentEnabled; - } - - public boolean isComponentVisible() { - return getComposition().isVisible(); - } - - @Override - public boolean isVisible() { - return DesktopComponentsHelper.isRecursivelyVisible(getComposition()); - } - - @Override - public void setVisible(boolean visible) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (this.visible != visible) { - this.visible = visible; - - getComposition().setVisible(visible); - - if (parent instanceof DesktopFieldGroup) { - ((DesktopFieldGroup) parent).updateCaptionVisibility(this); - } - - requestContainerUpdate(); - } - } - - @Override - public boolean isVisibleItself() { - return visible; - } - - @Override - public boolean isEnabledItself() { - return enabled; - } - - @Override - public void requestFocus() { - SwingUtilities.invokeLater(() -> - impl.requestFocus() - ); - } - - @Override - public float getHeight() { - return heightSize != null ? heightSize.value : -1; - } - - @Override - public int getHeightUnits() { - return heightSize != null ? heightSize.unit : 0; - } - - @Override - public void setHeight(String height) { - heightSize = ComponentSize.parse(height); - requestContainerUpdate(); - } - - @Override - public float getWidth() { - return widthSize != null ? widthSize.value : -1; - } - - @Override - public int getWidthUnits() { - return widthSize != null ? widthSize.unit : 0; - } - - @Override - public void setWidth(String width) { - widthSize = ComponentSize.parse(width); - requestContainerUpdate(); - } - - @Override - public Alignment getAlignment() { - return alignment; - } - - @Override - public void setAlignment(Alignment alignment) { - if (this.alignment != alignment) { - this.alignment = alignment; - requestContainerUpdate(); - } - } - - @Override - public String getStyleName() { - if (CollectionUtils.isEmpty(styles)) - return StringUtils.EMPTY; - - return String.join(" ", styles); - } - - @Override - public void setStyleName(String styleName) { - if (styles == null) - styles = new LinkedList<>(); - - styles.clear(); - - parseAndApplyTheme(styleName); - } - - @Override - public void addStyleName(String styleName) { - if (styles == null) - styles = new LinkedList<>(); - - if (StringUtils.isEmpty(styleName) || styles.contains(styleName)) - return; - - parseAndApplyTheme(styleName); - } - - protected void parseAndApplyTheme(String styleName) { - String style = null; - if (StringUtils.isNotEmpty(styleName)) { - StringTokenizer tokenizer = new StringTokenizer(styleName, " "); - while (tokenizer.hasMoreTokens()) { - style = tokenizer.nextToken(); - styles.add(style); - } - } - - DesktopTheme appTheme = App.getInstance().getTheme(); - if (appTheme != null) - appTheme.applyStyle(this, style); - } - - @Override - public void removeStyleName(String styleName) { - if (StringUtils.isEmpty(styleName) || CollectionUtils.isEmpty(styles) || !styles.contains(styleName)) - return; - - List passedStyles = new ArrayList<>(); - - StringTokenizer tokenizer = new StringTokenizer(styleName, " "); - while (tokenizer.hasMoreTokens()) { - passedStyles.add(tokenizer.nextToken()); - } - - String appliedStyleName = styles.get(styles.size() - 1); - if (passedStyles.contains(appliedStyleName)) { - DesktopTheme appTheme = App.getInstance().getTheme(); - if (appTheme != null) - appTheme.applyStyle(this, null); - } - - styles.removeAll(passedStyles); - } - - @Override - public Element getXmlDescriptor() { - return xmlDescriptor; - } - - @Override - public void setXmlDescriptor(Element element) { - xmlDescriptor = element; - } - - @Override - public JComponent getComponent() { - return impl; - } - - @Override - public JComponent getComposition() { - return impl; - } - - @Override - public void setContainer(DesktopContainer container) { - this.container = container; - } - - protected void requestContainerUpdate() { - if (container != null) { - container.updateComponent(this); - } - } - - @Override - public void setExpanded(boolean expanded) { - } - - public boolean isParentEnabled() { - return parentEnabled; - } - - public void setParentEnabled(boolean parentEnabled) { - this.parentEnabled = parentEnabled; - - updateEnabled(); - } - - /** - * Default formatter for {@link DesktopLabel} and {@link DesktopTextField} - */ - protected static class DefaultValueFormatter { - - private MetaProperty metaProperty; - private Formatter formatter; - private Datatype datatype; - private Locale locale; - - public DefaultValueFormatter(Locale locale) { - this.locale = locale; - } - - public Formatter getFormatter() { - return formatter; - } - - public void setFormatter(Formatter formatter) { - this.formatter = formatter; - } - - public Datatype getDatatype() { - return datatype; - } - - public void setDatatype(Datatype datatype) { - this.datatype = datatype; - } - - public MetaProperty getMetaProperty() { - return metaProperty; - } - - public void setMetaProperty(MetaProperty metaProperty) { - this.metaProperty = metaProperty; - } - - /** - * Format value for text field or label - * - * @param value Object value - * @return Formatted string - */ - public String formatValue(Object value) { - String text; - if (formatter == null) { - if (value == null) { - text = ""; - } else { - MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - - if (metaProperty != null) { - text = metadataTools.format(value, metaProperty); - } else if (datatype != null) { - text = datatype.format(value, locale); - } else { - text = metadataTools.format(value); - } - } - } else { - text = formatter.format(value); - } - return text; - } - } - - @Override - public X unwrap(Class internalComponentClass) { - return (X) getComponent(); - } - - @Override - public X unwrapComposition(Class internalCompositionClass) { - return (X) getComposition(); - } - - @Override - public String getIcon() { - return null; - } - - @Override - public void setIcon(String icon) { - // do nothing - } - - // Just stub - public int getTabIndex() { - return tabIndex; - } - - // Just stub - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.data.ComponentSize; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.theme.DesktopTheme; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Field; +import com.haulmont.cuba.gui.components.Formatter; +import com.haulmont.cuba.gui.components.Frame; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import javax.swing.*; +import java.util.*; + +public abstract class DesktopAbstractComponent + implements + DesktopComponent, Component.Wrapper, Component.HasXmlDescriptor, Component.BelongToFrame, Component.HasIcon { + + public static final String SWING_PROPERTY_CLASS = "cubaClass"; + public static final String SWING_PROPERTY_ID = "cubaId"; + + protected C impl; + + protected DesktopContainer container; + + protected String id; + protected Frame frame; + protected Component parent; + + protected Element xmlDescriptor; + + protected ComponentSize widthSize; + protected ComponentSize heightSize; + + protected Alignment alignment; + + protected boolean visible = true; + protected boolean enabled = true; + protected boolean responsive = false; + + protected boolean parentEnabled = true; + + protected int tabIndex = 0; // just stub + + protected String debugId; + + // lazily initialized list + protected List styles; + + protected String caption; + + protected C getImpl() { + return impl; + } + + protected String getSwingPropertyId() { + return SWING_PROPERTY_ID; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + if (!Objects.equals(getCaption(), caption)) { + this.caption = caption; + + setCaptionToComponent(caption); + + if (this instanceof Field + && parent instanceof DesktopFieldGroup) { + ((DesktopFieldGroup) parent).updateCaptionText(this); + } + } + } + + protected void setCaptionToComponent(String caption) { + } + + @Override + public Component getParent() { + return parent; + } + + @Override + public void setParent(Component parent) { + this.parent = parent; + } + + @Override + public Frame getFrame() { + return frame; + } + + @Override + public void setFrame(Frame frame) { + this.frame = frame; + if (frame != null) { + frame.registerComponent(this); + } + + assignAutoDebugId(); + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + if (!ObjectUtils.equals(this.id, id)) { + if (frame != null) { + frame.unregisterComponent(this); + } + + this.id = id; + C impl = getImpl(); + if (impl != null) { + impl.putClientProperty(getSwingPropertyId(), id); + impl.setName(id); + } + + if (frame != null) { + frame.registerComponent(this); + } + } + } + + public void assignAutoDebugId() { + App app = App.getInstance(); + if (app != null && app.isTestMode()) { + C impl = getImpl(); + // always change name, do not assign auto id for components + if (getId() == null && impl != null) { + String alternativeDebugId = getAlternativeDebugId(); + + impl.setName(alternativeDebugId); + } + } + } + + /** + * @return id that is suitable for auto debug id + */ + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + + return getClass().getSimpleName(); + } + + protected void assignClassDebugProperty(JComponent c) { + c.putClientProperty(SWING_PROPERTY_CLASS, getClass().getSimpleName()); + } + + @Override + public String getDebugId() { + return debugId; + } + + @Override + public void setDebugId(String id) { + this.debugId = id; + } + + @Override + public boolean isEnabled() { + return DesktopComponentsHelper.isRecursivelyEnabled(getComposition()); + } + + @Override + public void setEnabled(boolean enabled) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (this.enabled != enabled) { + this.enabled = enabled; + + updateEnabled(); + } + } + + @Override + public boolean isResponsive() { + return responsive; + } + + @Override + public void setResponsive(boolean responsive) { + this.responsive = responsive; + } + + protected void updateEnabled() { + getComposition().setEnabled(isEnabledWithParent()); + + requestContainerUpdate(); + + if (parent instanceof DesktopFieldGroup) { + ((DesktopFieldGroup) parent).updateChildEnabled(this); + } + } + + protected boolean isEnabledWithParent() { + return enabled && parentEnabled; + } + + public boolean isComponentVisible() { + return getComposition().isVisible(); + } + + @Override + public boolean isVisible() { + return DesktopComponentsHelper.isRecursivelyVisible(getComposition()); + } + + @Override + public void setVisible(boolean visible) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (this.visible != visible) { + this.visible = visible; + + getComposition().setVisible(visible); + + if (parent instanceof DesktopFieldGroup) { + ((DesktopFieldGroup) parent).updateCaptionVisibility(this); + } + + requestContainerUpdate(); + } + } + + @Override + public boolean isVisibleItself() { + return visible; + } + + @Override + public boolean isEnabledItself() { + return enabled; + } + + @Override + public void requestFocus() { + SwingUtilities.invokeLater(() -> + impl.requestFocus() + ); + } + + @Override + public float getHeight() { + return heightSize != null ? heightSize.value : -1; + } + + @Override + public int getHeightUnits() { + return heightSize != null ? heightSize.unit : 0; + } + + @Override + public void setHeight(String height) { + heightSize = ComponentSize.parse(height); + requestContainerUpdate(); + } + + @Override + public float getWidth() { + return widthSize != null ? widthSize.value : -1; + } + + @Override + public int getWidthUnits() { + return widthSize != null ? widthSize.unit : 0; + } + + @Override + public void setWidth(String width) { + widthSize = ComponentSize.parse(width); + requestContainerUpdate(); + } + + @Override + public Alignment getAlignment() { + return alignment; + } + + @Override + public void setAlignment(Alignment alignment) { + if (this.alignment != alignment) { + this.alignment = alignment; + requestContainerUpdate(); + } + } + + @Override + public String getStyleName() { + if (CollectionUtils.isEmpty(styles)) + return StringUtils.EMPTY; + + return String.join(" ", styles); + } + + @Override + public void setStyleName(String styleName) { + if (styles == null) + styles = new LinkedList<>(); + + styles.clear(); + + parseAndApplyTheme(styleName); + } + + @Override + public void addStyleName(String styleName) { + if (styles == null) + styles = new LinkedList<>(); + + if (StringUtils.isEmpty(styleName) || styles.contains(styleName)) + return; + + parseAndApplyTheme(styleName); + } + + protected void parseAndApplyTheme(String styleName) { + String style = null; + if (StringUtils.isNotEmpty(styleName)) { + StringTokenizer tokenizer = new StringTokenizer(styleName, " "); + while (tokenizer.hasMoreTokens()) { + style = tokenizer.nextToken(); + styles.add(style); + } + } + + DesktopTheme appTheme = App.getInstance().getTheme(); + if (appTheme != null) + appTheme.applyStyle(this, style); + } + + @Override + public void removeStyleName(String styleName) { + if (StringUtils.isEmpty(styleName) || CollectionUtils.isEmpty(styles) || !styles.contains(styleName)) + return; + + List passedStyles = new ArrayList<>(); + + StringTokenizer tokenizer = new StringTokenizer(styleName, " "); + while (tokenizer.hasMoreTokens()) { + passedStyles.add(tokenizer.nextToken()); + } + + String appliedStyleName = styles.get(styles.size() - 1); + if (passedStyles.contains(appliedStyleName)) { + DesktopTheme appTheme = App.getInstance().getTheme(); + if (appTheme != null) + appTheme.applyStyle(this, null); + } + + styles.removeAll(passedStyles); + } + + @Override + public Element getXmlDescriptor() { + return xmlDescriptor; + } + + @Override + public void setXmlDescriptor(Element element) { + xmlDescriptor = element; + } + + @Override + public JComponent getComponent() { + return impl; + } + + @Override + public JComponent getComposition() { + return impl; + } + + @Override + public void setContainer(DesktopContainer container) { + this.container = container; + } + + protected void requestContainerUpdate() { + if (container != null) { + container.updateComponent(this); + } + } + + @Override + public void setExpanded(boolean expanded) { + } + + public boolean isParentEnabled() { + return parentEnabled; + } + + public void setParentEnabled(boolean parentEnabled) { + this.parentEnabled = parentEnabled; + + updateEnabled(); + } + + /** + * Default formatter for {@link DesktopLabel} and {@link DesktopTextField} + */ + protected static class DefaultValueFormatter { + + private MetaProperty metaProperty; + private Formatter formatter; + private Datatype datatype; + private Locale locale; + + public DefaultValueFormatter(Locale locale) { + this.locale = locale; + } + + public Formatter getFormatter() { + return formatter; + } + + public void setFormatter(Formatter formatter) { + this.formatter = formatter; + } + + public Datatype getDatatype() { + return datatype; + } + + public void setDatatype(Datatype datatype) { + this.datatype = datatype; + } + + public MetaProperty getMetaProperty() { + return metaProperty; + } + + public void setMetaProperty(MetaProperty metaProperty) { + this.metaProperty = metaProperty; + } + + /** + * Format value for text field or label + * + * @param value Object value + * @return Formatted string + */ + public String formatValue(Object value) { + String text; + if (formatter == null) { + if (value == null) { + text = ""; + } else { + MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + + if (metaProperty != null) { + text = metadataTools.format(value, metaProperty); + } else if (datatype != null) { + text = datatype.format(value, locale); + } else { + text = metadataTools.format(value); + } + } + } else { + text = formatter.format(value); + } + return text; + } + } + + @Override + public X unwrap(Class internalComponentClass) { + return (X) getComponent(); + } + + @Override + public X unwrapComposition(Class internalCompositionClass) { + return (X) getComposition(); + } + + @Override + public String getIcon() { + return null; + } + + @Override + public void setIcon(String icon) { + // do nothing + } + + // Just stub + public int getTabIndex() { + return tabIndex; + } + + // Just stub + public void setTabIndex(int tabIndex) { + this.tabIndex = tabIndex; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractField.java index a4de3fc87e..25ca69421c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractField.java @@ -1,293 +1,293 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; -import com.haulmont.cuba.core.entity.KeyValueEntity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.BeanValidation; -import com.haulmont.cuba.core.global.MessageTools; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.gui.components.Field; -import com.haulmont.cuba.gui.components.RequiredValueMissingException; -import com.haulmont.cuba.gui.components.ValidationException; -import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; -import com.haulmont.cuba.gui.components.validators.BeanValidator; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.ValueListener; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import javax.validation.constraints.NotNull; -import javax.validation.metadata.BeanDescriptor; -import java.awt.*; -import java.util.*; -import java.util.List; - -public abstract class DesktopAbstractField extends DesktopAbstractComponent implements Field { - - protected List listeners = new ArrayList<>(); - - protected boolean editable = true; - - protected boolean required; - protected String requiredMessage; - - protected Set validators = new LinkedHashSet<>(); - - // todo move nimbus constants to theme - protected Color requiredBgColor = (Color) UIManager.get("cubaRequiredBackground"); - protected Color defaultBgColor = (Color) UIManager.get("nimbusLightBackground"); - - protected MetaProperty metaProperty; - protected MetaPropertyPath metaPropertyPath; - - protected EditableChangeListener parentEditableChangeListener; - - @Override - public void addListener(ValueListener listener) { - addValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - @Override - public void removeListener(ValueListener listener) { - removeValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - protected void fireValueChanged(Object prevValue, Object value) { - for (ValueChangeListener listener : new ArrayList<>(listeners)) { - listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); - } - } - - @Override - public void addValueChangeListener(ValueChangeListener listener) { - if (!listeners.contains(listener)) { - listeners.add(listener); - } - } - - @Override - public void removeValueChangeListener(ValueChangeListener listener) { - listeners.remove(listener); - } - - @Override - public void addValidator(Validator validator) { - if (!validators.contains(validator)) - validators.add(validator); - } - - @Override - public void removeValidator(Validator validator) { - validators.remove(validator); - } - - @Override - public Collection getValidators() { - return Collections.unmodifiableCollection(validators); - } - - @Override - public boolean isValid() { - try { - validate(); - return true; - } catch (ValidationException e) { - return false; - } - } - - protected boolean isEmpty(Object value) { - return value == null; - } - - @Override - public void validate() throws ValidationException { - if (!isVisible() || !isEditableWithParent() || !isEnabled()) - return; - - Object value = getValue(); - if (isEmpty(value)) { - if (isRequired()) - throw new RequiredValueMissingException(requiredMessage, this); - else - return; - } - - for (Validator validator : validators) { - validator.validate(value); - } - } - - @Override - public boolean isRequired() { - return required; - } - - @Override - public void setRequired(boolean required) { - this.required = required; - updateMissingValueState(); - } - - public void updateMissingValueState() { - if (impl != null) { - decorateMissingValue(impl, required); - } - } - - protected void decorateMissingValue(JComponent jComponent, boolean missingValueState) { - jComponent.setBackground(missingValueState ? requiredBgColor : defaultBgColor); - } - - protected void initRequired(MetaPropertyPath metaPropertyPath) { - MetaProperty metaProperty = metaPropertyPath.getMetaProperty(); - - boolean newRequired = metaProperty.isMandatory(); - Object notNullUiComponent = metaProperty.getAnnotations().get(NotNull.class.getName() + "_notnull_ui_component"); - if (Boolean.TRUE.equals(notNullUiComponent)) { - newRequired = true; - } - setRequired(newRequired); - - if (StringUtils.isEmpty(getRequiredMessage())) { - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - setRequiredMessage(messageTools.getDefaultRequiredMessage(metaPropertyPath.getMetaClass(), metaPropertyPath.toString())); - } - } - - protected void initBeanValidator() { - MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - MetaClass propertyEnclosingMetaClass = metadataTools.getPropertyEnclosingMetaClass(metaPropertyPath); - Class enclosingJavaClass = propertyEnclosingMetaClass.getJavaClass(); - - if (enclosingJavaClass != KeyValueEntity.class - && !DynamicAttributesUtils.isDynamicAttribute(metaProperty)) { - BeanValidation beanValidation = AppBeans.get(BeanValidation.NAME); - javax.validation.Validator validator = beanValidation.getValidator(); - BeanDescriptor beanDescriptor = validator.getConstraintsForClass(enclosingJavaClass); - - if (beanDescriptor.isBeanConstrained()) { - addValidator(new BeanValidator(enclosingJavaClass, metaProperty.getName())); - } - } - } - - protected void disableBeanValidator() { - if (validators != null) { - for (Validator validator : new ArrayList<>(validators)) { - if (validator instanceof BeanValidator) { - validators.remove(validator); - } - } - } - } - - @Override - public void setRequiredMessage(String msg) { - requiredMessage = msg; - } - - @Override - public String getRequiredMessage() { - return requiredMessage; - } - - @Override - public boolean isEditable() { - return editable; - } - - @Override - public void setEditable(boolean editable) { - if (this.editable == editable) { - return; - } - - this.editable = editable; - - boolean parentEditable = true; - if (parent instanceof ChildEditableController) { - parentEditable = ((ChildEditableController) parent).isEditable(); - } - boolean finalEditable = parentEditable && editable; - - setEditableToComponent(finalEditable); - } - - protected abstract void setEditableToComponent(boolean editable); - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - Datasource datasource = getDatasource(); - MetaPropertyPath metaPropertyPath = getMetaPropertyPath(); - - if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { - return getClass().getSimpleName() + "_" + datasource.getId() + "_" + metaPropertyPath.toString(); - } - - return getClass().getSimpleName(); - } - - protected void resolveMetaPropertyPath(MetaClass metaClass, String property) { - metaPropertyPath = getResolvedMetaPropertyPath(metaClass, property); - this.metaProperty = metaPropertyPath.getMetaProperty(); - } - - protected MetaPropertyPath getResolvedMetaPropertyPath(MetaClass metaClass, String property) { - MetaPropertyPath metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) - .resolveMetaPropertyPath(metaClass, property); - Preconditions.checkNotNullArgument(metaPropertyPath, "Could not resolve property path '%s' in '%s'", property, metaClass); - - return metaPropertyPath; - } - - @Override - public void setParent(com.haulmont.cuba.gui.components.Component parent) { - if (this.parent instanceof EditableChangeNotifier - && parentEditableChangeListener != null) { - ((EditableChangeNotifier) this.parent).removeEditableChangeListener(parentEditableChangeListener); - - parentEditableChangeListener = null; - } - - super.setParent(parent); - - if (parent instanceof EditableChangeNotifier) { - parentEditableChangeListener = event -> { - boolean parentEditable = event.getSource().isEditable(); - boolean finalEditable = parentEditable && editable; - setEditableToComponent(finalEditable); - }; - ((EditableChangeNotifier) parent).addEditableChangeListener(parentEditableChangeListener); - - Editable parentEditable = (Editable) parent; - if (!parentEditable.isEditable()) { - setEditableToComponent(false); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; +import com.haulmont.cuba.core.entity.KeyValueEntity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.BeanValidation; +import com.haulmont.cuba.core.global.MessageTools; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.gui.components.Field; +import com.haulmont.cuba.gui.components.RequiredValueMissingException; +import com.haulmont.cuba.gui.components.ValidationException; +import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; +import com.haulmont.cuba.gui.components.validators.BeanValidator; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.ValueListener; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import javax.validation.constraints.NotNull; +import javax.validation.metadata.BeanDescriptor; +import java.awt.*; +import java.util.*; +import java.util.List; + +public abstract class DesktopAbstractField extends DesktopAbstractComponent implements Field { + + protected List listeners = new ArrayList<>(); + + protected boolean editable = true; + + protected boolean required; + protected String requiredMessage; + + protected Set validators = new LinkedHashSet<>(); + + // todo move nimbus constants to theme + protected Color requiredBgColor = (Color) UIManager.get("cubaRequiredBackground"); + protected Color defaultBgColor = (Color) UIManager.get("nimbusLightBackground"); + + protected MetaProperty metaProperty; + protected MetaPropertyPath metaPropertyPath; + + protected EditableChangeListener parentEditableChangeListener; + + @Override + public void addListener(ValueListener listener) { + addValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + @Override + public void removeListener(ValueListener listener) { + removeValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + protected void fireValueChanged(Object prevValue, Object value) { + for (ValueChangeListener listener : new ArrayList<>(listeners)) { + listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); + } + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + listeners.remove(listener); + } + + @Override + public void addValidator(Validator validator) { + if (!validators.contains(validator)) + validators.add(validator); + } + + @Override + public void removeValidator(Validator validator) { + validators.remove(validator); + } + + @Override + public Collection getValidators() { + return Collections.unmodifiableCollection(validators); + } + + @Override + public boolean isValid() { + try { + validate(); + return true; + } catch (ValidationException e) { + return false; + } + } + + protected boolean isEmpty(Object value) { + return value == null; + } + + @Override + public void validate() throws ValidationException { + if (!isVisible() || !isEditableWithParent() || !isEnabled()) + return; + + Object value = getValue(); + if (isEmpty(value)) { + if (isRequired()) + throw new RequiredValueMissingException(requiredMessage, this); + else + return; + } + + for (Validator validator : validators) { + validator.validate(value); + } + } + + @Override + public boolean isRequired() { + return required; + } + + @Override + public void setRequired(boolean required) { + this.required = required; + updateMissingValueState(); + } + + public void updateMissingValueState() { + if (impl != null) { + decorateMissingValue(impl, required); + } + } + + protected void decorateMissingValue(JComponent jComponent, boolean missingValueState) { + jComponent.setBackground(missingValueState ? requiredBgColor : defaultBgColor); + } + + protected void initRequired(MetaPropertyPath metaPropertyPath) { + MetaProperty metaProperty = metaPropertyPath.getMetaProperty(); + + boolean newRequired = metaProperty.isMandatory(); + Object notNullUiComponent = metaProperty.getAnnotations().get(NotNull.class.getName() + "_notnull_ui_component"); + if (Boolean.TRUE.equals(notNullUiComponent)) { + newRequired = true; + } + setRequired(newRequired); + + if (StringUtils.isEmpty(getRequiredMessage())) { + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + setRequiredMessage(messageTools.getDefaultRequiredMessage(metaPropertyPath.getMetaClass(), metaPropertyPath.toString())); + } + } + + protected void initBeanValidator() { + MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + MetaClass propertyEnclosingMetaClass = metadataTools.getPropertyEnclosingMetaClass(metaPropertyPath); + Class enclosingJavaClass = propertyEnclosingMetaClass.getJavaClass(); + + if (enclosingJavaClass != KeyValueEntity.class + && !DynamicAttributesUtils.isDynamicAttribute(metaProperty)) { + BeanValidation beanValidation = AppBeans.get(BeanValidation.NAME); + javax.validation.Validator validator = beanValidation.getValidator(); + BeanDescriptor beanDescriptor = validator.getConstraintsForClass(enclosingJavaClass); + + if (beanDescriptor.isBeanConstrained()) { + addValidator(new BeanValidator(enclosingJavaClass, metaProperty.getName())); + } + } + } + + protected void disableBeanValidator() { + if (validators != null) { + for (Validator validator : new ArrayList<>(validators)) { + if (validator instanceof BeanValidator) { + validators.remove(validator); + } + } + } + } + + @Override + public void setRequiredMessage(String msg) { + requiredMessage = msg; + } + + @Override + public String getRequiredMessage() { + return requiredMessage; + } + + @Override + public boolean isEditable() { + return editable; + } + + @Override + public void setEditable(boolean editable) { + if (this.editable == editable) { + return; + } + + this.editable = editable; + + boolean parentEditable = true; + if (parent instanceof ChildEditableController) { + parentEditable = ((ChildEditableController) parent).isEditable(); + } + boolean finalEditable = parentEditable && editable; + + setEditableToComponent(finalEditable); + } + + protected abstract void setEditableToComponent(boolean editable); + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + Datasource datasource = getDatasource(); + MetaPropertyPath metaPropertyPath = getMetaPropertyPath(); + + if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { + return getClass().getSimpleName() + "_" + datasource.getId() + "_" + metaPropertyPath.toString(); + } + + return getClass().getSimpleName(); + } + + protected void resolveMetaPropertyPath(MetaClass metaClass, String property) { + metaPropertyPath = getResolvedMetaPropertyPath(metaClass, property); + this.metaProperty = metaPropertyPath.getMetaProperty(); + } + + protected MetaPropertyPath getResolvedMetaPropertyPath(MetaClass metaClass, String property) { + MetaPropertyPath metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) + .resolveMetaPropertyPath(metaClass, property); + Preconditions.checkNotNullArgument(metaPropertyPath, "Could not resolve property path '%s' in '%s'", property, metaClass); + + return metaPropertyPath; + } + + @Override + public void setParent(com.haulmont.cuba.gui.components.Component parent) { + if (this.parent instanceof EditableChangeNotifier + && parentEditableChangeListener != null) { + ((EditableChangeNotifier) this.parent).removeEditableChangeListener(parentEditableChangeListener); + + parentEditableChangeListener = null; + } + + super.setParent(parent); + + if (parent instanceof EditableChangeNotifier) { + parentEditableChangeListener = event -> { + boolean parentEditable = event.getSource().isEditable(); + boolean finalEditable = parentEditable && editable; + setEditableToComponent(finalEditable); + }; + ((EditableChangeNotifier) parent).addEditableChangeListener(parentEditableChangeListener); + + Editable parentEditable = (Editable) parent; + if (!parentEditable.isEditable()) { + setEditableToComponent(false); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractOptionsField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractOptionsField.java index 93b02889ea..043a3b04c5 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractOptionsField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractOptionsField.java @@ -1,464 +1,464 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; -import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.gui.components.CaptionMode; -import com.haulmont.cuba.gui.components.OptionsField; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; - -public abstract class DesktopAbstractOptionsField - extends - DesktopAbstractField - implements - OptionsField { - - protected CaptionMode captionMode = CaptionMode.ITEM; - protected String captionProperty; - protected String descProperty; - - protected CollectionDatasource, Object> optionsDatasource; - protected List optionsList; - protected Map optionsMap; - protected Class optionsEnum; - - protected Datasource datasource; - protected boolean updatingInstance; - - protected Object prevValue; - - protected Messages messages = AppBeans.get(Messages.NAME); - - protected CaptionFormatter captionFormatter; - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemChangeListener securityItemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - public interface CaptionFormatter { - String formatValue(T value); - } - - @Override - public CollectionDatasource getOptionsDatasource() { - return optionsDatasource; - } - - @Override - public void setOptionsDatasource(CollectionDatasource datasource) { - this.optionsDatasource = datasource; - - assignAutoDebugId(); - } - - @Override - public List getOptionsList() { - return optionsList; - } - - @Override - public void setOptionsList(List optionsList) { - this.optionsList = optionsList; - this.captionMode = CaptionMode.ITEM; // works as web version - } - - @Override - public Map getOptionsMap() { - return optionsMap; - } - - @Override - public void setOptionsMap(Map map) { - optionsMap = map; - } - - @Override - public Class getOptionsEnum() { - return optionsEnum; - } - - @Override - public void setOptionsEnum(Class optionsEnum) { - this.optionsEnum = optionsEnum; - this.captionMode = CaptionMode.ITEM; // works as web version - } - - @Override - public CaptionMode getCaptionMode() { - return captionMode; - } - - @Override - public void setCaptionMode(CaptionMode captionMode) { - this.captionMode = captionMode; - } - - @Override - public String getCaptionProperty() { - return captionProperty; - } - - @Override - public void setCaptionProperty(String captionProperty) { - this.captionProperty = captionProperty; - } - - @Override - public String getDescriptionProperty() { - return descProperty; - } - - @Override - public void setDescriptionProperty(String descProperty) { - this.descProperty = descProperty; - } - - @Override - public void setDatasource(Datasource datasource, String property) { - this.datasource = datasource; - - if (datasource == null) { - setValue(null); - return; - } - - MetaClass metaClass = datasource.getMetaClass(); - resolveMetaPropertyPath(metaClass, property); - - itemChangeListener = e -> { - if (updatingInstance) - return; - Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); - updateComponent(value); - fireChangeListeners(value); - }; - // noinspection unchecked - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) - return; - if (e.getProperty().equals(metaPropertyPath.toString())) { - updateComponent(e.getValue()); - fireChangeListeners(e.getValue()); - } - }; - // noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - initRequired(metaPropertyPath); - - if (metaProperty.getRange().isEnum()) { - Enumeration enumeration = metaProperty.getRange().asEnumeration(); - @SuppressWarnings("unchecked") - Class javaClass = enumeration.getJavaClass(); - - setOptionsList(Arrays.asList(javaClass.getEnumConstants())); - setCaptionMode(CaptionMode.ITEM); - } - - if (DynamicAttributesUtils.isDynamicAttribute(metaProperty)) { - CategoryAttribute categoryAttribute = DynamicAttributesUtils.getCategoryAttribute(metaProperty); - if (categoryAttribute != null && categoryAttribute.getDataType() == PropertyType.ENUMERATION) { - setOptionsMap(categoryAttribute.getLocalizedEnumerationMap()); - } - } - - if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { - Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); - updateComponent(newValue); - fireChangeListeners(newValue); - } - - if (metaProperty.isReadOnly()) { - setEditable(false); - } - - handleFilteredAttributes(this, this.datasource, metaPropertyPath); - securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); - // noinspection unchecked - this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); - - initBeanValidator(); - } - - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = newValue; - if (!InstanceUtils.propertyValueEquals(oldValue, newValue)) { - fireValueChanged(oldValue, newValue); - } - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - @Override - public T getValue() { - Object selectedItem = getSelectedItem(); - return selectedItem != null && selectedItem instanceof ValueWrapper ? - (T) ((ValueWrapper) selectedItem).getValue() : null; - } - - protected void updateComponent(Object value) { - if (value == null) { - setSelectedItem(null); - return; - } - - Object selectedItem; - if (optionsMap != null) { - for (Map.Entry entry : optionsMap.entrySet()) { - if (value.equals(entry.getValue())) { - setSelectedItem(new MapKeyWrapper(entry.getKey())); - return; - } - } - setSelectedItem(null); - return; - } - - if (!(value instanceof ValueWrapper)) { - if (value instanceof Entity) { - selectedItem = new EntityWrapper((Entity) value); - } else { - selectedItem = new ObjectWrapper(value); - } - } else { - selectedItem = value; - } - setSelectedItem(selectedItem); - } - - protected void updateInstance(Object value) { - updatingInstance = true; - try { - if (datasource != null && metaProperty != null && datasource.getItem() != null) { - InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); - } - } finally { - updatingInstance = false; - } - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (!InstanceUtils.propertyValueEquals(prevValue, value)) { - updateInstance(value); - updateComponent(value); - fireChangeListeners(value); - } else { - updateComponent(prevValue); - } - } - - /** - * Set custom caption formatter. This formatter is only used when options are explicitly - * set with {@link #setOptionsMap(java.util.Map)} or {@link #setOptionsList(java.util.List)} - * @param captionFormatter - */ - public void setCaptionFormatter(CaptionFormatter captionFormatter) { - this.captionFormatter = captionFormatter; - } - - protected String getDisplayString(Entity entity) { - if (entity == null) - return ""; - - String captionValue; - if (captionMode.equals(CaptionMode.PROPERTY) && !StringUtils.isBlank(captionProperty)) { - captionValue = entity.getValueEx(captionProperty); - } else { - captionValue = entity.getInstanceName(); - } - - if (captionValue == null) - captionValue = ""; - - return captionValue; - } - - protected abstract Object getSelectedItem(); - protected abstract void setSelectedItem(Object item); - - public interface ValueWrapper { - T getValue(); - } - - public class EntityWrapper implements ValueWrapper { - - private Entity entity; - - public EntityWrapper(Entity entity) { - this.entity = entity; - } - - @Override - public Entity getValue() { - return entity; - } - - @Override - public String toString() { - if (captionFormatter != null) { - return captionFormatter.formatValue(entity); - } - return getDisplayString(entity); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof DesktopAbstractOptionsField.EntityWrapper) { - DesktopAbstractOptionsField.EntityWrapper that = (EntityWrapper) obj; - return InstanceUtils.propertyValueEquals(this.entity, that.entity); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - if (entity != null) { - return entity.hashCode(); - } - return 0; - } - } - - public class MapKeyWrapper implements ValueWrapper { - - private String key; - - public MapKeyWrapper(String key) { - this.key = key; - } - - @Override - public Object getValue() { - return optionsMap.get(key); - } - - @Override - public String toString() { - return key; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof DesktopAbstractOptionsField.MapKeyWrapper) { - DesktopAbstractOptionsField.MapKeyWrapper other = (DesktopAbstractOptionsField.MapKeyWrapper) obj; - return StringUtils.equals(this.key, other.key); - } - return false; - } - - @Override - public int hashCode() { - if (key != null) { - return key.hashCode(); - } - return 0; - } - } - - public class ObjectWrapper implements ValueWrapper { - - private Object obj; - - public ObjectWrapper(Object obj) { - this.obj = obj; - } - - @Override - public Object getValue() { - return obj; - } - - @Override - public String toString() { - if (captionFormatter != null) { - return captionFormatter.formatValue(obj); - } - - if (obj == null) - return ""; - - if (obj instanceof Instance) - return InstanceUtils.getInstanceName((Instance) obj); - - if (obj instanceof Enum) - return messages.getMessage((Enum) obj); - - return obj.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof DesktopAbstractOptionsField.ObjectWrapper) { - DesktopAbstractOptionsField.ObjectWrapper anotherWrapper = (DesktopAbstractOptionsField.ObjectWrapper) obj; - return InstanceUtils.propertyValueEquals(this.obj, anotherWrapper.obj); - } - return false; - } - - @Override - public int hashCode() { - if (obj != null) { - return obj.hashCode(); - } - return 0; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; +import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.gui.components.CaptionMode; +import com.haulmont.cuba.gui.components.OptionsField; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; + +public abstract class DesktopAbstractOptionsField + extends + DesktopAbstractField + implements + OptionsField { + + protected CaptionMode captionMode = CaptionMode.ITEM; + protected String captionProperty; + protected String descProperty; + + protected CollectionDatasource, Object> optionsDatasource; + protected List optionsList; + protected Map optionsMap; + protected Class optionsEnum; + + protected Datasource datasource; + protected boolean updatingInstance; + + protected Object prevValue; + + protected Messages messages = AppBeans.get(Messages.NAME); + + protected CaptionFormatter captionFormatter; + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemChangeListener securityItemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + public interface CaptionFormatter { + String formatValue(T value); + } + + @Override + public CollectionDatasource getOptionsDatasource() { + return optionsDatasource; + } + + @Override + public void setOptionsDatasource(CollectionDatasource datasource) { + this.optionsDatasource = datasource; + + assignAutoDebugId(); + } + + @Override + public List getOptionsList() { + return optionsList; + } + + @Override + public void setOptionsList(List optionsList) { + this.optionsList = optionsList; + this.captionMode = CaptionMode.ITEM; // works as web version + } + + @Override + public Map getOptionsMap() { + return optionsMap; + } + + @Override + public void setOptionsMap(Map map) { + optionsMap = map; + } + + @Override + public Class getOptionsEnum() { + return optionsEnum; + } + + @Override + public void setOptionsEnum(Class optionsEnum) { + this.optionsEnum = optionsEnum; + this.captionMode = CaptionMode.ITEM; // works as web version + } + + @Override + public CaptionMode getCaptionMode() { + return captionMode; + } + + @Override + public void setCaptionMode(CaptionMode captionMode) { + this.captionMode = captionMode; + } + + @Override + public String getCaptionProperty() { + return captionProperty; + } + + @Override + public void setCaptionProperty(String captionProperty) { + this.captionProperty = captionProperty; + } + + @Override + public String getDescriptionProperty() { + return descProperty; + } + + @Override + public void setDescriptionProperty(String descProperty) { + this.descProperty = descProperty; + } + + @Override + public void setDatasource(Datasource datasource, String property) { + this.datasource = datasource; + + if (datasource == null) { + setValue(null); + return; + } + + MetaClass metaClass = datasource.getMetaClass(); + resolveMetaPropertyPath(metaClass, property); + + itemChangeListener = e -> { + if (updatingInstance) + return; + Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); + updateComponent(value); + fireChangeListeners(value); + }; + // noinspection unchecked + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) + return; + if (e.getProperty().equals(metaPropertyPath.toString())) { + updateComponent(e.getValue()); + fireChangeListeners(e.getValue()); + } + }; + // noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + initRequired(metaPropertyPath); + + if (metaProperty.getRange().isEnum()) { + Enumeration enumeration = metaProperty.getRange().asEnumeration(); + @SuppressWarnings("unchecked") + Class javaClass = enumeration.getJavaClass(); + + setOptionsList(Arrays.asList(javaClass.getEnumConstants())); + setCaptionMode(CaptionMode.ITEM); + } + + if (DynamicAttributesUtils.isDynamicAttribute(metaProperty)) { + CategoryAttribute categoryAttribute = DynamicAttributesUtils.getCategoryAttribute(metaProperty); + if (categoryAttribute != null && categoryAttribute.getDataType() == PropertyType.ENUMERATION) { + setOptionsMap(categoryAttribute.getLocalizedEnumerationMap()); + } + } + + if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { + Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); + updateComponent(newValue); + fireChangeListeners(newValue); + } + + if (metaProperty.isReadOnly()) { + setEditable(false); + } + + handleFilteredAttributes(this, this.datasource, metaPropertyPath); + securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); + // noinspection unchecked + this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); + + initBeanValidator(); + } + + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = newValue; + if (!InstanceUtils.propertyValueEquals(oldValue, newValue)) { + fireValueChanged(oldValue, newValue); + } + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + @Override + public T getValue() { + Object selectedItem = getSelectedItem(); + return selectedItem != null && selectedItem instanceof ValueWrapper ? + (T) ((ValueWrapper) selectedItem).getValue() : null; + } + + protected void updateComponent(Object value) { + if (value == null) { + setSelectedItem(null); + return; + } + + Object selectedItem; + if (optionsMap != null) { + for (Map.Entry entry : optionsMap.entrySet()) { + if (value.equals(entry.getValue())) { + setSelectedItem(new MapKeyWrapper(entry.getKey())); + return; + } + } + setSelectedItem(null); + return; + } + + if (!(value instanceof ValueWrapper)) { + if (value instanceof Entity) { + selectedItem = new EntityWrapper((Entity) value); + } else { + selectedItem = new ObjectWrapper(value); + } + } else { + selectedItem = value; + } + setSelectedItem(selectedItem); + } + + protected void updateInstance(Object value) { + updatingInstance = true; + try { + if (datasource != null && metaProperty != null && datasource.getItem() != null) { + InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); + } + } finally { + updatingInstance = false; + } + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (!InstanceUtils.propertyValueEquals(prevValue, value)) { + updateInstance(value); + updateComponent(value); + fireChangeListeners(value); + } else { + updateComponent(prevValue); + } + } + + /** + * Set custom caption formatter. This formatter is only used when options are explicitly + * set with {@link #setOptionsMap(java.util.Map)} or {@link #setOptionsList(java.util.List)} + * @param captionFormatter + */ + public void setCaptionFormatter(CaptionFormatter captionFormatter) { + this.captionFormatter = captionFormatter; + } + + protected String getDisplayString(Entity entity) { + if (entity == null) + return ""; + + String captionValue; + if (captionMode.equals(CaptionMode.PROPERTY) && !StringUtils.isBlank(captionProperty)) { + captionValue = entity.getValueEx(captionProperty); + } else { + captionValue = entity.getInstanceName(); + } + + if (captionValue == null) + captionValue = ""; + + return captionValue; + } + + protected abstract Object getSelectedItem(); + protected abstract void setSelectedItem(Object item); + + public interface ValueWrapper { + T getValue(); + } + + public class EntityWrapper implements ValueWrapper { + + private Entity entity; + + public EntityWrapper(Entity entity) { + this.entity = entity; + } + + @Override + public Entity getValue() { + return entity; + } + + @Override + public String toString() { + if (captionFormatter != null) { + return captionFormatter.formatValue(entity); + } + return getDisplayString(entity); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DesktopAbstractOptionsField.EntityWrapper) { + DesktopAbstractOptionsField.EntityWrapper that = (EntityWrapper) obj; + return InstanceUtils.propertyValueEquals(this.entity, that.entity); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + if (entity != null) { + return entity.hashCode(); + } + return 0; + } + } + + public class MapKeyWrapper implements ValueWrapper { + + private String key; + + public MapKeyWrapper(String key) { + this.key = key; + } + + @Override + public Object getValue() { + return optionsMap.get(key); + } + + @Override + public String toString() { + return key; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DesktopAbstractOptionsField.MapKeyWrapper) { + DesktopAbstractOptionsField.MapKeyWrapper other = (DesktopAbstractOptionsField.MapKeyWrapper) obj; + return StringUtils.equals(this.key, other.key); + } + return false; + } + + @Override + public int hashCode() { + if (key != null) { + return key.hashCode(); + } + return 0; + } + } + + public class ObjectWrapper implements ValueWrapper { + + private Object obj; + + public ObjectWrapper(Object obj) { + this.obj = obj; + } + + @Override + public Object getValue() { + return obj; + } + + @Override + public String toString() { + if (captionFormatter != null) { + return captionFormatter.formatValue(obj); + } + + if (obj == null) + return ""; + + if (obj instanceof Instance) + return InstanceUtils.getInstanceName((Instance) obj); + + if (obj instanceof Enum) + return messages.getMessage((Enum) obj); + + return obj.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DesktopAbstractOptionsField.ObjectWrapper) { + DesktopAbstractOptionsField.ObjectWrapper anotherWrapper = (DesktopAbstractOptionsField.ObjectWrapper) obj; + return InstanceUtils.propertyValueEquals(this.obj, anotherWrapper.obj); + } + return false; + } + + @Override + public int hashCode() { + if (obj != null) { + return obj.hashCode(); + } + return 0; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractTable.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractTable.java index 7c61d4cb44..4d3b649387 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractTable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopAbstractTable.java @@ -1,2650 +1,2650 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.google.common.collect.Lists; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.data.AnyTableModelAdapter; -import com.haulmont.cuba.desktop.gui.data.RowSorterImpl; -import com.haulmont.cuba.desktop.sys.FontDialog; -import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; -import com.haulmont.cuba.desktop.sys.vcl.Flushable; -import com.haulmont.cuba.desktop.sys.vcl.FocusableTable; -import com.haulmont.cuba.desktop.sys.vcl.TableFocusManager; -import com.haulmont.cuba.desktop.theme.DesktopTheme; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Formatter; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.components.formatters.CollectionFormatter; -import com.haulmont.cuba.gui.data.*; -import com.haulmont.cuba.gui.data.impl.CollectionDsActionsNotifier; -import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import com.haulmont.cuba.gui.presentations.Presentations; -import net.miginfocom.layout.CC; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Document; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.action.BoundAction; -import org.jdesktop.swingx.table.ColumnControlButton; -import org.jdesktop.swingx.table.TableColumnExt; -import org.jdesktop.swingx.table.TableColumnModelExt; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; - -import javax.annotation.Nullable; -import javax.swing.AbstractAction; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import java.awt.*; -import java.awt.Component; -import java.awt.event.*; -import java.util.*; -import java.util.List; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; -import static com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper.convertKeyCombination; -import static java.util.Collections.singletonList; - -public abstract class DesktopAbstractTable - extends DesktopAbstractActionsHolderComponent - implements Table, LookupComponent.LookupSelectionChangeNotifier { - - protected static final int DEFAULT_ROW_MARGIN = 4; - - protected boolean contextMenuEnabled = true; - protected MigLayout layout; - protected JPanel panel; - protected JPanel topPanel; - protected JScrollPane scrollPane; - protected AnyTableModelAdapter tableModel; - protected CollectionDatasource datasource; - protected ButtonsPanel buttonsPanel; - protected RowsCount rowsCount; - protected Map aggregationResult; - protected Map columns = new HashMap<>(); - protected List columnsOrder = new ArrayList<>(); - protected boolean sortable = true; - protected TableSettings tableSettings; - protected boolean editable; - protected List styleProviders; // lazy initialized list - protected IconProvider iconProvider; - - protected Action itemClickAction; - protected Action enterPressAction; - - protected boolean columnsInitialized = false; - protected int generatedColumnsCount = 0; - - protected boolean columnHeaderVisible = true; - - protected boolean textSelectionEnabled = false; - - protected boolean showSelection = true; - - // Indicates that model is being changed. - protected boolean isAdjusting = false; - - protected DesktopTableFieldFactory tableFieldFactory = new DesktopTableFieldFactory(); - - protected List editableColumns = new LinkedList<>(); - - protected Map requiredColumns = new HashMap<>(); - - protected Security security = AppBeans.get(Security.NAME); - - protected boolean columnAdjustRequired = false; - - protected boolean fontInitialized = false; - - protected int defaultRowHeight = 24; - protected int defaultEditableRowHeight = 28; - - protected Set selectedItems = Collections.emptySet(); - - protected Map printables = new HashMap<>(); - - protected Map fieldDatasources = new WeakHashMap<>(); - - // Manual control for content repaint process - protected boolean contentRepaintEnabled = true; - - protected Document defaultSettings; - protected boolean multiLineCells; - protected boolean settingsEnabled = true; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - protected CollectionDatasource.CollectionChangeListener securityCollectionChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - protected CollectionDsActionsNotifier collectionDsActionsNotifier; - - protected List lookupSelectionChangeListeners = new ArrayList<>(); - - protected DesktopAbstractTable() { - shortcutsDelegate.setAllowEnterShortcut(false); - } - - protected void initComponent() { - layout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); - panel = new JPanel(layout); - - topPanel = new JPanel(new BorderLayout()); - topPanel.setVisible(false); - panel.add(topPanel, "growx"); - - scrollPane = new JScrollPane(impl); - impl.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - impl.setFillsViewportHeight(true); - panel.add(scrollPane, "grow"); - - impl.setShowGrid(true); - impl.setGridColor(Color.lightGray); - - impl.addMouseListener( - new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { - handleClickAction(); - } - } - - @Override - public void mousePressed(MouseEvent e) { - showPopup(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - showPopup(e); - } - - protected void showPopup(MouseEvent e) { - if (e.isPopupTrigger() && contextMenuEnabled) { - // select row - Point p = e.getPoint(); - int viewRowIndex = impl.rowAtPoint(p); - - int rowNumber; - if (viewRowIndex >= 0) { - rowNumber = impl.convertRowIndexToModel(viewRowIndex); - } else { - rowNumber = -1; - } - ListSelectionModel model = impl.getSelectionModel(); - - if (!model.isSelectedIndex(rowNumber)) { - model.setSelectionInterval(rowNumber, rowNumber); - } - - // show popup menu - JPopupMenu popupMenu = createPopupMenu(); - if (popupMenu.getComponentCount() > 0) { - popupMenu.show(e.getComponent(), e.getX(), e.getY()); - } - } - } - } - ); - - ColumnControlButton columnControlButton = new ColumnControlButton(impl) { - @Override - protected ColumnVisibilityAction createColumnVisibilityAction(TableColumn column) { - ColumnVisibilityAction columnVisibilityAction = super.createColumnVisibilityAction(column); - - columnVisibilityAction.addPropertyChangeListener(evt -> { - if ("SwingSelectedKey".equals(evt.getPropertyName()) - && evt.getNewValue() instanceof Boolean) { - ColumnVisibilityAction action = (ColumnVisibilityAction) evt.getSource(); - - String columnName = action.getActionCommand(); - boolean collapsed = !((boolean) evt.getNewValue()); - - Column col = getColumn(columnName); - if (col != null) { - col.setCollapsed(collapsed); - } - } - }); - - return columnVisibilityAction; - } - }; - impl.setColumnControl(columnControlButton); - - impl.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter"); - impl.getActionMap().put("enter", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (enterPressAction != null) { - enterPressAction.actionPerform(DesktopAbstractTable.this); - } else { - handleClickAction(); - } - } - }); - - Messages messages = AppBeans.get(Messages.NAME); - // localize default column control actions - for (Object actionKey : impl.getActionMap().allKeys()) { - if ("column.packAll".equals(actionKey)) { - BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); - action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.packAll")); - } else if ("column.packSelected".equals(actionKey)) { - BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); - action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.packSelected")); - } else if ("column.horizontalScroll".equals(actionKey)) { - BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); - action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.horizontalScroll")); - } - } - - // Ability to configure fonts in table - // Add action to column control - String configureFontsLabel = messages.getMessage( - DesktopTable.class, "DesktopTable.configureFontsLabel"); - impl.getActionMap().put(ColumnControlButton.COLUMN_CONTROL_MARKER + "fonts", - new AbstractAction(configureFontsLabel) { - @Override - public void actionPerformed(ActionEvent e) { - Component rootComponent = SwingUtilities.getRoot(impl); - final FontDialog fontDialog = FontDialog.show(rootComponent, impl.getFont()); - fontDialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - Font result = fontDialog.getResult(); - if (result != null) { - impl.setFont(result); - packRows(); - } - } - }); - fontDialog.open(); - } - }); - - // Ability to reset settings - String resetSettingsLabel = messages.getMessage( - DesktopTable.class, "DesktopTable.resetSettings"); - impl.getActionMap().put(ColumnControlButton.COLUMN_CONTROL_MARKER + "resetSettings", - new AbstractAction(resetSettingsLabel) { - @Override - public void actionPerformed(ActionEvent e) { - resetPresentation(); - } - }); - - scrollPane.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - if (!columnsInitialized) { - adjustColumnHeaders(); - } - columnsInitialized = true; - } - }); - - // init default row height - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!fontInitialized) { - applyFont(impl, impl.getFont()); - } - } - }); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - CC cc = new CC().grow(); - MigLayoutHelper.applyWidth(cc, (int) widthSize.value, widthSize.unit, false); - layout.setComponentConstraints(scrollPane, cc); - } - - protected void handleClickAction() { - Action action = getItemClickAction(); - if (action == null) { - action = getEnterAction(); - if (action == null) { - action = getAction("edit"); - if (action == null) { - action = getAction("view"); - } - } - } - if (action != null && action.isEnabled() && action.isVisible()) { - Window window = ComponentsHelper.getWindow(DesktopAbstractTable.this); - if (window instanceof Window.Wrapper) { - window = ((Window.Wrapper) window).getWrappedWindow(); - } - - if (!(window instanceof Window.Lookup)) { - action.actionPerform(DesktopAbstractTable.this); - } else { - Window.Lookup lookup = (Window.Lookup) window; - - com.haulmont.cuba.gui.components.Component lookupComponent = lookup.getLookupComponent(); - if (lookupComponent != this) { - action.actionPerform(DesktopAbstractTable.this); - } else if (action.getId().equals(WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID)) { - action.actionPerform(DesktopAbstractTable.this); - } - } - } - } - - @Override - public void setLookupSelectHandler(Runnable selectHandler) { - setEnterPressAction(new com.haulmont.cuba.gui.components.AbstractAction( - WindowDelegate.LOOKUP_ENTER_PRESSED_ACTION_ID) { - @Override - public void actionPerform(com.haulmont.cuba.gui.components.Component component) { - selectHandler.run(); - } - }); - - setItemClickAction(new com.haulmont.cuba.gui.components.AbstractAction( - WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID) { - @Override - public void actionPerform(com.haulmont.cuba.gui.components.Component component) { - selectHandler.run(); - } - }); - } - - @Override - public Collection getLookupSelectedItems() { - return getSelected(); - } - - protected void refreshActionsState() { - for (Action action : getActions()) { - action.refreshState(); - } - } - - protected Action getEnterAction() { - for (Action action : getActions()) { - KeyCombination kc = action.getShortcutCombination(); - if (kc != null) { - if ((kc.getModifiers() == null || kc.getModifiers().length == 0) - && kc.getKey() == KeyCombination.Key.ENTER) { - return action; - } - } - } - return null; - } - - protected void readjustColumns() { - if (columnAdjustRequired) { - return; - } - - this.columnAdjustRequired = true; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - adjustColumnHeaders(); - - columnAdjustRequired = false; - } - }); - } - - protected void adjustColumnHeaders() { - List notInited = new LinkedList<>(); - int summaryWidth = 0; - int componentWidth = impl.getParent().getWidth(); - - // take into account only visible columns - Enumeration columnEnumeration = impl.getColumnModel().getColumns(); - while (columnEnumeration.hasMoreElements()) { - TableColumn tableColumn = columnEnumeration.nextElement(); - Column column = (Column) tableColumn.getIdentifier(); - - Integer width = column.getWidth(); - if (width != null) { - tableColumn.setPreferredWidth(width); - tableColumn.setWidth(width); - summaryWidth += width; - } else { - notInited.add(tableColumn); - } - } - - if (notInited.size() != impl.getColumnCount()) { - impl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - - if (!notInited.isEmpty() && (componentWidth > summaryWidth)) { - int defaultWidth = (componentWidth - summaryWidth) / notInited.size(); - for (TableColumn column : notInited) { - column.setPreferredWidth(Math.max(defaultWidth, column.getWidth())); - } - } - } - } - - protected abstract void initTableModel(CollectionDatasource datasource); - - @Override - public JComponent getComposition() { - return panel; - } - - @Override - public List getColumns() { - return Collections.unmodifiableList(columnsOrder); - } - - @Override - public Column getColumn(String id) { - for (Table.Column column : columnsOrder) { - if (column.getId().toString().equals(id)) { - return column; - } - } - return null; - } - - @Override - public void addColumn(Column column) { - checkNotNullArgument(column, "Column must be non null"); - - Object columnId = column.getId(); - columns.put(columnId, column); - columnsOrder.add(column); - - if (tableModel != null) { - tableModel.addColumn(column); - } - - if (datasource != null && column.isEditable() && columnId instanceof MetaPropertyPath) { - if (!editableColumns.contains(columnId)) { - editableColumns.add((MetaPropertyPath) columnId); - } - } - - setColumnIdentifiers(); - refresh(); - - column.setOwner(this); - - if (column.getFormatter() == null && columnId instanceof MetaPropertyPath) { - MetaProperty metaProperty = ((MetaPropertyPath) columnId).getMetaProperty(); - - if (Collection.class.isAssignableFrom(metaProperty.getJavaType())) { - final Formatter collectionFormatter = new CollectionFormatter(); - column.setFormatter(collectionFormatter); - } - } - } - - @Override - public void removeColumn(Column column) { - if (column == null) { - return; - } - - String name; - if (column.getId() instanceof MetaPropertyPath) { - MetaPropertyPath metaPropertyPath = (MetaPropertyPath) column.getId(); - name = metaPropertyPath.getMetaProperty().getName(); - - editableColumns.remove(metaPropertyPath); - } else { - name = column.getId().toString(); - } - - TableColumn tableColumn = null; - - Iterator columnIterator = getAllColumns().iterator(); - while (columnIterator.hasNext() && (tableColumn == null)) { - TableColumn xColumn = columnIterator.next(); - Object identifier = xColumn.getIdentifier(); - if (identifier instanceof String && identifier.equals(name)) { - tableColumn = xColumn; - } else if (column.equals(identifier)) { - tableColumn = xColumn; - } - } - - if (tableColumn != null) { - // store old cell editors / renderers - Map cellEditors = new HashMap<>(); - Map cellRenderers = new HashMap<>(); - - for (int i = 0; i < tableModel.getColumnCount(); i++) { - Column tableModelColumn = tableModel.getColumn(i); - - if (tableModel.isGeneratedColumn(tableModelColumn)) { - TableColumn oldColumn = getColumn(tableModelColumn); - - cellEditors.put(tableModelColumn.getId(), oldColumn.getCellEditor()); - cellRenderers.put(tableModelColumn.getId(), oldColumn.getCellRenderer()); - } - } - - impl.getColumnModel().removeColumn(tableColumn); - impl.removeColumn(tableColumn); - - columns.remove(column.getId()); - columnsOrder.remove(column); - - if (tableModel != null) { - tableModel.removeColumn(column); - } - - // reassign column identifiers - setColumnIdentifiers(); - - // reattach old generated columns - for (int i = 0; i < tableModel.getColumnCount(); i++) { - Column tableModelColumn = tableModel.getColumn(i); - - if (tableModel.isGeneratedColumn(tableModelColumn)) { - TableColumn oldColumn = getColumn(tableModelColumn); - if (cellEditors.containsKey(tableModelColumn.getId())) { - oldColumn.setCellEditor(cellEditors.get(tableModelColumn.getId())); - } - if (cellRenderers.containsKey(tableModelColumn.getId())) { - oldColumn.setCellRenderer(cellRenderers.get(tableModelColumn.getId())); - } - } - } - - packRows(); - repaintImplIfNeeded(); - } - - column.setOwner(null); - } - - @Override - public void setDatasource(final CollectionDatasource datasource) { - Preconditions.checkNotNullArgument(datasource, "datasource is null"); - - final Collection properties; - if (this.columns.isEmpty()) { - MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - - Collection paths = datasource.getView() != null ? - // if a view is specified - use view properties - metadataTools.getViewPropertyPaths(datasource.getView(), datasource.getMetaClass()) : - // otherwise use only string properties from meta-class - the temporary solution for KeyValue datasources - metadataTools.getPropertyPaths(datasource.getMetaClass()).stream() - .filter(mpp -> mpp.getRangeJavaClass().equals(String.class)) - .collect(Collectors.toList()); - - for (MetaPropertyPath metaPropertyPath : paths) { - MetaProperty property = metaPropertyPath.getMetaProperty(); - if (!property.getRange().getCardinality().isMany() && !metadataTools.isSystem(property)) { - Table.Column column = new Table.Column(metaPropertyPath); - - String propertyName = property.getName(); - MetaClass propertyMetaClass = metadataTools.getPropertyEnclosingMetaClass(metaPropertyPath); - - column.setCaption(messageTools.getPropertyCaption(propertyMetaClass, propertyName)); - column.setType(metaPropertyPath.getRangeJavaClass()); - - Element element = DocumentHelper.createElement("column"); - column.setXmlDescriptor(element); - - addColumn(column); - } - } - } - properties = this.columns.keySet(); - - this.datasource = datasource; - - collectionChangeListener = e -> { - switch (e.getOperation()) { - case CLEAR: - case REFRESH: - fieldDatasources.clear(); - break; - - case UPDATE: - case REMOVE: - for (Object entity : e.getItems()) { - fieldDatasources.remove(entity); - } - break; - } - }; - //noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - - initTableModel(datasource); - - initChangeListener(); - - setColumnIdentifiers(); - - // Major change in table columns behavior #PL-4853 - // We need not to recreate all columns on each table change after initTableModel -// impl.setAutoCreateColumnsFromModel(false); - - if (isSortable()) { - impl.setRowSorter(new RowSorterImpl(tableModel)); - } - - initSelectionListener(datasource); - - List editableColumns = null; - if (isEditable()) { - editableColumns = new LinkedList<>(); - } - - MetaClass metaClass = datasource.getMetaClass(); - for (final Object property : properties) { - final Table.Column column = this.columns.get(property); - -// todo implement setColumnHeader -// final String caption; -// if (column != null) { -// caption = StringUtils.capitalize(column.getCaption() != null ? column.getCaption() : getColumnCaption(property)); -// } else { -// caption = StringUtils.capitalize(getColumnCaption(property)); -// } -// -// setColumnHeader(property, caption); - - if (column != null) { - if (column.isCollapsed() && getColumnControlVisible()) { - TableColumn tableColumn = getColumn(column); - if (tableColumn instanceof TableColumnExt) { - ((TableColumnExt) tableColumn).setVisible(false); - } - } - - if (editableColumns != null && column.isEditable() && (property instanceof MetaPropertyPath)) { - MetaPropertyPath propertyPath = (MetaPropertyPath) property; - if (security.isEntityAttrUpdatePermitted(metaClass, property.toString())) { - editableColumns.add(propertyPath); - } - } - } - } - - if (editableColumns != null && !editableColumns.isEmpty()) { - setEditableColumns(editableColumns); - } - - List columnsOrder = new ArrayList<>(); - for (Table.Column column : this.columnsOrder) { - if (column.getId() instanceof MetaPropertyPath) { - MetaPropertyPath metaPropertyPath = (MetaPropertyPath) column.getId(); - if (security.isEntityAttrReadPermitted(metaClass, metaPropertyPath.toString())) { - columnsOrder.add(column.getId()); - } - } else { - columnsOrder.add(column.getId()); - } - } - - setVisibleColumns(columnsOrder); - - if (security.isSpecificPermitted(ShowInfoAction.ACTION_PERMISSION)) { - ShowInfoAction action = (ShowInfoAction) getAction(ShowInfoAction.ACTION_ID); - if (action == null) { - action = new ShowInfoAction(); - addAction(action); - } - action.setDatasource(datasource); - } - - securityCollectionChangeListener = e -> { - onDataChange(); - packRows(); - - // #PL-2035, reload selection from ds - Set selectedItems1 = getSelected(); - if (selectedItems1 == null) { - selectedItems1 = Collections.emptySet(); - } - - Set newSelection = new HashSet<>(); - for (E entity : selectedItems1) { - if (e.getDs().containsItem(entity.getId())) { - newSelection.add(entity); - } - } - - if (e.getDs().getState() == Datasource.State.VALID && e.getDs().getItem() != null) { - if (e.getDs().containsItem(e.getDs().getItem().getId())) { - newSelection.add((E) e.getDs().getItem()); - } - } - - if (newSelection.isEmpty()) { - setSelected((E) null); - } else { - setSelected(newSelection); - } - }; - // noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, securityCollectionChangeListener)); - - itemPropertyChangeListener = e -> { - List columns1 = getColumns(); - boolean find = false; - int i = 0; - while ((i < columns1.size()) & !find) { - Object columnId = columns1.get(i).getId(); - if (columnId instanceof MetaPropertyPath) { - String propertyName = ((MetaPropertyPath) columnId).getMetaProperty().getName(); - if (propertyName.equals(e.getProperty())) { - find = true; - } - } - i++; - } - if (find) { - onDataChange(); - } - packRows(); - }; - // noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - if (rowsCount != null) { - rowsCount.setDatasource(datasource); - } - - collectionDsActionsNotifier = new CollectionDsActionsNotifier(this); - collectionDsActionsNotifier.bind(datasource); - - for (Action action : getActions()) { - action.refreshState(); - } - - if (!canBeSorted(datasource)) - setSortable(false); - } - - protected boolean canBeSorted(CollectionDatasource datasource) { - //noinspection SimplifiableConditionalExpression - return datasource instanceof PropertyDatasource ? - ((PropertyDatasource) datasource).getProperty().getRange().isOrdered() : true; - } - - protected String getColumnCaption(Object columnId) { - if (columnId instanceof MetaPropertyPath) { - return ((MetaPropertyPath) columnId).getMetaProperty().getName(); - } else { - return columnId.toString(); - } - } - - protected void setColumnIdentifiers() { - int i = 0; - for (TableColumn tableColumn : getAllColumns()) { - Column column = columnsOrder.get(i++); - if (!(tableColumn.getIdentifier() instanceof Column)) { - tableColumn.setIdentifier(column); - } - } - } - - protected List getAllColumns() { - return ((TableColumnModelExt) impl.getColumnModel()).getColumns(true); - } - - protected void onDataChange() { - for (TableColumn tableColumn : getAllColumns()) { - TableCellEditor cellEditor = tableColumn.getCellEditor(); - if (cellEditor instanceof DesktopTableCellEditor) { - ((DesktopTableCellEditor) cellEditor).clearCache(); - } - } - repaintImplIfNeeded(); - } - - protected void initChangeListener() { - tableModel.addChangeListener(new AnyTableModelAdapter.DataChangeListener() { - - private boolean focused = false; - private ThreadLocal> selectionBackup = new ThreadLocal<>(); - private int scrollRowIndex = -1; - - @Override - public void beforeChange(boolean structureChanged) { - if (!structureChanged) - return; - - isAdjusting = true; - focused = impl.isFocusOwner(); - selectionBackup.set(selectedItems); - - JViewport viewport = (JViewport) impl.getParent(); - Point scrollPoint = viewport.getViewPosition(); - scrollRowIndex = impl.rowAtPoint(scrollPoint); - } - - @Override - public void afterChange(boolean structureChanged) { - if (!structureChanged) - return; - - isAdjusting = false; - applySelection(filterSelection(selectionBackup.get())); - selectionBackup.remove(); - - if (focused) { - impl.requestFocus(); - } else { - if (impl.getCellEditor() != null) { - if (!impl.getCellEditor().stopCellEditing()) { - impl.getCellEditor().cancelCellEditing(); - } - } - } - - TableFocusManager focusManager = ((FocusableTable) impl).getFocusManager(); - if (focusManager != null && scrollRowIndex >= 0) { - focusManager.scrollToSelectedRow(scrollRowIndex); - } - - // reassign identifiers for auto created columns - setColumnIdentifiers(); - } - - @SuppressWarnings("unchecked") - private Set filterSelection(Set selection) { - if (selection == null) - return Collections.emptySet(); - - Set newSelection = new HashSet<>(2 * selection.size()); - for (Entity item : selection) { - if (datasource.containsItem(item.getId())) { - newSelection.add((E) datasource.getItem(item.getId())); - } - } - return newSelection; - } - - private void applySelection(Set selection) { - int minimalSelectionRowIndex = Integer.MAX_VALUE; - if (!selection.isEmpty()) { - for (Entity entity : selection) { - int rowIndex = tableModel.getRowIndex(entity); - if (rowIndex < minimalSelectionRowIndex && rowIndex >= 0) { - minimalSelectionRowIndex = rowIndex; - } - } - } - - setSelected(selection); - - if (!selection.isEmpty()) { - if (focused) { - impl.requestFocus(); - } else { - if (impl.getCellEditor() != null) { - if (!impl.getCellEditor().stopCellEditing()) { - impl.getCellEditor().cancelCellEditing(); - } - } - } - - TableFocusManager focusManager = ((FocusableTable) impl).getFocusManager(); - if (focusManager != null) { - focusManager.scrollToSelectedRow(minimalSelectionRowIndex); - } - } - } - - @Override - public void dataSorted() { - clearGeneratedColumnsCache(); - packRows(); - } - }); - } - - protected void clearGeneratedColumnsCache() { - for (Column column : columnsOrder) { - if (tableModel.isGeneratedColumn(column)) { - TableColumn tableColumn = getColumn(column); - if (tableColumn != null) { - TableCellEditor tableCellEditor = tableColumn.getCellEditor(); - if (tableCellEditor instanceof DesktopTableCellEditor) { - ((DesktopTableCellEditor) tableCellEditor).clearCache(); - } - } - } - } - } - - // Get cell editor for editable column - protected TableCellEditor getCellEditor(int row, int column) { - - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - if (tableColumn.getIdentifier() instanceof Column) { - Column columnConf = (Column) tableColumn.getIdentifier(); - - if (editableColumns != null - && columnConf.getId() instanceof MetaPropertyPath - && editableColumns.contains(columnConf.getId())) { - - return tableFieldFactory.createEditComponent(row, columnConf); - } - } - - return null; - } - - protected class EditableColumnTableCellEditor extends AbstractCellEditor implements TableCellEditor { - protected com.haulmont.cuba.gui.components.Component cellComponent; - - public EditableColumnTableCellEditor(com.haulmont.cuba.gui.components.Component cellComponent) { - this.cellComponent = cellComponent; - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, - boolean isSelected, int row, int column) { - JComponent composition = DesktopComponentsHelper.getComposition(cellComponent); - composition.putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, table); - return composition; - } - - @Override - public boolean isCellEditable(EventObject e) { - return DesktopAbstractTable.this.isEditable() - && cellComponent instanceof Editable && ((Editable) cellComponent).isEditable(); - } - - @Override - public Object getCellEditorValue() { - flush(DesktopComponentsHelper.getComposition(cellComponent)); - impl.requestFocus(); - if (cellComponent instanceof HasValue) { - return ((Field) cellComponent).getValue(); - } - return null; - } - - protected void flush(Component component) { - if (component instanceof Flushable) { - ((Flushable) component).flushValue(); - } else if (component instanceof java.awt.Container) { - for (Component child : ((java.awt.Container) component).getComponents()) { - flush(child); - } - } - } - } - - protected class DesktopTableFieldFactory extends AbstractFieldFactory { - - public TableCellEditor createEditComponent(int row, Column columnConf) { - MetaPropertyPath mpp = (MetaPropertyPath) columnConf.getId(); - - Datasource fieldDatasource = getItemDatasource(tableModel.getItem(row)); - // create lookup - final com.haulmont.cuba.gui.components.Component columnComponent = createField(fieldDatasource, - mpp.getMetaProperty().getName(), columnConf.getXmlDescriptor()); - - if (columnComponent instanceof Field) { - Field cubaField = (Field) columnComponent; - - if (columnConf.getDescription() != null) { - cubaField.setDescription(columnConf.getDescription()); - } - if (requiredColumns.containsKey(columnConf)) { - cubaField.setRequired(true); - cubaField.setRequiredMessage(requiredColumns.get(columnConf)); - } - } - - if (columnComponent instanceof DesktopCheckBox) { - JCheckBox checkboxImpl = (JCheckBox) ((DesktopCheckBox) columnComponent).getComponent(); - checkboxImpl.setHorizontalAlignment(SwingConstants.CENTER); - } - - JComponent composition = DesktopComponentsHelper.getComposition(columnComponent); - Color color = UIManager.getColor("Table:\"Table.cellRenderer\".background"); - composition.setBackground(new Color(color.getRGB())); - composition.setForeground(impl.getForeground()); - composition.setFont(impl.getFont()); - - if (columnConf.getWidth() != null) { - columnComponent.setWidth(columnConf.getWidth() + "px"); - } else { - columnComponent.setWidth("100%"); - } - - if (columnComponent instanceof BelongToFrame) { - BelongToFrame belongToFrame = (BelongToFrame) columnComponent; - if (belongToFrame.getFrame() == null) { - belongToFrame.setFrame(getFrame()); - } - } - - applyPermissions(columnComponent); - - columnComponent.setParent(DesktopAbstractTable.this); - - return new EditableColumnTableCellEditor(columnComponent); - } - - protected void applyPermissions(com.haulmont.cuba.gui.components.Component columnComponent) { - if (columnComponent instanceof DatasourceComponent) { - DatasourceComponent dsComponent = (DatasourceComponent) columnComponent; - MetaPropertyPath propertyPath = dsComponent.getMetaPropertyPath(); - - if (propertyPath != null) { - MetaClass metaClass = dsComponent.getDatasource().getMetaClass(); - dsComponent.setEditable(dsComponent.isEditable() - && security.isEntityAttrUpdatePermitted(metaClass, propertyPath.toString())); - } - } - } - - @Override - @Nullable - protected CollectionDatasource getOptionsDatasource(Datasource fieldDatasource, String propertyId) { - if (datasource == null) - throw new IllegalStateException("Table datasource is null"); - - MetaPropertyPath metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) - .resolveMetaPropertyPath(datasource.getMetaClass(), propertyId); - Column columnConf = columns.get(metaPropertyPath); - - final DsContext dsContext = datasource.getDsContext(); - - String optDsName = columnConf.getXmlDescriptor() != null ? - columnConf.getXmlDescriptor().attributeValue("optionsDatasource") : ""; - - if (StringUtils.isBlank(optDsName)) { - return null; - } else { - CollectionDatasource ds = (CollectionDatasource) dsContext.get(optDsName); - if (ds == null) - throw new IllegalStateException("Options datasource not found: " + optDsName); - - return ds; - } - } - } - - protected void initSelectionListener(final CollectionDatasource datasource) { - impl.getSelectionModel().addListSelectionListener( - new ListSelectionListener() { - @Override - @SuppressWarnings("unchecked") - public void valueChanged(ListSelectionEvent e) { - if (e.getValueIsAdjusting() || datasource == null) { - return; - } - - selectedItems = getSelected(); - - if (selectedItems.isEmpty()) { - Entity dsItem = datasource.getItemIfValid(); - datasource.setItem(null); - - if (dsItem == null) { - // in this case item change event will not be generated - refreshActionsState(); - } - } else { - // reset selection and select new item - if (isMultiSelect()) { - datasource.setItem(null); - } - - Entity newItem = selectedItems.iterator().next(); - Entity dsItem = datasource.getItemIfValid(); - datasource.setItem(newItem); - - if (ObjectUtils.equals(dsItem, newItem)) { - // in this case item change event will not be generated - refreshActionsState(); - } - } - - LookupSelectionChangeEvent selectionChangeEvent = - new LookupSelectionChangeEvent(DesktopAbstractTable.this); - for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { - listener.lookupValueChanged(selectionChangeEvent); - } - } - } - ); - } - - protected void setVisibleColumns(List columnsOrder) { - for (TableColumn tableColumn : getAllColumns()) { - Column columnIdentifier = (Column) tableColumn.getIdentifier(); - if (!columnsOrder.contains(columnIdentifier.getId())) { - impl.removeColumn(tableColumn); - } - } - } - - @Override - public boolean isContextMenuEnabled() { - return contextMenuEnabled; - } - - @Override - public void setContextMenuEnabled(boolean contextMenuEnabled) { - this.contextMenuEnabled = contextMenuEnabled; - } - - protected void setEditableColumns(List editableColumns) { - this.editableColumns.clear(); - this.editableColumns.addAll(editableColumns); - } - - @Override - public void setRequired(Table.Column column, boolean required, String message) { - if (required) - requiredColumns.put(column, message); - else - requiredColumns.remove(column); - } - - @Override - public void addValidator(Column column, Field.Validator validator) { - } - - @Override - public void addValidator(Field.Validator validator) { - } - - @Override - public void setEnterPressAction(Action action) { - enterPressAction = action; - } - - @Override - public Action getEnterPressAction() { - return enterPressAction; - } - - @Override - public void setItemClickAction(Action action) { - if (itemClickAction != null) { - removeAction(itemClickAction); - } - itemClickAction = action; - if (!getActions().contains(action)) { - addAction(action); - } - } - - @Override - public Action getItemClickAction() { - return itemClickAction; - } - - @Override - public List getNotCollapsedColumns() { - List visibleColumns = new LinkedList<>(); - for (Column column : columnsOrder) { - TableColumnExt columnExt = impl.getColumnExt(column); - if (columnExt != null && columnExt.isVisible()) { - visibleColumns.add(column); - } - } - return visibleColumns; - } - - @Override - public void setSortable(boolean sortable) { - this.sortable = sortable && canBeSorted(datasource); - if (this.sortable) { - if (tableModel != null && impl.getRowSorter() == null) { - impl.setRowSorter(new RowSorterImpl(tableModel)); - } - } else { - impl.setRowSorter(null); - } - } - - @Override - public boolean isSortable() { - return sortable; - } - - @Override - public void setColumnReorderingAllowed(boolean columnReorderingAllowed) { - JTableHeader tableHeader = impl.getTableHeader(); - tableHeader.setReorderingAllowed(columnReorderingAllowed); - } - - @Override - public boolean getColumnReorderingAllowed() { - JTableHeader tableHeader = impl.getTableHeader(); - return tableHeader.getReorderingAllowed(); - } - - @Override - public void setColumnControlVisible(boolean columnCollapsingAllowed) { - impl.setColumnControlVisible(columnCollapsingAllowed); - } - - @Override - public boolean getColumnControlVisible() { - return impl.isColumnControlVisible(); - } - - @Override - public void setAggregatable(boolean aggregatable) { - } - - @Override - public Map getAggregationResults() { - return Collections.emptyMap(); - } - - @Override - public boolean isAggregatable() { - return false; - } - - @Override - public void setAggregationStyle(AggregationStyle aggregationStyle) { - } - - @Override - public AggregationStyle getAggregationStyle() { - return null; - } - - @Override - public void setShowTotalAggregation(boolean showAggregation) { - } - - @Override - public boolean isShowTotalAggregation() { - return false; - } - - @Override - public void sortBy(Object propertyId, boolean ascending) { - if (isSortable()) { - for (int i = 0; i < columnsOrder.size(); i++) { - Column column = columnsOrder.get(i); - if (column.getId().equals(propertyId)) { - SortOrder sortOrder = ascending ? SortOrder.ASCENDING : SortOrder.DESCENDING; - tableModel.sort(singletonList(new RowSorter.SortKey(i, sortOrder))); - onDataChange(); - packRows(); - break; - } - } - } - } - - @Override - public void sort(String columnId, SortDirection direction) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalArgumentException("Unable to find column " + columnId); - } - - if (isSortable()) { - SortOrder sortOrder = direction == SortDirection.ASCENDING ? SortOrder.ASCENDING : SortOrder.DESCENDING; - int columnIndex = columnsOrder.indexOf(column); - tableModel.sort(singletonList(new RowSorter.SortKey(columnIndex, sortOrder))); - onDataChange(); - packRows(); - } - } - - @Nullable - @Override - public SortInfo getSortInfo() { - // SortInfo is returned only for sorting triggered from UI - List sortKeys = impl.getRowSorter().getSortKeys(); - if (CollectionUtils.isNotEmpty(sortKeys)) { - RowSorter.SortKey sortKey = sortKeys.get(0); - - return new SortInfo(columnsOrder.get(sortKey.getColumn()).getId(), - SortOrder.ASCENDING.equals(sortKey.getSortOrder())); - } - return null; - } - - @Override - public void selectAll() { - if (isMultiSelect()) { - if (impl.getRowCount() > 0) { - impl.setRowSelectionInterval(0, impl.getModel().getRowCount() - 1); - } - } - } - - @Override - public RowsCount getRowsCount() { - return rowsCount; - } - - @Override - public void setRowsCount(RowsCount rowsCount) { - if (this.rowsCount != null) { - topPanel.remove(DesktopComponentsHelper.getComposition(this.rowsCount)); - } - this.rowsCount = rowsCount; - if (rowsCount != null) { - topPanel.add(DesktopComponentsHelper.getComposition(rowsCount), BorderLayout.EAST); - topPanel.setVisible(true); - } - } - - @Override - public void setMultiLineCells(boolean multiLineCells) { - this.multiLineCells = multiLineCells; - } - - @Override - public boolean isMultiLineCells() { - return multiLineCells; - } - - @Override - public void setRowHeaderMode(RowHeaderMode mode) { - } - - @Override - public void setStyleProvider(StyleProvider styleProvider) { - if (styleProvider != null) { - if (this.styleProviders == null) { - this.styleProviders = new LinkedList<>(); - } else { - this.styleProviders.clear(); - } - - this.styleProviders.add(styleProvider); - } else { - this.styleProviders = null; - } - - refreshCellStyles(); - } - - @Override - public void addStyleProvider(StyleProvider styleProvider) { - if (this.styleProviders == null) { - this.styleProviders = new LinkedList<>(); - } - - if (!this.styleProviders.contains(styleProvider)) { - this.styleProviders.add(styleProvider); - - refreshCellStyles(); - } - } - - @Override - public void removeStyleProvider(StyleProvider styleProvider) { - if (this.styleProviders != null) { - if (this.styleProviders.remove(styleProvider)) { - refreshCellStyles(); - } - } - } - - protected void refreshCellStyles() { - for (Column col : columnsOrder) { - // generated column handles styles himself - if (!tableModel.isGeneratedColumn(col)) { - TableColumn tableColumn = getColumn(col); - - // If column is not hidden by security - if (tableColumn != null) { - boolean useStyledCells = styleProviders != null && !styleProviders.isEmpty(); - tableColumn.setCellRenderer(useStyledCells ? new StylingCellRenderer() : null); - } - } - } - } - - @Override - public void setIconProvider(IconProvider iconProvider) { - this.iconProvider = iconProvider; // TODO Kozlov: PL-2411. - } - - @Override - public int getRowHeaderWidth() { - return 0; // TODO Kozlov: PL-2411. - } - - @Override - public void setRowHeaderWidth(int width) { - // TODO Kozlov: PL-2411. - } - - @Override - public Datasource getItemDatasource(Entity item) { - Datasource fieldDatasource = fieldDatasources.get(item); - - if (fieldDatasource == null) { - fieldDatasource = new DsBuilder() - .setAllowCommit(false) - .setMetaClass(datasource.getMetaClass()) - .setRefreshMode(CollectionDatasource.RefreshMode.NEVER) - .setViewName("_local") - .buildDatasource(); - - ((DatasourceImplementation) fieldDatasource).valid(); - - fieldDatasource.setItem(item); - fieldDatasources.put(item, fieldDatasource); - } - - return fieldDatasource; - } - - @Override - public void addGeneratedColumn(String columnId, ColumnGenerator generator) { - addGeneratedColumn(columnId, generator, null); - } - - @Override - public void addGeneratedColumn(String columnId, ColumnGenerator generator, - Class componentClass) { - checkArgument(columnId != null, "columnId is null"); - checkArgument(generator != null, "generator is null for column id '%s'", columnId); - - addGeneratedColumnInternal(columnId, generator, componentClass); - } - - protected void addGeneratedColumnInternal(String columnId, ColumnGenerator generator, - Class componentClass) { - Column col = getColumn(columnId); - Column associatedRuntimeColumn = null; - if (col == null) { - col = addRuntimeGeneratedColumn(columnId); - associatedRuntimeColumn = col; - } - - tableModel.addGeneratedColumn(col); - TableColumn tableColumn = getColumn(col); - DesktopTableCellEditor cellEditor = new DesktopTableCellEditor(this, generator, componentClass); - tableColumn.setCellEditor(cellEditor); - tableColumn.setCellRenderer(cellEditor); - - cellEditor.setAssociatedRuntimeColumn(associatedRuntimeColumn); - - generatedColumnsCount++; - - packRows(); - repaintImplIfNeeded(); - } - - protected Column addRuntimeGeneratedColumn(String columnId) { - // store old cell editors / renderers - TableCellEditor[] cellEditors = new TableCellEditor[tableModel.getColumnCount() + 1]; - TableCellRenderer[] cellRenderers = new TableCellRenderer[tableModel.getColumnCount() + 1]; - - for (int i = 0; i < tableModel.getColumnCount(); i++) { - Column tableModelColumn = tableModel.getColumn(i); - - if (tableModel.isGeneratedColumn(tableModelColumn)) { - TableColumn tableColumn = getColumn(tableModelColumn); - cellEditors[i] = tableColumn.getCellEditor(); - cellRenderers[i] = tableColumn.getCellRenderer(); - } - } - - // if column with columnId does not exists then add new to model - Column col = new Column(columnId, columnId); - col.setEditable(false); - - columns.put(col.getId(), col); - // do not touch columnsOrder, it will be synced from table model - if (tableModel != null) { - tableModel.addColumn(col); - } - - // reassign column identifiers - setColumnIdentifiers(); - - // reattach old generated columns - for (int i = 0; i < tableModel.getColumnCount(); i++) { - Column tableModelColumn = tableModel.getColumn(i); - - if (tableModel.isGeneratedColumn(tableModelColumn)) { - TableColumn tableColumn = getColumn(tableModelColumn); - if (cellEditors[i] != null) { - tableColumn.setCellEditor(cellEditors[i]); - } - if (cellRenderers[i] != null) { - tableColumn.setCellRenderer(cellRenderers[i]); - } - } - } - return col; - } - - @Override - public void removeGeneratedColumn(String columnId) { - checkArgument(columnId != null, "columnId is null"); - Column col = getColumn(columnId); - if (col != null) { - boolean oldContentRepaintEnabled = isContentRepaintEnabled(); - setContentRepaintEnabled(false); - - TableColumn targetTableColumn = getColumn(col); - TableCellEditor cellEditor = targetTableColumn.getCellEditor(); - if (cellEditor instanceof DesktopTableCellEditor) { - Column associatedRuntimeColumn = ((DesktopTableCellEditor) cellEditor).getAssociatedRuntimeColumn(); - - removeColumn(associatedRuntimeColumn); - } - - tableModel.removeGeneratedColumn(col); - generatedColumnsCount--; - - packRows(); - repaintImplIfNeeded(); - setContentRepaintEnabled(oldContentRepaintEnabled); - } - } - - @Override - public void addAggregationProperty(String columnId, AggregationInfo.Type type) { - } - - @Override - public void addAggregationProperty(Column columnId, AggregationInfo.Type type) { - } - - @Override - public void removeAggregationProperty(String columnId) { - } - - @Override - public void setColumnCaption(String columnId, String caption) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); - } - - setColumnCaption(column, caption); - } - - @Override - public void setColumnCaption(Column column, String caption) { - checkNotNullArgument(column, "column must be non null"); - - if (!StringUtils.equals(column.getCaption(), caption)) { - column.setCaption(caption); - } - TableColumn tableColumn = getColumn(column); - - // If column is not hidden by security - if (tableColumn != null) { - tableColumn.setHeaderValue(caption); - } - } - - @Override - public void setColumnDescription(String columnId, String description) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); - } - - setColumnDescription(column, description); - } - - @Override - public void setColumnDescription(Column column, String description) { - checkNotNullArgument(column, "column must be non null"); - - if (!StringUtils.equals(column.getDescription(), description)) { - column.setDescription(description); - } - // not supported for desktop - } - - @Override - public void setTextSelectionEnabled(boolean value) { - textSelectionEnabled = value; - } - - @Override - public boolean isTextSelectionEnabled() { - return textSelectionEnabled; - } - - @Override - public void setColumnCollapsed(String columnId, boolean collapsed) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); - } - - setColumnCollapsed(column, collapsed); - } - - @Override - public void setColumnCollapsed(Column column, boolean collapsed) { - if (!getColumnControlVisible()) { - return; - } - - checkNotNullArgument(column, "column must be non null"); - - if (column.isCollapsed() != collapsed) { - column.setCollapsed(collapsed); - } - - TableColumn tableColumn = getColumn(column); - if (tableColumn instanceof TableColumnExt) { - ((TableColumnExt) tableColumn).setVisible(!collapsed); - } - } - - @Override - public void setColumnAlignment(Column column, ColumnAlignment alignment) { - checkNotNullArgument(column, "column must be non null"); - - if (column.getAlignment() != alignment) { - column.setAlignment(alignment); - } - } - - @Override - public void setColumnAlignment(String columnId, ColumnAlignment alignment) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); - } - - setColumnAlignment(column, alignment); - } - - @Override - public void setColumnWidth(Column column, int width) { - checkNotNullArgument(column, "column must be non null"); - - if (column.getWidth() == null || column.getWidth() != width) { - column.setWidth(width); - } - readjustColumns(); - } - - @Override - public void setColumnWidth(String columnId, int width) { - Column column = getColumn(columnId); - if (column == null) { - throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); - } - - setColumnWidth(column, width); - } - - @Override - public void addPrintable(String columnId, Printable printable) { - printables.put(columnId, printable); - } - - @Override - public void removePrintable(String columnId) { - printables.remove(columnId); - } - - @Override - @Nullable - public Printable getPrintable(Column column) { - checkNotNullArgument(column, "column is null"); - - return getPrintable(String.valueOf(column.getId())); - } - - @Nullable - @Override - public Printable getPrintable(String columnId) { - checkArgument(columnId != null, "columnId is null"); - - Printable printable = printables.get(columnId); - if (printable != null) { - return printable; - } else { - Column column = getColumn(columnId); - if (column != null) { - TableColumn tableColumn = getColumn(column); - TableCellEditor cellEditor = tableColumn.getCellEditor(); - if (cellEditor instanceof DesktopTableCellEditor) { - ColumnGenerator columnGenerator = ((DesktopTableCellEditor) cellEditor).getColumnGenerator(); - if (columnGenerator instanceof Printable) { - return (Printable) columnGenerator; - } - } - } - return null; - } - } - - /** - * {@inheritDoc} - */ - @Override - public void repaint() { - TableCellEditor cellEditor = impl.getCellEditor(); - if (cellEditor instanceof DesktopTableCellEditor) { - ((DesktopTableCellEditor) cellEditor).clearCache(); - } - - List implColumns = impl.getColumns(); - for (Column column : getColumns()) { - TableColumn tableColumn = null; - for (TableColumn implColumn : implColumns) { - if (column.equals((implColumn.getIdentifier()))) { - tableColumn = implColumn; - break; - } - } - // column may be hidden - if (tableColumn != null) { - TableCellEditor columnCellEditor = tableColumn.getCellEditor(); - if (columnCellEditor instanceof DesktopTableCellEditor) { - ((DesktopTableCellEditor) columnCellEditor).clearCache(); - } - } - } - packRows(); - repaintImplIfNeeded(); - } - - protected void repaintImplIfNeeded() { - if (contentRepaintEnabled) { - impl.repaint(); - } - } - - @Override - public boolean isEditable() { - return editable; - } - - @Override - public void setEditable(boolean editable) { - this.editable = editable; - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - impl.setEnabled(isEnabledWithParent()); - - if (buttonsPanel != null) { - ((DesktopButtonsPanel) buttonsPanel).setParentEnabled(isEnabledWithParent()); - } - } - - @Override - public ButtonsPanel getButtonsPanel() { - return buttonsPanel; - } - - @Override - public void setButtonsPanel(ButtonsPanel panel) { - if (buttonsPanel != null) { - topPanel.remove(DesktopComponentsHelper.unwrap(buttonsPanel)); - buttonsPanel.setParent(null); - } - buttonsPanel = panel; - if (panel != null) { - if (panel.getParent() != null && panel.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - topPanel.add(DesktopComponentsHelper.unwrap(panel), BorderLayout.WEST); - topPanel.setVisible(true); - - panel.setParent(this); - } - } - - @Override - public void usePresentations(boolean b) { - } - - @Override - public boolean isUsePresentations() { - return false; - } - - @Override - public void resetPresentation() { - if (defaultSettings != null) { - applySettings(defaultSettings.getRootElement()); - } - } - - @Override - public void loadPresentations() { - } - - @Override - public Presentations getPresentations() { - return null; - } - - @Override - public void applyPresentation(Object id) { - } - - @Override - public void applyPresentationAsDefault(Object id) { - } - - @Override - public Object getDefaultPresentationId() { - return null; - } - - @Override - public void applySettings(Element element) { - if (!isSettingsEnabled()) { - return; - } - - if (defaultSettings == null) { - // save default view before apply custom - defaultSettings = DocumentHelper.createDocument(); - defaultSettings.setRootElement(defaultSettings.addElement("presentation")); - - saveSettings(defaultSettings.getRootElement()); - } - - tableSettings.apply(element, isSortable()); - } - - @Override - public boolean saveSettings(Element element) { - return isSettingsEnabled() && tableSettings.saveSettings(element); - } - - @Override - public boolean isSettingsEnabled() { - return settingsEnabled; - } - - @Override - public void setSettingsEnabled(boolean settingsEnabled) { - this.settingsEnabled = settingsEnabled; - } - - @Override - public boolean isMultiSelect() { - return impl.getSelectionModel().getSelectionMode() != ListSelectionModel.SINGLE_SELECTION; - } - - @Override - public void setMultiSelect(boolean multiselect) { - if (multiselect) { - impl.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - } else { - impl.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - } - } - - @Override - public E getSingleSelected() { - Set selected = getSelected(); - return selected.isEmpty() ? null : selected.iterator().next(); - } - - @Override - public Set getSelected() { - Set set = new HashSet<>(); - int[] rows = impl.getSelectedRows(); - for (int row : rows) { - int modelRow = impl.convertRowIndexToModel(row); - Object item = tableModel.getItem(modelRow); - if (item != null) { - //noinspection unchecked - set.add((E) item); - } - } - return set; - } - - @Override - public void setSelected(E item) { - if (item != null) { - setSelected(Collections.singleton(item)); - } else { - setSelected(Collections.emptySet()); - } - } - - @Override - public void setSelected(Collection items) { - if (items == null) { - items = Collections.emptyList(); - } - for (Entity item : items) { - // noinspection unchecked - if (!datasource.containsItem(item.getId())) { - throw new IllegalStateException("Datasource does not contain specified item: " + item.getId()); - } - } - impl.clearSelection(); - if (!items.isEmpty()) { - List indexes = getSelectionIndexes(items); - if (!indexes.isEmpty()) { - applySelectionIndexes(indexes); - } - } - } - - @Override - protected void attachAction(Action action) { - if (action instanceof Action.HasTarget) { - ((Action.HasTarget) action).setTarget(this); - } - - super.attachAction(action); - } - - protected void applySelectionIndexes(List indexes) { - Collections.sort(indexes); - ListSelectionModel model = impl.getSelectionModel(); - model.setValueIsAdjusting(true); - int lastOpened = indexes.get(0); - int current = indexes.get(0); - for (Integer index : indexes) { - if (index > current + 1) { - model.addSelectionInterval(lastOpened, current); - lastOpened = index; - } - current = index; - } - model.addSelectionInterval(lastOpened, current); - model.setValueIsAdjusting(false); - } - - protected List getSelectionIndexes(Collection items) { - if (items.isEmpty()) { - return Collections.emptyList(); - } - List indexes = Lists.newArrayList(); - if (datasource instanceof CollectionDatasource.Ordered) { - HashSet itemSet = new HashSet<>(items); - int itemIndex = 0; - CollectionDatasource.Ordered orderedDs = (CollectionDatasource.Ordered) datasource; - Object id = orderedDs.firstItemId(); - while (id != null && !itemSet.isEmpty()) { - int rowIndex = impl.convertRowIndexToView(itemIndex); - // noinspection unchecked - Entity itemById = datasource.getItem(id); - if (itemSet.contains(itemById)) { - indexes.add(rowIndex); - itemSet.remove(itemById); - } - // noinspection unchecked - id = orderedDs.nextItemId(id); - itemIndex++; - } - } else { - for (Entity item : items) { - int idx = tableModel.getRowIndex(item); - if (idx != -1) { - indexes.add(impl.convertColumnIndexToView(idx)); - } - } - } - return indexes; - } - - @Override - public CollectionDatasource getDatasource() { - return datasource; - } - - @Override - public void refresh() { - if (datasource != null) { - datasource.refresh(); - packRows(); - repaintImplIfNeeded(); - } - } - - protected JPopupMenu createPopupMenu() { - JPopupMenu popup = new JPopupMenu(); - JMenuItem menuItem; - for (final Action action : actionList) { - if (StringUtils.isNotBlank(action.getCaption()) - && action.isVisible()) { - menuItem = new JMenuItem(action.getCaption()); - if (action.getIcon() != null) { - menuItem.setIcon(App.getInstance().getResources().getIcon(action.getIcon())); - } - if (action.getShortcutCombination() != null) { - menuItem.setAccelerator(convertKeyCombination(action.getShortcutCombination())); - } - menuItem.setEnabled(action.isEnabled()); - menuItem.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - action.actionPerform(DesktopAbstractTable.this); - } - } - ); - popup.add(menuItem); - } - } - return popup; - } - - /** - * Returns the preferred height of a row. - * The result is equal to the tallest cell in the row. - * - * @param rowIndex row index - * @return row height - */ - public int getPreferredRowHeight(int rowIndex) { - // Get the current default height for all rows - int height = impl.getRowHeight(); - - // Determine highest cell in the row - for (int c = 0; c < impl.getColumnCount(); c++) { - TableCellRenderer renderer = impl.getCellRenderer(rowIndex, c); - Component comp = impl.prepareRenderer(renderer, rowIndex, c); - int componentHeight = comp.getPreferredSize().height; - height = Math.max(height, componentHeight); - } - return height; - } - - protected void applyFont(JTable table, Font font) { - Graphics graphics = table.getGraphics(); - if (graphics != null) { - FontMetrics metrics = graphics.getFontMetrics(font); - defaultRowHeight = metrics.getHeight() + DEFAULT_ROW_MARGIN; - fontInitialized = true; - if (impl != null) { - packRows(); - } - } - } - - /** - * Sets the height of each row into the preferred height of the tallest cell in that row. - */ - public void packRows() { - if (!contentRepaintEnabled) { - return; - } - - impl.setRowHeight(defaultRowHeight); - - for (Column column : columnsOrder) { - if (column.isEditable()) { - impl.setRowHeight(defaultEditableRowHeight); - break; - } - } - - if (allColumnsAreInline()) { - return; - } - - int preferredRowHeight = -1; - boolean equalsRowHeight = true; - - StopWatch sw = new Log4JStopWatch("DAT packRows " + id); - for (int r = 0; r < impl.getRowCount(); r++) { - int h = getPreferredRowHeight(r); - - if (preferredRowHeight == -1) { - preferredRowHeight = h; - } else if (preferredRowHeight != h) { - equalsRowHeight = false; - } - - if (impl.getRowHeight(r) != h) { - impl.setRowHeight(r, h); - } - } - - if (equalsRowHeight && preferredRowHeight > 0) { - impl.setRowHeight(preferredRowHeight); - } - - sw.stop(); - } - - protected boolean allColumnsAreInline() { - if (generatedColumnsCount <= 0) { - return true; - } - - for (Column column : columnsOrder) { - if (!tableModel.isGeneratedColumn(column)) { - continue; - } - - TableColumn tableColumn = getColumn(column); - if (tableColumn != null) { - DesktopTableCellEditor cellEditor = (DesktopTableCellEditor) tableColumn.getCellEditor(); - if (cellEditor != null) { - boolean inline = cellEditor.isInline(); - if (!inline) { - return false; - } - } - } - } - return true; - } - - protected TableColumn getColumn(Column column) { - List tableColumns = getAllColumns(); - - for (TableColumn tableColumn : tableColumns) { - if (column.equals(tableColumn.getIdentifier())) { - return tableColumn; - } - } - - return null; - } - - @Override - public void addColumnCollapsedListener(ColumnCollapseListener columnCollapsedListener) { - } - - @Override - public void removeColumnCollapseListener(ColumnCollapseListener columnCollapseListener) { - } - - @Override - public void setClickListener(String columnId, CellClickListener clickListener) { - } - - @Override - public void removeClickListener(String columnId) { - } - - public AnyTableModelAdapter getTableModel() { - return tableModel; - } - - public boolean isContentRepaintEnabled() { - return contentRepaintEnabled; - } - - public void setContentRepaintEnabled(boolean contentRepaintEnabled) { - if (this.contentRepaintEnabled != contentRepaintEnabled) { - this.contentRepaintEnabled = contentRepaintEnabled; - - packRows(); - repaintImplIfNeeded(); - } - } - - protected void applyStylename(boolean isSelected, boolean hasFocus, Component component, String style) { - if (style == null) { - return; - } - - DesktopTheme theme = App.getInstance().getTheme(); - if (theme != null) { - HashSet properties = new HashSet<>(); - - if (hasFocus) { - properties.add("focused"); - } else if (isSelected) { - properties.add("selected"); - } else { - properties.add("unselected"); - } - theme.applyStyle(component, style, properties); - } - } - - protected String getStylename(JTable table, int row, int column) { - if (styleProviders == null) { - return null; - } - - Entity item = tableModel.getItem(row); - int modelColumn = table.convertColumnIndexToModel(column); - Object property = columnsOrder.get(modelColumn).getId(); - - String joinedStyle = null; - for (StyleProvider styleProvider : styleProviders) { - //noinspection unchecked - String styleName = styleProvider.getStyleName(item, property.toString()); - if (styleName != null) { - if (joinedStyle == null) { - joinedStyle = styleName; - } else { - joinedStyle += " " + styleName; - } - } - } - - return joinedStyle; - } - - protected TableCellEditor getColumnEditor(int column) { - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - if (tableColumn.getIdentifier() instanceof Table.Column) { - Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); - - if (columnConf.getId() instanceof MetaPropertyPath - && !(isEditable() && columnConf.isEditable()) - && !getTableModel().isGeneratedColumn(columnConf)) { - MetaPropertyPath propertyPath = (MetaPropertyPath) columnConf.getId(); - - final CellProvider cellProvider = getCustomCellEditor(propertyPath); - if (cellProvider != null) { - return new CellProviderEditor(cellProvider); - } - } - } - return null; - } - - protected TableCellRenderer getColumnRenderer(int column) { - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - if (tableColumn.getIdentifier() instanceof Table.Column) { - Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); - if (columnConf.getId() instanceof MetaPropertyPath - && !(isEditable() && columnConf.isEditable()) - && !getTableModel().isGeneratedColumn(columnConf)) { - MetaPropertyPath propertyPath = (MetaPropertyPath) columnConf.getId(); - - final CellProvider cellViewProvider = getCustomCellView(propertyPath); - if (cellViewProvider != null) { - return new CellProviderRenderer(cellViewProvider); - } else if (multiLineCells && String.class == columnConf.getType()) { - return new MultiLineTableCellRenderer(); - } - } - } - return null; - } - - protected boolean isCustomCellEditable(int row, int column) { - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - if (tableColumn.getIdentifier() instanceof Table.Column) { - Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); - if (columnConf.getId() instanceof MetaPropertyPath && !getTableModel().isGeneratedColumn(columnConf)) { - return isCustomCellEditable(tableModel.getItem(row), (MetaPropertyPath) columnConf.getId()); - } - } - return false; - } - - @SuppressWarnings("UnusedParameters") - protected CellProvider getCustomCellView(MetaPropertyPath mpp) { - return null; - } - - @SuppressWarnings("UnusedParameters") - protected CellProvider getCustomCellEditor(MetaPropertyPath mpp) { - return null; - } - - @SuppressWarnings("UnusedParameters") - protected boolean isCustomCellEditable(Entity e, MetaPropertyPath mpp) { - return false; - } - - @Override - public void setId(String id) { - super.setId(id); - - if (id != null && App.getInstance().isTestMode()) { - getComposition().setName(id + "_composition"); - } - } - - @Override - public void assignAutoDebugId() { - super.assignAutoDebugId(); - - if (buttonsPanel != null) { - for (com.haulmont.cuba.gui.components.Component subComponent : buttonsPanel.getComponents()) { - if (subComponent instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) subComponent).assignAutoDebugId(); - } - } - } - } - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { - return "table_" + datasource.getId(); - } - - return getClass().getSimpleName(); - } - - @Override - public void showCustomPopup(com.haulmont.cuba.gui.components.Component popupComponent) { - } - - @Override - public void showCustomPopupActions(List actions) { - } - - @Override - public void setColumnSortable(String columnId, boolean sortable) { - } - - @Override - public boolean getColumnSortable(String columnId) { - return true; - } - - @Override - public void setColumnSortable(Column column, boolean sortable) { - } - - @Override - public boolean getColumnSortable(Column column) { - return true; - } - - @Override - public void setColumnHeaderVisible(boolean visible) { - columnHeaderVisible = visible; - } - - @Override - public boolean isColumnHeaderVisible() { - return columnHeaderVisible; - } - - @Override - public void setShowSelection(boolean showSelection) { - this.showSelection = showSelection; - } - - @Override - public boolean isShowSelection() { - return showSelection; - } - - @Override - public void requestFocus(E itemId, String columnId) { - // unsupported for desktop - } - - @Override - public void scrollTo(E item) { - Preconditions.checkNotNullArgument(item); - int rowIndex = tableModel.getRowIndex(item); - if (rowIndex == -1) { - throw new IllegalArgumentException("Unable to find item in Table"); - } - - impl.scrollRowToVisible(rowIndex); - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - @Override - public void addLookupValueChangeListener(LookupSelectionChangeListener listener) { - if (!lookupSelectionChangeListeners.contains(listener)) { - lookupSelectionChangeListeners.add(listener); - } - } - - @Override - public void removeLookupValueChangeListener(LookupSelectionChangeListener listener) { - lookupSelectionChangeListeners.remove(listener); - } - - /** - * Uses delegate renderer to create cell component. - * Then applies desktop styles to cell component. - */ - protected class StylingCellRenderer implements TableCellRenderer { - - private TableCellRenderer delegate; - - public StylingCellRenderer(TableCellRenderer delegate) { - this.delegate = delegate; - } - - public StylingCellRenderer() { - } - - public TableCellRenderer getDelegate() { - return delegate; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - TableCellRenderer renderer = delegate; - if (renderer == null) { - renderer = table.getDefaultRenderer(value != null ? value.getClass() : Object.class); - } - java.awt.Component component = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - - if (0 <= row) { - String style = getStylename(table, row, column); - applyStylename(isSelected, hasFocus, component, style); - } - return component; - } - } - - protected class CellProviderEditor extends AbstractCellEditor implements TableCellEditor { - private final CellProvider cellProvider; - - public CellProviderEditor(CellProvider cellProvider) { - this.cellProvider = cellProvider; - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, - boolean isSelected, int row, int column) { - Entity item = getTableModel().getItem(row); - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - Column columnConf = (Column) tableColumn.getIdentifier(); - - Component component = cellProvider.generateCell(item, (MetaPropertyPath) columnConf.getId()); - - if (component == null) { - return new JLabel(""); - } - - if (component instanceof JComponent) { - ((JComponent) component).putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, impl); - } - - return component; - } - - @Override - public Object getCellEditorValue() { - DesktopComponentsHelper.flushCurrentInputField(); - return ""; - } - } - - protected class CellProviderRenderer implements TableCellRenderer { - private final CellProvider cellViewProvider; - - public CellProviderRenderer(CellProvider cellViewProvider) { - this.cellViewProvider = cellViewProvider; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - Entity item = getTableModel().getItem(row); - TableColumn tableColumn = impl.getColumnModel().getColumn(column); - Column columnConf = (Column) tableColumn.getIdentifier(); - - Component component = cellViewProvider.generateCell(item, (MetaPropertyPath) columnConf.getId()); - - if (component == null) { - return new JLabel(""); - } - - if (component instanceof JComponent) { - ((JComponent) component).putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, impl); - } - - String style = getStylename(table, row, column); - applyStylename(isSelected, hasFocus, component, style); - - return component; - } - } - - protected class MultiLineTableCellRenderer extends JTextArea implements TableCellRenderer { - private List> rowColHeight = new ArrayList<>(); - - public MultiLineTableCellRenderer() { - setLineWrap(true); - setWrapStyleWord(true); - setOpaque(true); - setBorder(new EmptyBorder(0, 0, 0, 0)); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - if (isSelected) { - setForeground(table.getSelectionForeground()); - setBackground(table.getSelectionBackground()); - } else { - setForeground(table.getForeground()); - Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); - if (row % 2 == 1) { - Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); - if (alternateColor != null) { - background = alternateColor; - } - } - setBackground(background); - } - setFont(table.getFont()); - - Border border = null; - if (isSelected) { - border = UIManager.getDefaults().getBorder("Table.focusSelectedCellHighlightBorder"); - } - if (border == null) { - border = UIManager.getDefaults().getBorder("Table.focusCellHighlightBorder"); - } - - if (hasFocus) { - setBorder(border); - if (table.isCellEditable(row, column)) { - setForeground(UIManager.getColor("Table.focusCellForeground")); - setBackground(UIManager.getColor("Table.focusCellBackground")); - } - } else { - setBorder(UIManager.getDefaults().getBorder("Table.cellNoFocusBorder")); - } - - if (value != null) { - setText(value.toString()); - } else { - setText(""); - } - adjustRowHeight(table, row, column); - return this; - } - - /** - * Calculate the new preferred height for a given row, and sets the height on the table. - */ - private void adjustRowHeight(JTable table, int row, int column) { - //The trick to get this to work properly is to set the width of the column to the - //textarea. The reason for this is that getPreferredSize(), without a width tries - //to place all the text in one line. By setting the size with the with of the column, - //getPreferredSize() returnes the proper height which the row should have in - //order to make room for the text. - int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth(); - setSize(new Dimension(cWidth, 1000)); - int prefH = getPreferredSize().height; - while (rowColHeight.size() <= row) { - rowColHeight.add(new ArrayList(column)); - } - List colHeights = rowColHeight.get(row); - while (colHeights.size() <= column) { - colHeights.add(0); - } - colHeights.set(column, prefH); - int maxH = prefH; - for (Integer colHeight : colHeights) { - if (colHeight > maxH) { - maxH = colHeight; - } - } - if (table.getRowHeight(row) != maxH) { - table.setRowHeight(row, maxH); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.google.common.collect.Lists; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.data.AnyTableModelAdapter; +import com.haulmont.cuba.desktop.gui.data.RowSorterImpl; +import com.haulmont.cuba.desktop.sys.FontDialog; +import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; +import com.haulmont.cuba.desktop.sys.vcl.Flushable; +import com.haulmont.cuba.desktop.sys.vcl.FocusableTable; +import com.haulmont.cuba.desktop.sys.vcl.TableFocusManager; +import com.haulmont.cuba.desktop.theme.DesktopTheme; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Formatter; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.components.formatters.CollectionFormatter; +import com.haulmont.cuba.gui.data.*; +import com.haulmont.cuba.gui.data.impl.CollectionDsActionsNotifier; +import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import com.haulmont.cuba.gui.presentations.Presentations; +import net.miginfocom.layout.CC; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.action.BoundAction; +import org.jdesktop.swingx.table.ColumnControlButton; +import org.jdesktop.swingx.table.TableColumnExt; +import org.jdesktop.swingx.table.TableColumnModelExt; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; + +import javax.annotation.Nullable; +import javax.swing.AbstractAction; +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.awt.Component; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; +import static com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper.convertKeyCombination; +import static java.util.Collections.singletonList; + +public abstract class DesktopAbstractTable + extends DesktopAbstractActionsHolderComponent + implements Table, LookupComponent.LookupSelectionChangeNotifier { + + protected static final int DEFAULT_ROW_MARGIN = 4; + + protected boolean contextMenuEnabled = true; + protected MigLayout layout; + protected JPanel panel; + protected JPanel topPanel; + protected JScrollPane scrollPane; + protected AnyTableModelAdapter tableModel; + protected CollectionDatasource datasource; + protected ButtonsPanel buttonsPanel; + protected RowsCount rowsCount; + protected Map aggregationResult; + protected Map columns = new HashMap<>(); + protected List columnsOrder = new ArrayList<>(); + protected boolean sortable = true; + protected TableSettings tableSettings; + protected boolean editable; + protected List styleProviders; // lazy initialized list + protected IconProvider iconProvider; + + protected Action itemClickAction; + protected Action enterPressAction; + + protected boolean columnsInitialized = false; + protected int generatedColumnsCount = 0; + + protected boolean columnHeaderVisible = true; + + protected boolean textSelectionEnabled = false; + + protected boolean showSelection = true; + + // Indicates that model is being changed. + protected boolean isAdjusting = false; + + protected DesktopTableFieldFactory tableFieldFactory = new DesktopTableFieldFactory(); + + protected List editableColumns = new LinkedList<>(); + + protected Map requiredColumns = new HashMap<>(); + + protected Security security = AppBeans.get(Security.NAME); + + protected boolean columnAdjustRequired = false; + + protected boolean fontInitialized = false; + + protected int defaultRowHeight = 24; + protected int defaultEditableRowHeight = 28; + + protected Set selectedItems = Collections.emptySet(); + + protected Map printables = new HashMap<>(); + + protected Map fieldDatasources = new WeakHashMap<>(); + + // Manual control for content repaint process + protected boolean contentRepaintEnabled = true; + + protected Document defaultSettings; + protected boolean multiLineCells; + protected boolean settingsEnabled = true; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + protected CollectionDatasource.CollectionChangeListener securityCollectionChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + protected CollectionDsActionsNotifier collectionDsActionsNotifier; + + protected List lookupSelectionChangeListeners = new ArrayList<>(); + + protected DesktopAbstractTable() { + shortcutsDelegate.setAllowEnterShortcut(false); + } + + protected void initComponent() { + layout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); + panel = new JPanel(layout); + + topPanel = new JPanel(new BorderLayout()); + topPanel.setVisible(false); + panel.add(topPanel, "growx"); + + scrollPane = new JScrollPane(impl); + impl.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + impl.setFillsViewportHeight(true); + panel.add(scrollPane, "grow"); + + impl.setShowGrid(true); + impl.setGridColor(Color.lightGray); + + impl.addMouseListener( + new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { + handleClickAction(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + showPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + showPopup(e); + } + + protected void showPopup(MouseEvent e) { + if (e.isPopupTrigger() && contextMenuEnabled) { + // select row + Point p = e.getPoint(); + int viewRowIndex = impl.rowAtPoint(p); + + int rowNumber; + if (viewRowIndex >= 0) { + rowNumber = impl.convertRowIndexToModel(viewRowIndex); + } else { + rowNumber = -1; + } + ListSelectionModel model = impl.getSelectionModel(); + + if (!model.isSelectedIndex(rowNumber)) { + model.setSelectionInterval(rowNumber, rowNumber); + } + + // show popup menu + JPopupMenu popupMenu = createPopupMenu(); + if (popupMenu.getComponentCount() > 0) { + popupMenu.show(e.getComponent(), e.getX(), e.getY()); + } + } + } + } + ); + + ColumnControlButton columnControlButton = new ColumnControlButton(impl) { + @Override + protected ColumnVisibilityAction createColumnVisibilityAction(TableColumn column) { + ColumnVisibilityAction columnVisibilityAction = super.createColumnVisibilityAction(column); + + columnVisibilityAction.addPropertyChangeListener(evt -> { + if ("SwingSelectedKey".equals(evt.getPropertyName()) + && evt.getNewValue() instanceof Boolean) { + ColumnVisibilityAction action = (ColumnVisibilityAction) evt.getSource(); + + String columnName = action.getActionCommand(); + boolean collapsed = !((boolean) evt.getNewValue()); + + Column col = getColumn(columnName); + if (col != null) { + col.setCollapsed(collapsed); + } + } + }); + + return columnVisibilityAction; + } + }; + impl.setColumnControl(columnControlButton); + + impl.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter"); + impl.getActionMap().put("enter", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (enterPressAction != null) { + enterPressAction.actionPerform(DesktopAbstractTable.this); + } else { + handleClickAction(); + } + } + }); + + Messages messages = AppBeans.get(Messages.NAME); + // localize default column control actions + for (Object actionKey : impl.getActionMap().allKeys()) { + if ("column.packAll".equals(actionKey)) { + BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); + action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.packAll")); + } else if ("column.packSelected".equals(actionKey)) { + BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); + action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.packSelected")); + } else if ("column.horizontalScroll".equals(actionKey)) { + BoundAction action = (BoundAction) impl.getActionMap().get(actionKey); + action.setName(messages.getMessage(DesktopTable.class, "DesktopTable.horizontalScroll")); + } + } + + // Ability to configure fonts in table + // Add action to column control + String configureFontsLabel = messages.getMessage( + DesktopTable.class, "DesktopTable.configureFontsLabel"); + impl.getActionMap().put(ColumnControlButton.COLUMN_CONTROL_MARKER + "fonts", + new AbstractAction(configureFontsLabel) { + @Override + public void actionPerformed(ActionEvent e) { + Component rootComponent = SwingUtilities.getRoot(impl); + final FontDialog fontDialog = FontDialog.show(rootComponent, impl.getFont()); + fontDialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Font result = fontDialog.getResult(); + if (result != null) { + impl.setFont(result); + packRows(); + } + } + }); + fontDialog.open(); + } + }); + + // Ability to reset settings + String resetSettingsLabel = messages.getMessage( + DesktopTable.class, "DesktopTable.resetSettings"); + impl.getActionMap().put(ColumnControlButton.COLUMN_CONTROL_MARKER + "resetSettings", + new AbstractAction(resetSettingsLabel) { + @Override + public void actionPerformed(ActionEvent e) { + resetPresentation(); + } + }); + + scrollPane.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + if (!columnsInitialized) { + adjustColumnHeaders(); + } + columnsInitialized = true; + } + }); + + // init default row height + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (!fontInitialized) { + applyFont(impl, impl.getFont()); + } + } + }); + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + CC cc = new CC().grow(); + MigLayoutHelper.applyWidth(cc, (int) widthSize.value, widthSize.unit, false); + layout.setComponentConstraints(scrollPane, cc); + } + + protected void handleClickAction() { + Action action = getItemClickAction(); + if (action == null) { + action = getEnterAction(); + if (action == null) { + action = getAction("edit"); + if (action == null) { + action = getAction("view"); + } + } + } + if (action != null && action.isEnabled() && action.isVisible()) { + Window window = ComponentsHelper.getWindow(DesktopAbstractTable.this); + if (window instanceof Window.Wrapper) { + window = ((Window.Wrapper) window).getWrappedWindow(); + } + + if (!(window instanceof Window.Lookup)) { + action.actionPerform(DesktopAbstractTable.this); + } else { + Window.Lookup lookup = (Window.Lookup) window; + + com.haulmont.cuba.gui.components.Component lookupComponent = lookup.getLookupComponent(); + if (lookupComponent != this) { + action.actionPerform(DesktopAbstractTable.this); + } else if (action.getId().equals(WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID)) { + action.actionPerform(DesktopAbstractTable.this); + } + } + } + } + + @Override + public void setLookupSelectHandler(Runnable selectHandler) { + setEnterPressAction(new com.haulmont.cuba.gui.components.AbstractAction( + WindowDelegate.LOOKUP_ENTER_PRESSED_ACTION_ID) { + @Override + public void actionPerform(com.haulmont.cuba.gui.components.Component component) { + selectHandler.run(); + } + }); + + setItemClickAction(new com.haulmont.cuba.gui.components.AbstractAction( + WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID) { + @Override + public void actionPerform(com.haulmont.cuba.gui.components.Component component) { + selectHandler.run(); + } + }); + } + + @Override + public Collection getLookupSelectedItems() { + return getSelected(); + } + + protected void refreshActionsState() { + for (Action action : getActions()) { + action.refreshState(); + } + } + + protected Action getEnterAction() { + for (Action action : getActions()) { + KeyCombination kc = action.getShortcutCombination(); + if (kc != null) { + if ((kc.getModifiers() == null || kc.getModifiers().length == 0) + && kc.getKey() == KeyCombination.Key.ENTER) { + return action; + } + } + } + return null; + } + + protected void readjustColumns() { + if (columnAdjustRequired) { + return; + } + + this.columnAdjustRequired = true; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + adjustColumnHeaders(); + + columnAdjustRequired = false; + } + }); + } + + protected void adjustColumnHeaders() { + List notInited = new LinkedList<>(); + int summaryWidth = 0; + int componentWidth = impl.getParent().getWidth(); + + // take into account only visible columns + Enumeration columnEnumeration = impl.getColumnModel().getColumns(); + while (columnEnumeration.hasMoreElements()) { + TableColumn tableColumn = columnEnumeration.nextElement(); + Column column = (Column) tableColumn.getIdentifier(); + + Integer width = column.getWidth(); + if (width != null) { + tableColumn.setPreferredWidth(width); + tableColumn.setWidth(width); + summaryWidth += width; + } else { + notInited.add(tableColumn); + } + } + + if (notInited.size() != impl.getColumnCount()) { + impl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + if (!notInited.isEmpty() && (componentWidth > summaryWidth)) { + int defaultWidth = (componentWidth - summaryWidth) / notInited.size(); + for (TableColumn column : notInited) { + column.setPreferredWidth(Math.max(defaultWidth, column.getWidth())); + } + } + } + } + + protected abstract void initTableModel(CollectionDatasource datasource); + + @Override + public JComponent getComposition() { + return panel; + } + + @Override + public List getColumns() { + return Collections.unmodifiableList(columnsOrder); + } + + @Override + public Column getColumn(String id) { + for (Table.Column column : columnsOrder) { + if (column.getId().toString().equals(id)) { + return column; + } + } + return null; + } + + @Override + public void addColumn(Column column) { + checkNotNullArgument(column, "Column must be non null"); + + Object columnId = column.getId(); + columns.put(columnId, column); + columnsOrder.add(column); + + if (tableModel != null) { + tableModel.addColumn(column); + } + + if (datasource != null && column.isEditable() && columnId instanceof MetaPropertyPath) { + if (!editableColumns.contains(columnId)) { + editableColumns.add((MetaPropertyPath) columnId); + } + } + + setColumnIdentifiers(); + refresh(); + + column.setOwner(this); + + if (column.getFormatter() == null && columnId instanceof MetaPropertyPath) { + MetaProperty metaProperty = ((MetaPropertyPath) columnId).getMetaProperty(); + + if (Collection.class.isAssignableFrom(metaProperty.getJavaType())) { + final Formatter collectionFormatter = new CollectionFormatter(); + column.setFormatter(collectionFormatter); + } + } + } + + @Override + public void removeColumn(Column column) { + if (column == null) { + return; + } + + String name; + if (column.getId() instanceof MetaPropertyPath) { + MetaPropertyPath metaPropertyPath = (MetaPropertyPath) column.getId(); + name = metaPropertyPath.getMetaProperty().getName(); + + editableColumns.remove(metaPropertyPath); + } else { + name = column.getId().toString(); + } + + TableColumn tableColumn = null; + + Iterator columnIterator = getAllColumns().iterator(); + while (columnIterator.hasNext() && (tableColumn == null)) { + TableColumn xColumn = columnIterator.next(); + Object identifier = xColumn.getIdentifier(); + if (identifier instanceof String && identifier.equals(name)) { + tableColumn = xColumn; + } else if (column.equals(identifier)) { + tableColumn = xColumn; + } + } + + if (tableColumn != null) { + // store old cell editors / renderers + Map cellEditors = new HashMap<>(); + Map cellRenderers = new HashMap<>(); + + for (int i = 0; i < tableModel.getColumnCount(); i++) { + Column tableModelColumn = tableModel.getColumn(i); + + if (tableModel.isGeneratedColumn(tableModelColumn)) { + TableColumn oldColumn = getColumn(tableModelColumn); + + cellEditors.put(tableModelColumn.getId(), oldColumn.getCellEditor()); + cellRenderers.put(tableModelColumn.getId(), oldColumn.getCellRenderer()); + } + } + + impl.getColumnModel().removeColumn(tableColumn); + impl.removeColumn(tableColumn); + + columns.remove(column.getId()); + columnsOrder.remove(column); + + if (tableModel != null) { + tableModel.removeColumn(column); + } + + // reassign column identifiers + setColumnIdentifiers(); + + // reattach old generated columns + for (int i = 0; i < tableModel.getColumnCount(); i++) { + Column tableModelColumn = tableModel.getColumn(i); + + if (tableModel.isGeneratedColumn(tableModelColumn)) { + TableColumn oldColumn = getColumn(tableModelColumn); + if (cellEditors.containsKey(tableModelColumn.getId())) { + oldColumn.setCellEditor(cellEditors.get(tableModelColumn.getId())); + } + if (cellRenderers.containsKey(tableModelColumn.getId())) { + oldColumn.setCellRenderer(cellRenderers.get(tableModelColumn.getId())); + } + } + } + + packRows(); + repaintImplIfNeeded(); + } + + column.setOwner(null); + } + + @Override + public void setDatasource(final CollectionDatasource datasource) { + Preconditions.checkNotNullArgument(datasource, "datasource is null"); + + final Collection properties; + if (this.columns.isEmpty()) { + MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + + Collection paths = datasource.getView() != null ? + // if a view is specified - use view properties + metadataTools.getViewPropertyPaths(datasource.getView(), datasource.getMetaClass()) : + // otherwise use only string properties from meta-class - the temporary solution for KeyValue datasources + metadataTools.getPropertyPaths(datasource.getMetaClass()).stream() + .filter(mpp -> mpp.getRangeJavaClass().equals(String.class)) + .collect(Collectors.toList()); + + for (MetaPropertyPath metaPropertyPath : paths) { + MetaProperty property = metaPropertyPath.getMetaProperty(); + if (!property.getRange().getCardinality().isMany() && !metadataTools.isSystem(property)) { + Table.Column column = new Table.Column(metaPropertyPath); + + String propertyName = property.getName(); + MetaClass propertyMetaClass = metadataTools.getPropertyEnclosingMetaClass(metaPropertyPath); + + column.setCaption(messageTools.getPropertyCaption(propertyMetaClass, propertyName)); + column.setType(metaPropertyPath.getRangeJavaClass()); + + Element element = DocumentHelper.createElement("column"); + column.setXmlDescriptor(element); + + addColumn(column); + } + } + } + properties = this.columns.keySet(); + + this.datasource = datasource; + + collectionChangeListener = e -> { + switch (e.getOperation()) { + case CLEAR: + case REFRESH: + fieldDatasources.clear(); + break; + + case UPDATE: + case REMOVE: + for (Object entity : e.getItems()) { + fieldDatasources.remove(entity); + } + break; + } + }; + //noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + + initTableModel(datasource); + + initChangeListener(); + + setColumnIdentifiers(); + + // Major change in table columns behavior #PL-4853 + // We need not to recreate all columns on each table change after initTableModel +// impl.setAutoCreateColumnsFromModel(false); + + if (isSortable()) { + impl.setRowSorter(new RowSorterImpl(tableModel)); + } + + initSelectionListener(datasource); + + List editableColumns = null; + if (isEditable()) { + editableColumns = new LinkedList<>(); + } + + MetaClass metaClass = datasource.getMetaClass(); + for (final Object property : properties) { + final Table.Column column = this.columns.get(property); + +// todo implement setColumnHeader +// final String caption; +// if (column != null) { +// caption = StringUtils.capitalize(column.getCaption() != null ? column.getCaption() : getColumnCaption(property)); +// } else { +// caption = StringUtils.capitalize(getColumnCaption(property)); +// } +// +// setColumnHeader(property, caption); + + if (column != null) { + if (column.isCollapsed() && getColumnControlVisible()) { + TableColumn tableColumn = getColumn(column); + if (tableColumn instanceof TableColumnExt) { + ((TableColumnExt) tableColumn).setVisible(false); + } + } + + if (editableColumns != null && column.isEditable() && (property instanceof MetaPropertyPath)) { + MetaPropertyPath propertyPath = (MetaPropertyPath) property; + if (security.isEntityAttrUpdatePermitted(metaClass, property.toString())) { + editableColumns.add(propertyPath); + } + } + } + } + + if (editableColumns != null && !editableColumns.isEmpty()) { + setEditableColumns(editableColumns); + } + + List columnsOrder = new ArrayList<>(); + for (Table.Column column : this.columnsOrder) { + if (column.getId() instanceof MetaPropertyPath) { + MetaPropertyPath metaPropertyPath = (MetaPropertyPath) column.getId(); + if (security.isEntityAttrReadPermitted(metaClass, metaPropertyPath.toString())) { + columnsOrder.add(column.getId()); + } + } else { + columnsOrder.add(column.getId()); + } + } + + setVisibleColumns(columnsOrder); + + if (security.isSpecificPermitted(ShowInfoAction.ACTION_PERMISSION)) { + ShowInfoAction action = (ShowInfoAction) getAction(ShowInfoAction.ACTION_ID); + if (action == null) { + action = new ShowInfoAction(); + addAction(action); + } + action.setDatasource(datasource); + } + + securityCollectionChangeListener = e -> { + onDataChange(); + packRows(); + + // #PL-2035, reload selection from ds + Set selectedItems1 = getSelected(); + if (selectedItems1 == null) { + selectedItems1 = Collections.emptySet(); + } + + Set newSelection = new HashSet<>(); + for (E entity : selectedItems1) { + if (e.getDs().containsItem(entity.getId())) { + newSelection.add(entity); + } + } + + if (e.getDs().getState() == Datasource.State.VALID && e.getDs().getItem() != null) { + if (e.getDs().containsItem(e.getDs().getItem().getId())) { + newSelection.add((E) e.getDs().getItem()); + } + } + + if (newSelection.isEmpty()) { + setSelected((E) null); + } else { + setSelected(newSelection); + } + }; + // noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, securityCollectionChangeListener)); + + itemPropertyChangeListener = e -> { + List columns1 = getColumns(); + boolean find = false; + int i = 0; + while ((i < columns1.size()) & !find) { + Object columnId = columns1.get(i).getId(); + if (columnId instanceof MetaPropertyPath) { + String propertyName = ((MetaPropertyPath) columnId).getMetaProperty().getName(); + if (propertyName.equals(e.getProperty())) { + find = true; + } + } + i++; + } + if (find) { + onDataChange(); + } + packRows(); + }; + // noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + if (rowsCount != null) { + rowsCount.setDatasource(datasource); + } + + collectionDsActionsNotifier = new CollectionDsActionsNotifier(this); + collectionDsActionsNotifier.bind(datasource); + + for (Action action : getActions()) { + action.refreshState(); + } + + if (!canBeSorted(datasource)) + setSortable(false); + } + + protected boolean canBeSorted(CollectionDatasource datasource) { + //noinspection SimplifiableConditionalExpression + return datasource instanceof PropertyDatasource ? + ((PropertyDatasource) datasource).getProperty().getRange().isOrdered() : true; + } + + protected String getColumnCaption(Object columnId) { + if (columnId instanceof MetaPropertyPath) { + return ((MetaPropertyPath) columnId).getMetaProperty().getName(); + } else { + return columnId.toString(); + } + } + + protected void setColumnIdentifiers() { + int i = 0; + for (TableColumn tableColumn : getAllColumns()) { + Column column = columnsOrder.get(i++); + if (!(tableColumn.getIdentifier() instanceof Column)) { + tableColumn.setIdentifier(column); + } + } + } + + protected List getAllColumns() { + return ((TableColumnModelExt) impl.getColumnModel()).getColumns(true); + } + + protected void onDataChange() { + for (TableColumn tableColumn : getAllColumns()) { + TableCellEditor cellEditor = tableColumn.getCellEditor(); + if (cellEditor instanceof DesktopTableCellEditor) { + ((DesktopTableCellEditor) cellEditor).clearCache(); + } + } + repaintImplIfNeeded(); + } + + protected void initChangeListener() { + tableModel.addChangeListener(new AnyTableModelAdapter.DataChangeListener() { + + private boolean focused = false; + private ThreadLocal> selectionBackup = new ThreadLocal<>(); + private int scrollRowIndex = -1; + + @Override + public void beforeChange(boolean structureChanged) { + if (!structureChanged) + return; + + isAdjusting = true; + focused = impl.isFocusOwner(); + selectionBackup.set(selectedItems); + + JViewport viewport = (JViewport) impl.getParent(); + Point scrollPoint = viewport.getViewPosition(); + scrollRowIndex = impl.rowAtPoint(scrollPoint); + } + + @Override + public void afterChange(boolean structureChanged) { + if (!structureChanged) + return; + + isAdjusting = false; + applySelection(filterSelection(selectionBackup.get())); + selectionBackup.remove(); + + if (focused) { + impl.requestFocus(); + } else { + if (impl.getCellEditor() != null) { + if (!impl.getCellEditor().stopCellEditing()) { + impl.getCellEditor().cancelCellEditing(); + } + } + } + + TableFocusManager focusManager = ((FocusableTable) impl).getFocusManager(); + if (focusManager != null && scrollRowIndex >= 0) { + focusManager.scrollToSelectedRow(scrollRowIndex); + } + + // reassign identifiers for auto created columns + setColumnIdentifiers(); + } + + @SuppressWarnings("unchecked") + private Set filterSelection(Set selection) { + if (selection == null) + return Collections.emptySet(); + + Set newSelection = new HashSet<>(2 * selection.size()); + for (Entity item : selection) { + if (datasource.containsItem(item.getId())) { + newSelection.add((E) datasource.getItem(item.getId())); + } + } + return newSelection; + } + + private void applySelection(Set selection) { + int minimalSelectionRowIndex = Integer.MAX_VALUE; + if (!selection.isEmpty()) { + for (Entity entity : selection) { + int rowIndex = tableModel.getRowIndex(entity); + if (rowIndex < minimalSelectionRowIndex && rowIndex >= 0) { + minimalSelectionRowIndex = rowIndex; + } + } + } + + setSelected(selection); + + if (!selection.isEmpty()) { + if (focused) { + impl.requestFocus(); + } else { + if (impl.getCellEditor() != null) { + if (!impl.getCellEditor().stopCellEditing()) { + impl.getCellEditor().cancelCellEditing(); + } + } + } + + TableFocusManager focusManager = ((FocusableTable) impl).getFocusManager(); + if (focusManager != null) { + focusManager.scrollToSelectedRow(minimalSelectionRowIndex); + } + } + } + + @Override + public void dataSorted() { + clearGeneratedColumnsCache(); + packRows(); + } + }); + } + + protected void clearGeneratedColumnsCache() { + for (Column column : columnsOrder) { + if (tableModel.isGeneratedColumn(column)) { + TableColumn tableColumn = getColumn(column); + if (tableColumn != null) { + TableCellEditor tableCellEditor = tableColumn.getCellEditor(); + if (tableCellEditor instanceof DesktopTableCellEditor) { + ((DesktopTableCellEditor) tableCellEditor).clearCache(); + } + } + } + } + } + + // Get cell editor for editable column + protected TableCellEditor getCellEditor(int row, int column) { + + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + if (tableColumn.getIdentifier() instanceof Column) { + Column columnConf = (Column) tableColumn.getIdentifier(); + + if (editableColumns != null + && columnConf.getId() instanceof MetaPropertyPath + && editableColumns.contains(columnConf.getId())) { + + return tableFieldFactory.createEditComponent(row, columnConf); + } + } + + return null; + } + + protected class EditableColumnTableCellEditor extends AbstractCellEditor implements TableCellEditor { + protected com.haulmont.cuba.gui.components.Component cellComponent; + + public EditableColumnTableCellEditor(com.haulmont.cuba.gui.components.Component cellComponent) { + this.cellComponent = cellComponent; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, + boolean isSelected, int row, int column) { + JComponent composition = DesktopComponentsHelper.getComposition(cellComponent); + composition.putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, table); + return composition; + } + + @Override + public boolean isCellEditable(EventObject e) { + return DesktopAbstractTable.this.isEditable() + && cellComponent instanceof Editable && ((Editable) cellComponent).isEditable(); + } + + @Override + public Object getCellEditorValue() { + flush(DesktopComponentsHelper.getComposition(cellComponent)); + impl.requestFocus(); + if (cellComponent instanceof HasValue) { + return ((Field) cellComponent).getValue(); + } + return null; + } + + protected void flush(Component component) { + if (component instanceof Flushable) { + ((Flushable) component).flushValue(); + } else if (component instanceof java.awt.Container) { + for (Component child : ((java.awt.Container) component).getComponents()) { + flush(child); + } + } + } + } + + protected class DesktopTableFieldFactory extends AbstractFieldFactory { + + public TableCellEditor createEditComponent(int row, Column columnConf) { + MetaPropertyPath mpp = (MetaPropertyPath) columnConf.getId(); + + Datasource fieldDatasource = getItemDatasource(tableModel.getItem(row)); + // create lookup + final com.haulmont.cuba.gui.components.Component columnComponent = createField(fieldDatasource, + mpp.getMetaProperty().getName(), columnConf.getXmlDescriptor()); + + if (columnComponent instanceof Field) { + Field cubaField = (Field) columnComponent; + + if (columnConf.getDescription() != null) { + cubaField.setDescription(columnConf.getDescription()); + } + if (requiredColumns.containsKey(columnConf)) { + cubaField.setRequired(true); + cubaField.setRequiredMessage(requiredColumns.get(columnConf)); + } + } + + if (columnComponent instanceof DesktopCheckBox) { + JCheckBox checkboxImpl = (JCheckBox) ((DesktopCheckBox) columnComponent).getComponent(); + checkboxImpl.setHorizontalAlignment(SwingConstants.CENTER); + } + + JComponent composition = DesktopComponentsHelper.getComposition(columnComponent); + Color color = UIManager.getColor("Table:\"Table.cellRenderer\".background"); + composition.setBackground(new Color(color.getRGB())); + composition.setForeground(impl.getForeground()); + composition.setFont(impl.getFont()); + + if (columnConf.getWidth() != null) { + columnComponent.setWidth(columnConf.getWidth() + "px"); + } else { + columnComponent.setWidth("100%"); + } + + if (columnComponent instanceof BelongToFrame) { + BelongToFrame belongToFrame = (BelongToFrame) columnComponent; + if (belongToFrame.getFrame() == null) { + belongToFrame.setFrame(getFrame()); + } + } + + applyPermissions(columnComponent); + + columnComponent.setParent(DesktopAbstractTable.this); + + return new EditableColumnTableCellEditor(columnComponent); + } + + protected void applyPermissions(com.haulmont.cuba.gui.components.Component columnComponent) { + if (columnComponent instanceof DatasourceComponent) { + DatasourceComponent dsComponent = (DatasourceComponent) columnComponent; + MetaPropertyPath propertyPath = dsComponent.getMetaPropertyPath(); + + if (propertyPath != null) { + MetaClass metaClass = dsComponent.getDatasource().getMetaClass(); + dsComponent.setEditable(dsComponent.isEditable() + && security.isEntityAttrUpdatePermitted(metaClass, propertyPath.toString())); + } + } + } + + @Override + @Nullable + protected CollectionDatasource getOptionsDatasource(Datasource fieldDatasource, String propertyId) { + if (datasource == null) + throw new IllegalStateException("Table datasource is null"); + + MetaPropertyPath metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) + .resolveMetaPropertyPath(datasource.getMetaClass(), propertyId); + Column columnConf = columns.get(metaPropertyPath); + + final DsContext dsContext = datasource.getDsContext(); + + String optDsName = columnConf.getXmlDescriptor() != null ? + columnConf.getXmlDescriptor().attributeValue("optionsDatasource") : ""; + + if (StringUtils.isBlank(optDsName)) { + return null; + } else { + CollectionDatasource ds = (CollectionDatasource) dsContext.get(optDsName); + if (ds == null) + throw new IllegalStateException("Options datasource not found: " + optDsName); + + return ds; + } + } + } + + protected void initSelectionListener(final CollectionDatasource datasource) { + impl.getSelectionModel().addListSelectionListener( + new ListSelectionListener() { + @Override + @SuppressWarnings("unchecked") + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting() || datasource == null) { + return; + } + + selectedItems = getSelected(); + + if (selectedItems.isEmpty()) { + Entity dsItem = datasource.getItemIfValid(); + datasource.setItem(null); + + if (dsItem == null) { + // in this case item change event will not be generated + refreshActionsState(); + } + } else { + // reset selection and select new item + if (isMultiSelect()) { + datasource.setItem(null); + } + + Entity newItem = selectedItems.iterator().next(); + Entity dsItem = datasource.getItemIfValid(); + datasource.setItem(newItem); + + if (ObjectUtils.equals(dsItem, newItem)) { + // in this case item change event will not be generated + refreshActionsState(); + } + } + + LookupSelectionChangeEvent selectionChangeEvent = + new LookupSelectionChangeEvent(DesktopAbstractTable.this); + for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { + listener.lookupValueChanged(selectionChangeEvent); + } + } + } + ); + } + + protected void setVisibleColumns(List columnsOrder) { + for (TableColumn tableColumn : getAllColumns()) { + Column columnIdentifier = (Column) tableColumn.getIdentifier(); + if (!columnsOrder.contains(columnIdentifier.getId())) { + impl.removeColumn(tableColumn); + } + } + } + + @Override + public boolean isContextMenuEnabled() { + return contextMenuEnabled; + } + + @Override + public void setContextMenuEnabled(boolean contextMenuEnabled) { + this.contextMenuEnabled = contextMenuEnabled; + } + + protected void setEditableColumns(List editableColumns) { + this.editableColumns.clear(); + this.editableColumns.addAll(editableColumns); + } + + @Override + public void setRequired(Table.Column column, boolean required, String message) { + if (required) + requiredColumns.put(column, message); + else + requiredColumns.remove(column); + } + + @Override + public void addValidator(Column column, Field.Validator validator) { + } + + @Override + public void addValidator(Field.Validator validator) { + } + + @Override + public void setEnterPressAction(Action action) { + enterPressAction = action; + } + + @Override + public Action getEnterPressAction() { + return enterPressAction; + } + + @Override + public void setItemClickAction(Action action) { + if (itemClickAction != null) { + removeAction(itemClickAction); + } + itemClickAction = action; + if (!getActions().contains(action)) { + addAction(action); + } + } + + @Override + public Action getItemClickAction() { + return itemClickAction; + } + + @Override + public List getNotCollapsedColumns() { + List visibleColumns = new LinkedList<>(); + for (Column column : columnsOrder) { + TableColumnExt columnExt = impl.getColumnExt(column); + if (columnExt != null && columnExt.isVisible()) { + visibleColumns.add(column); + } + } + return visibleColumns; + } + + @Override + public void setSortable(boolean sortable) { + this.sortable = sortable && canBeSorted(datasource); + if (this.sortable) { + if (tableModel != null && impl.getRowSorter() == null) { + impl.setRowSorter(new RowSorterImpl(tableModel)); + } + } else { + impl.setRowSorter(null); + } + } + + @Override + public boolean isSortable() { + return sortable; + } + + @Override + public void setColumnReorderingAllowed(boolean columnReorderingAllowed) { + JTableHeader tableHeader = impl.getTableHeader(); + tableHeader.setReorderingAllowed(columnReorderingAllowed); + } + + @Override + public boolean getColumnReorderingAllowed() { + JTableHeader tableHeader = impl.getTableHeader(); + return tableHeader.getReorderingAllowed(); + } + + @Override + public void setColumnControlVisible(boolean columnCollapsingAllowed) { + impl.setColumnControlVisible(columnCollapsingAllowed); + } + + @Override + public boolean getColumnControlVisible() { + return impl.isColumnControlVisible(); + } + + @Override + public void setAggregatable(boolean aggregatable) { + } + + @Override + public Map getAggregationResults() { + return Collections.emptyMap(); + } + + @Override + public boolean isAggregatable() { + return false; + } + + @Override + public void setAggregationStyle(AggregationStyle aggregationStyle) { + } + + @Override + public AggregationStyle getAggregationStyle() { + return null; + } + + @Override + public void setShowTotalAggregation(boolean showAggregation) { + } + + @Override + public boolean isShowTotalAggregation() { + return false; + } + + @Override + public void sortBy(Object propertyId, boolean ascending) { + if (isSortable()) { + for (int i = 0; i < columnsOrder.size(); i++) { + Column column = columnsOrder.get(i); + if (column.getId().equals(propertyId)) { + SortOrder sortOrder = ascending ? SortOrder.ASCENDING : SortOrder.DESCENDING; + tableModel.sort(singletonList(new RowSorter.SortKey(i, sortOrder))); + onDataChange(); + packRows(); + break; + } + } + } + } + + @Override + public void sort(String columnId, SortDirection direction) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalArgumentException("Unable to find column " + columnId); + } + + if (isSortable()) { + SortOrder sortOrder = direction == SortDirection.ASCENDING ? SortOrder.ASCENDING : SortOrder.DESCENDING; + int columnIndex = columnsOrder.indexOf(column); + tableModel.sort(singletonList(new RowSorter.SortKey(columnIndex, sortOrder))); + onDataChange(); + packRows(); + } + } + + @Nullable + @Override + public SortInfo getSortInfo() { + // SortInfo is returned only for sorting triggered from UI + List sortKeys = impl.getRowSorter().getSortKeys(); + if (CollectionUtils.isNotEmpty(sortKeys)) { + RowSorter.SortKey sortKey = sortKeys.get(0); + + return new SortInfo(columnsOrder.get(sortKey.getColumn()).getId(), + SortOrder.ASCENDING.equals(sortKey.getSortOrder())); + } + return null; + } + + @Override + public void selectAll() { + if (isMultiSelect()) { + if (impl.getRowCount() > 0) { + impl.setRowSelectionInterval(0, impl.getModel().getRowCount() - 1); + } + } + } + + @Override + public RowsCount getRowsCount() { + return rowsCount; + } + + @Override + public void setRowsCount(RowsCount rowsCount) { + if (this.rowsCount != null) { + topPanel.remove(DesktopComponentsHelper.getComposition(this.rowsCount)); + } + this.rowsCount = rowsCount; + if (rowsCount != null) { + topPanel.add(DesktopComponentsHelper.getComposition(rowsCount), BorderLayout.EAST); + topPanel.setVisible(true); + } + } + + @Override + public void setMultiLineCells(boolean multiLineCells) { + this.multiLineCells = multiLineCells; + } + + @Override + public boolean isMultiLineCells() { + return multiLineCells; + } + + @Override + public void setRowHeaderMode(RowHeaderMode mode) { + } + + @Override + public void setStyleProvider(StyleProvider styleProvider) { + if (styleProvider != null) { + if (this.styleProviders == null) { + this.styleProviders = new LinkedList<>(); + } else { + this.styleProviders.clear(); + } + + this.styleProviders.add(styleProvider); + } else { + this.styleProviders = null; + } + + refreshCellStyles(); + } + + @Override + public void addStyleProvider(StyleProvider styleProvider) { + if (this.styleProviders == null) { + this.styleProviders = new LinkedList<>(); + } + + if (!this.styleProviders.contains(styleProvider)) { + this.styleProviders.add(styleProvider); + + refreshCellStyles(); + } + } + + @Override + public void removeStyleProvider(StyleProvider styleProvider) { + if (this.styleProviders != null) { + if (this.styleProviders.remove(styleProvider)) { + refreshCellStyles(); + } + } + } + + protected void refreshCellStyles() { + for (Column col : columnsOrder) { + // generated column handles styles himself + if (!tableModel.isGeneratedColumn(col)) { + TableColumn tableColumn = getColumn(col); + + // If column is not hidden by security + if (tableColumn != null) { + boolean useStyledCells = styleProviders != null && !styleProviders.isEmpty(); + tableColumn.setCellRenderer(useStyledCells ? new StylingCellRenderer() : null); + } + } + } + } + + @Override + public void setIconProvider(IconProvider iconProvider) { + this.iconProvider = iconProvider; // TODO Kozlov: PL-2411. + } + + @Override + public int getRowHeaderWidth() { + return 0; // TODO Kozlov: PL-2411. + } + + @Override + public void setRowHeaderWidth(int width) { + // TODO Kozlov: PL-2411. + } + + @Override + public Datasource getItemDatasource(Entity item) { + Datasource fieldDatasource = fieldDatasources.get(item); + + if (fieldDatasource == null) { + fieldDatasource = new DsBuilder() + .setAllowCommit(false) + .setMetaClass(datasource.getMetaClass()) + .setRefreshMode(CollectionDatasource.RefreshMode.NEVER) + .setViewName("_local") + .buildDatasource(); + + ((DatasourceImplementation) fieldDatasource).valid(); + + fieldDatasource.setItem(item); + fieldDatasources.put(item, fieldDatasource); + } + + return fieldDatasource; + } + + @Override + public void addGeneratedColumn(String columnId, ColumnGenerator generator) { + addGeneratedColumn(columnId, generator, null); + } + + @Override + public void addGeneratedColumn(String columnId, ColumnGenerator generator, + Class componentClass) { + checkArgument(columnId != null, "columnId is null"); + checkArgument(generator != null, "generator is null for column id '%s'", columnId); + + addGeneratedColumnInternal(columnId, generator, componentClass); + } + + protected void addGeneratedColumnInternal(String columnId, ColumnGenerator generator, + Class componentClass) { + Column col = getColumn(columnId); + Column associatedRuntimeColumn = null; + if (col == null) { + col = addRuntimeGeneratedColumn(columnId); + associatedRuntimeColumn = col; + } + + tableModel.addGeneratedColumn(col); + TableColumn tableColumn = getColumn(col); + DesktopTableCellEditor cellEditor = new DesktopTableCellEditor(this, generator, componentClass); + tableColumn.setCellEditor(cellEditor); + tableColumn.setCellRenderer(cellEditor); + + cellEditor.setAssociatedRuntimeColumn(associatedRuntimeColumn); + + generatedColumnsCount++; + + packRows(); + repaintImplIfNeeded(); + } + + protected Column addRuntimeGeneratedColumn(String columnId) { + // store old cell editors / renderers + TableCellEditor[] cellEditors = new TableCellEditor[tableModel.getColumnCount() + 1]; + TableCellRenderer[] cellRenderers = new TableCellRenderer[tableModel.getColumnCount() + 1]; + + for (int i = 0; i < tableModel.getColumnCount(); i++) { + Column tableModelColumn = tableModel.getColumn(i); + + if (tableModel.isGeneratedColumn(tableModelColumn)) { + TableColumn tableColumn = getColumn(tableModelColumn); + cellEditors[i] = tableColumn.getCellEditor(); + cellRenderers[i] = tableColumn.getCellRenderer(); + } + } + + // if column with columnId does not exists then add new to model + Column col = new Column(columnId, columnId); + col.setEditable(false); + + columns.put(col.getId(), col); + // do not touch columnsOrder, it will be synced from table model + if (tableModel != null) { + tableModel.addColumn(col); + } + + // reassign column identifiers + setColumnIdentifiers(); + + // reattach old generated columns + for (int i = 0; i < tableModel.getColumnCount(); i++) { + Column tableModelColumn = tableModel.getColumn(i); + + if (tableModel.isGeneratedColumn(tableModelColumn)) { + TableColumn tableColumn = getColumn(tableModelColumn); + if (cellEditors[i] != null) { + tableColumn.setCellEditor(cellEditors[i]); + } + if (cellRenderers[i] != null) { + tableColumn.setCellRenderer(cellRenderers[i]); + } + } + } + return col; + } + + @Override + public void removeGeneratedColumn(String columnId) { + checkArgument(columnId != null, "columnId is null"); + Column col = getColumn(columnId); + if (col != null) { + boolean oldContentRepaintEnabled = isContentRepaintEnabled(); + setContentRepaintEnabled(false); + + TableColumn targetTableColumn = getColumn(col); + TableCellEditor cellEditor = targetTableColumn.getCellEditor(); + if (cellEditor instanceof DesktopTableCellEditor) { + Column associatedRuntimeColumn = ((DesktopTableCellEditor) cellEditor).getAssociatedRuntimeColumn(); + + removeColumn(associatedRuntimeColumn); + } + + tableModel.removeGeneratedColumn(col); + generatedColumnsCount--; + + packRows(); + repaintImplIfNeeded(); + setContentRepaintEnabled(oldContentRepaintEnabled); + } + } + + @Override + public void addAggregationProperty(String columnId, AggregationInfo.Type type) { + } + + @Override + public void addAggregationProperty(Column columnId, AggregationInfo.Type type) { + } + + @Override + public void removeAggregationProperty(String columnId) { + } + + @Override + public void setColumnCaption(String columnId, String caption) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); + } + + setColumnCaption(column, caption); + } + + @Override + public void setColumnCaption(Column column, String caption) { + checkNotNullArgument(column, "column must be non null"); + + if (!StringUtils.equals(column.getCaption(), caption)) { + column.setCaption(caption); + } + TableColumn tableColumn = getColumn(column); + + // If column is not hidden by security + if (tableColumn != null) { + tableColumn.setHeaderValue(caption); + } + } + + @Override + public void setColumnDescription(String columnId, String description) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); + } + + setColumnDescription(column, description); + } + + @Override + public void setColumnDescription(Column column, String description) { + checkNotNullArgument(column, "column must be non null"); + + if (!StringUtils.equals(column.getDescription(), description)) { + column.setDescription(description); + } + // not supported for desktop + } + + @Override + public void setTextSelectionEnabled(boolean value) { + textSelectionEnabled = value; + } + + @Override + public boolean isTextSelectionEnabled() { + return textSelectionEnabled; + } + + @Override + public void setColumnCollapsed(String columnId, boolean collapsed) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); + } + + setColumnCollapsed(column, collapsed); + } + + @Override + public void setColumnCollapsed(Column column, boolean collapsed) { + if (!getColumnControlVisible()) { + return; + } + + checkNotNullArgument(column, "column must be non null"); + + if (column.isCollapsed() != collapsed) { + column.setCollapsed(collapsed); + } + + TableColumn tableColumn = getColumn(column); + if (tableColumn instanceof TableColumnExt) { + ((TableColumnExt) tableColumn).setVisible(!collapsed); + } + } + + @Override + public void setColumnAlignment(Column column, ColumnAlignment alignment) { + checkNotNullArgument(column, "column must be non null"); + + if (column.getAlignment() != alignment) { + column.setAlignment(alignment); + } + } + + @Override + public void setColumnAlignment(String columnId, ColumnAlignment alignment) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); + } + + setColumnAlignment(column, alignment); + } + + @Override + public void setColumnWidth(Column column, int width) { + checkNotNullArgument(column, "column must be non null"); + + if (column.getWidth() == null || column.getWidth() != width) { + column.setWidth(width); + } + readjustColumns(); + } + + @Override + public void setColumnWidth(String columnId, int width) { + Column column = getColumn(columnId); + if (column == null) { + throw new IllegalStateException(String.format("Column with id '%s' not found", columnId)); + } + + setColumnWidth(column, width); + } + + @Override + public void addPrintable(String columnId, Printable printable) { + printables.put(columnId, printable); + } + + @Override + public void removePrintable(String columnId) { + printables.remove(columnId); + } + + @Override + @Nullable + public Printable getPrintable(Column column) { + checkNotNullArgument(column, "column is null"); + + return getPrintable(String.valueOf(column.getId())); + } + + @Nullable + @Override + public Printable getPrintable(String columnId) { + checkArgument(columnId != null, "columnId is null"); + + Printable printable = printables.get(columnId); + if (printable != null) { + return printable; + } else { + Column column = getColumn(columnId); + if (column != null) { + TableColumn tableColumn = getColumn(column); + TableCellEditor cellEditor = tableColumn.getCellEditor(); + if (cellEditor instanceof DesktopTableCellEditor) { + ColumnGenerator columnGenerator = ((DesktopTableCellEditor) cellEditor).getColumnGenerator(); + if (columnGenerator instanceof Printable) { + return (Printable) columnGenerator; + } + } + } + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void repaint() { + TableCellEditor cellEditor = impl.getCellEditor(); + if (cellEditor instanceof DesktopTableCellEditor) { + ((DesktopTableCellEditor) cellEditor).clearCache(); + } + + List implColumns = impl.getColumns(); + for (Column column : getColumns()) { + TableColumn tableColumn = null; + for (TableColumn implColumn : implColumns) { + if (column.equals((implColumn.getIdentifier()))) { + tableColumn = implColumn; + break; + } + } + // column may be hidden + if (tableColumn != null) { + TableCellEditor columnCellEditor = tableColumn.getCellEditor(); + if (columnCellEditor instanceof DesktopTableCellEditor) { + ((DesktopTableCellEditor) columnCellEditor).clearCache(); + } + } + } + packRows(); + repaintImplIfNeeded(); + } + + protected void repaintImplIfNeeded() { + if (contentRepaintEnabled) { + impl.repaint(); + } + } + + @Override + public boolean isEditable() { + return editable; + } + + @Override + public void setEditable(boolean editable) { + this.editable = editable; + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + impl.setEnabled(isEnabledWithParent()); + + if (buttonsPanel != null) { + ((DesktopButtonsPanel) buttonsPanel).setParentEnabled(isEnabledWithParent()); + } + } + + @Override + public ButtonsPanel getButtonsPanel() { + return buttonsPanel; + } + + @Override + public void setButtonsPanel(ButtonsPanel panel) { + if (buttonsPanel != null) { + topPanel.remove(DesktopComponentsHelper.unwrap(buttonsPanel)); + buttonsPanel.setParent(null); + } + buttonsPanel = panel; + if (panel != null) { + if (panel.getParent() != null && panel.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + topPanel.add(DesktopComponentsHelper.unwrap(panel), BorderLayout.WEST); + topPanel.setVisible(true); + + panel.setParent(this); + } + } + + @Override + public void usePresentations(boolean b) { + } + + @Override + public boolean isUsePresentations() { + return false; + } + + @Override + public void resetPresentation() { + if (defaultSettings != null) { + applySettings(defaultSettings.getRootElement()); + } + } + + @Override + public void loadPresentations() { + } + + @Override + public Presentations getPresentations() { + return null; + } + + @Override + public void applyPresentation(Object id) { + } + + @Override + public void applyPresentationAsDefault(Object id) { + } + + @Override + public Object getDefaultPresentationId() { + return null; + } + + @Override + public void applySettings(Element element) { + if (!isSettingsEnabled()) { + return; + } + + if (defaultSettings == null) { + // save default view before apply custom + defaultSettings = DocumentHelper.createDocument(); + defaultSettings.setRootElement(defaultSettings.addElement("presentation")); + + saveSettings(defaultSettings.getRootElement()); + } + + tableSettings.apply(element, isSortable()); + } + + @Override + public boolean saveSettings(Element element) { + return isSettingsEnabled() && tableSettings.saveSettings(element); + } + + @Override + public boolean isSettingsEnabled() { + return settingsEnabled; + } + + @Override + public void setSettingsEnabled(boolean settingsEnabled) { + this.settingsEnabled = settingsEnabled; + } + + @Override + public boolean isMultiSelect() { + return impl.getSelectionModel().getSelectionMode() != ListSelectionModel.SINGLE_SELECTION; + } + + @Override + public void setMultiSelect(boolean multiselect) { + if (multiselect) { + impl.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + } else { + impl.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + } + + @Override + public E getSingleSelected() { + Set selected = getSelected(); + return selected.isEmpty() ? null : selected.iterator().next(); + } + + @Override + public Set getSelected() { + Set set = new HashSet<>(); + int[] rows = impl.getSelectedRows(); + for (int row : rows) { + int modelRow = impl.convertRowIndexToModel(row); + Object item = tableModel.getItem(modelRow); + if (item != null) { + //noinspection unchecked + set.add((E) item); + } + } + return set; + } + + @Override + public void setSelected(E item) { + if (item != null) { + setSelected(Collections.singleton(item)); + } else { + setSelected(Collections.emptySet()); + } + } + + @Override + public void setSelected(Collection items) { + if (items == null) { + items = Collections.emptyList(); + } + for (Entity item : items) { + // noinspection unchecked + if (!datasource.containsItem(item.getId())) { + throw new IllegalStateException("Datasource does not contain specified item: " + item.getId()); + } + } + impl.clearSelection(); + if (!items.isEmpty()) { + List indexes = getSelectionIndexes(items); + if (!indexes.isEmpty()) { + applySelectionIndexes(indexes); + } + } + } + + @Override + protected void attachAction(Action action) { + if (action instanceof Action.HasTarget) { + ((Action.HasTarget) action).setTarget(this); + } + + super.attachAction(action); + } + + protected void applySelectionIndexes(List indexes) { + Collections.sort(indexes); + ListSelectionModel model = impl.getSelectionModel(); + model.setValueIsAdjusting(true); + int lastOpened = indexes.get(0); + int current = indexes.get(0); + for (Integer index : indexes) { + if (index > current + 1) { + model.addSelectionInterval(lastOpened, current); + lastOpened = index; + } + current = index; + } + model.addSelectionInterval(lastOpened, current); + model.setValueIsAdjusting(false); + } + + protected List getSelectionIndexes(Collection items) { + if (items.isEmpty()) { + return Collections.emptyList(); + } + List indexes = Lists.newArrayList(); + if (datasource instanceof CollectionDatasource.Ordered) { + HashSet itemSet = new HashSet<>(items); + int itemIndex = 0; + CollectionDatasource.Ordered orderedDs = (CollectionDatasource.Ordered) datasource; + Object id = orderedDs.firstItemId(); + while (id != null && !itemSet.isEmpty()) { + int rowIndex = impl.convertRowIndexToView(itemIndex); + // noinspection unchecked + Entity itemById = datasource.getItem(id); + if (itemSet.contains(itemById)) { + indexes.add(rowIndex); + itemSet.remove(itemById); + } + // noinspection unchecked + id = orderedDs.nextItemId(id); + itemIndex++; + } + } else { + for (Entity item : items) { + int idx = tableModel.getRowIndex(item); + if (idx != -1) { + indexes.add(impl.convertColumnIndexToView(idx)); + } + } + } + return indexes; + } + + @Override + public CollectionDatasource getDatasource() { + return datasource; + } + + @Override + public void refresh() { + if (datasource != null) { + datasource.refresh(); + packRows(); + repaintImplIfNeeded(); + } + } + + protected JPopupMenu createPopupMenu() { + JPopupMenu popup = new JPopupMenu(); + JMenuItem menuItem; + for (final Action action : actionList) { + if (StringUtils.isNotBlank(action.getCaption()) + && action.isVisible()) { + menuItem = new JMenuItem(action.getCaption()); + if (action.getIcon() != null) { + menuItem.setIcon(App.getInstance().getResources().getIcon(action.getIcon())); + } + if (action.getShortcutCombination() != null) { + menuItem.setAccelerator(convertKeyCombination(action.getShortcutCombination())); + } + menuItem.setEnabled(action.isEnabled()); + menuItem.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + action.actionPerform(DesktopAbstractTable.this); + } + } + ); + popup.add(menuItem); + } + } + return popup; + } + + /** + * Returns the preferred height of a row. + * The result is equal to the tallest cell in the row. + * + * @param rowIndex row index + * @return row height + */ + public int getPreferredRowHeight(int rowIndex) { + // Get the current default height for all rows + int height = impl.getRowHeight(); + + // Determine highest cell in the row + for (int c = 0; c < impl.getColumnCount(); c++) { + TableCellRenderer renderer = impl.getCellRenderer(rowIndex, c); + Component comp = impl.prepareRenderer(renderer, rowIndex, c); + int componentHeight = comp.getPreferredSize().height; + height = Math.max(height, componentHeight); + } + return height; + } + + protected void applyFont(JTable table, Font font) { + Graphics graphics = table.getGraphics(); + if (graphics != null) { + FontMetrics metrics = graphics.getFontMetrics(font); + defaultRowHeight = metrics.getHeight() + DEFAULT_ROW_MARGIN; + fontInitialized = true; + if (impl != null) { + packRows(); + } + } + } + + /** + * Sets the height of each row into the preferred height of the tallest cell in that row. + */ + public void packRows() { + if (!contentRepaintEnabled) { + return; + } + + impl.setRowHeight(defaultRowHeight); + + for (Column column : columnsOrder) { + if (column.isEditable()) { + impl.setRowHeight(defaultEditableRowHeight); + break; + } + } + + if (allColumnsAreInline()) { + return; + } + + int preferredRowHeight = -1; + boolean equalsRowHeight = true; + + StopWatch sw = new Log4JStopWatch("DAT packRows " + id); + for (int r = 0; r < impl.getRowCount(); r++) { + int h = getPreferredRowHeight(r); + + if (preferredRowHeight == -1) { + preferredRowHeight = h; + } else if (preferredRowHeight != h) { + equalsRowHeight = false; + } + + if (impl.getRowHeight(r) != h) { + impl.setRowHeight(r, h); + } + } + + if (equalsRowHeight && preferredRowHeight > 0) { + impl.setRowHeight(preferredRowHeight); + } + + sw.stop(); + } + + protected boolean allColumnsAreInline() { + if (generatedColumnsCount <= 0) { + return true; + } + + for (Column column : columnsOrder) { + if (!tableModel.isGeneratedColumn(column)) { + continue; + } + + TableColumn tableColumn = getColumn(column); + if (tableColumn != null) { + DesktopTableCellEditor cellEditor = (DesktopTableCellEditor) tableColumn.getCellEditor(); + if (cellEditor != null) { + boolean inline = cellEditor.isInline(); + if (!inline) { + return false; + } + } + } + } + return true; + } + + protected TableColumn getColumn(Column column) { + List tableColumns = getAllColumns(); + + for (TableColumn tableColumn : tableColumns) { + if (column.equals(tableColumn.getIdentifier())) { + return tableColumn; + } + } + + return null; + } + + @Override + public void addColumnCollapsedListener(ColumnCollapseListener columnCollapsedListener) { + } + + @Override + public void removeColumnCollapseListener(ColumnCollapseListener columnCollapseListener) { + } + + @Override + public void setClickListener(String columnId, CellClickListener clickListener) { + } + + @Override + public void removeClickListener(String columnId) { + } + + public AnyTableModelAdapter getTableModel() { + return tableModel; + } + + public boolean isContentRepaintEnabled() { + return contentRepaintEnabled; + } + + public void setContentRepaintEnabled(boolean contentRepaintEnabled) { + if (this.contentRepaintEnabled != contentRepaintEnabled) { + this.contentRepaintEnabled = contentRepaintEnabled; + + packRows(); + repaintImplIfNeeded(); + } + } + + protected void applyStylename(boolean isSelected, boolean hasFocus, Component component, String style) { + if (style == null) { + return; + } + + DesktopTheme theme = App.getInstance().getTheme(); + if (theme != null) { + HashSet properties = new HashSet<>(); + + if (hasFocus) { + properties.add("focused"); + } else if (isSelected) { + properties.add("selected"); + } else { + properties.add("unselected"); + } + theme.applyStyle(component, style, properties); + } + } + + protected String getStylename(JTable table, int row, int column) { + if (styleProviders == null) { + return null; + } + + Entity item = tableModel.getItem(row); + int modelColumn = table.convertColumnIndexToModel(column); + Object property = columnsOrder.get(modelColumn).getId(); + + String joinedStyle = null; + for (StyleProvider styleProvider : styleProviders) { + //noinspection unchecked + String styleName = styleProvider.getStyleName(item, property.toString()); + if (styleName != null) { + if (joinedStyle == null) { + joinedStyle = styleName; + } else { + joinedStyle += " " + styleName; + } + } + } + + return joinedStyle; + } + + protected TableCellEditor getColumnEditor(int column) { + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + if (tableColumn.getIdentifier() instanceof Table.Column) { + Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); + + if (columnConf.getId() instanceof MetaPropertyPath + && !(isEditable() && columnConf.isEditable()) + && !getTableModel().isGeneratedColumn(columnConf)) { + MetaPropertyPath propertyPath = (MetaPropertyPath) columnConf.getId(); + + final CellProvider cellProvider = getCustomCellEditor(propertyPath); + if (cellProvider != null) { + return new CellProviderEditor(cellProvider); + } + } + } + return null; + } + + protected TableCellRenderer getColumnRenderer(int column) { + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + if (tableColumn.getIdentifier() instanceof Table.Column) { + Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); + if (columnConf.getId() instanceof MetaPropertyPath + && !(isEditable() && columnConf.isEditable()) + && !getTableModel().isGeneratedColumn(columnConf)) { + MetaPropertyPath propertyPath = (MetaPropertyPath) columnConf.getId(); + + final CellProvider cellViewProvider = getCustomCellView(propertyPath); + if (cellViewProvider != null) { + return new CellProviderRenderer(cellViewProvider); + } else if (multiLineCells && String.class == columnConf.getType()) { + return new MultiLineTableCellRenderer(); + } + } + } + return null; + } + + protected boolean isCustomCellEditable(int row, int column) { + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + if (tableColumn.getIdentifier() instanceof Table.Column) { + Table.Column columnConf = (Table.Column) tableColumn.getIdentifier(); + if (columnConf.getId() instanceof MetaPropertyPath && !getTableModel().isGeneratedColumn(columnConf)) { + return isCustomCellEditable(tableModel.getItem(row), (MetaPropertyPath) columnConf.getId()); + } + } + return false; + } + + @SuppressWarnings("UnusedParameters") + protected CellProvider getCustomCellView(MetaPropertyPath mpp) { + return null; + } + + @SuppressWarnings("UnusedParameters") + protected CellProvider getCustomCellEditor(MetaPropertyPath mpp) { + return null; + } + + @SuppressWarnings("UnusedParameters") + protected boolean isCustomCellEditable(Entity e, MetaPropertyPath mpp) { + return false; + } + + @Override + public void setId(String id) { + super.setId(id); + + if (id != null && App.getInstance().isTestMode()) { + getComposition().setName(id + "_composition"); + } + } + + @Override + public void assignAutoDebugId() { + super.assignAutoDebugId(); + + if (buttonsPanel != null) { + for (com.haulmont.cuba.gui.components.Component subComponent : buttonsPanel.getComponents()) { + if (subComponent instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) subComponent).assignAutoDebugId(); + } + } + } + } + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { + return "table_" + datasource.getId(); + } + + return getClass().getSimpleName(); + } + + @Override + public void showCustomPopup(com.haulmont.cuba.gui.components.Component popupComponent) { + } + + @Override + public void showCustomPopupActions(List actions) { + } + + @Override + public void setColumnSortable(String columnId, boolean sortable) { + } + + @Override + public boolean getColumnSortable(String columnId) { + return true; + } + + @Override + public void setColumnSortable(Column column, boolean sortable) { + } + + @Override + public boolean getColumnSortable(Column column) { + return true; + } + + @Override + public void setColumnHeaderVisible(boolean visible) { + columnHeaderVisible = visible; + } + + @Override + public boolean isColumnHeaderVisible() { + return columnHeaderVisible; + } + + @Override + public void setShowSelection(boolean showSelection) { + this.showSelection = showSelection; + } + + @Override + public boolean isShowSelection() { + return showSelection; + } + + @Override + public void requestFocus(E itemId, String columnId) { + // unsupported for desktop + } + + @Override + public void scrollTo(E item) { + Preconditions.checkNotNullArgument(item); + int rowIndex = tableModel.getRowIndex(item); + if (rowIndex == -1) { + throw new IllegalArgumentException("Unable to find item in Table"); + } + + impl.scrollRowToVisible(rowIndex); + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + @Override + public void addLookupValueChangeListener(LookupSelectionChangeListener listener) { + if (!lookupSelectionChangeListeners.contains(listener)) { + lookupSelectionChangeListeners.add(listener); + } + } + + @Override + public void removeLookupValueChangeListener(LookupSelectionChangeListener listener) { + lookupSelectionChangeListeners.remove(listener); + } + + /** + * Uses delegate renderer to create cell component. + * Then applies desktop styles to cell component. + */ + protected class StylingCellRenderer implements TableCellRenderer { + + private TableCellRenderer delegate; + + public StylingCellRenderer(TableCellRenderer delegate) { + this.delegate = delegate; + } + + public StylingCellRenderer() { + } + + public TableCellRenderer getDelegate() { + return delegate; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + TableCellRenderer renderer = delegate; + if (renderer == null) { + renderer = table.getDefaultRenderer(value != null ? value.getClass() : Object.class); + } + java.awt.Component component = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + if (0 <= row) { + String style = getStylename(table, row, column); + applyStylename(isSelected, hasFocus, component, style); + } + return component; + } + } + + protected class CellProviderEditor extends AbstractCellEditor implements TableCellEditor { + private final CellProvider cellProvider; + + public CellProviderEditor(CellProvider cellProvider) { + this.cellProvider = cellProvider; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, + boolean isSelected, int row, int column) { + Entity item = getTableModel().getItem(row); + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + Column columnConf = (Column) tableColumn.getIdentifier(); + + Component component = cellProvider.generateCell(item, (MetaPropertyPath) columnConf.getId()); + + if (component == null) { + return new JLabel(""); + } + + if (component instanceof JComponent) { + ((JComponent) component).putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, impl); + } + + return component; + } + + @Override + public Object getCellEditorValue() { + DesktopComponentsHelper.flushCurrentInputField(); + return ""; + } + } + + protected class CellProviderRenderer implements TableCellRenderer { + private final CellProvider cellViewProvider; + + public CellProviderRenderer(CellProvider cellViewProvider) { + this.cellViewProvider = cellViewProvider; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Entity item = getTableModel().getItem(row); + TableColumn tableColumn = impl.getColumnModel().getColumn(column); + Column columnConf = (Column) tableColumn.getIdentifier(); + + Component component = cellViewProvider.generateCell(item, (MetaPropertyPath) columnConf.getId()); + + if (component == null) { + return new JLabel(""); + } + + if (component instanceof JComponent) { + ((JComponent) component).putClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE, impl); + } + + String style = getStylename(table, row, column); + applyStylename(isSelected, hasFocus, component, style); + + return component; + } + } + + protected class MultiLineTableCellRenderer extends JTextArea implements TableCellRenderer { + private List> rowColHeight = new ArrayList<>(); + + public MultiLineTableCellRenderer() { + setLineWrap(true); + setWrapStyleWord(true); + setOpaque(true); + setBorder(new EmptyBorder(0, 0, 0, 0)); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + if (isSelected) { + setForeground(table.getSelectionForeground()); + setBackground(table.getSelectionBackground()); + } else { + setForeground(table.getForeground()); + Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); + if (row % 2 == 1) { + Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); + if (alternateColor != null) { + background = alternateColor; + } + } + setBackground(background); + } + setFont(table.getFont()); + + Border border = null; + if (isSelected) { + border = UIManager.getDefaults().getBorder("Table.focusSelectedCellHighlightBorder"); + } + if (border == null) { + border = UIManager.getDefaults().getBorder("Table.focusCellHighlightBorder"); + } + + if (hasFocus) { + setBorder(border); + if (table.isCellEditable(row, column)) { + setForeground(UIManager.getColor("Table.focusCellForeground")); + setBackground(UIManager.getColor("Table.focusCellBackground")); + } + } else { + setBorder(UIManager.getDefaults().getBorder("Table.cellNoFocusBorder")); + } + + if (value != null) { + setText(value.toString()); + } else { + setText(""); + } + adjustRowHeight(table, row, column); + return this; + } + + /** + * Calculate the new preferred height for a given row, and sets the height on the table. + */ + private void adjustRowHeight(JTable table, int row, int column) { + //The trick to get this to work properly is to set the width of the column to the + //textarea. The reason for this is that getPreferredSize(), without a width tries + //to place all the text in one line. By setting the size with the with of the column, + //getPreferredSize() returnes the proper height which the row should have in + //order to make room for the text. + int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth(); + setSize(new Dimension(cWidth, 1000)); + int prefH = getPreferredSize().height; + while (rowColHeight.size() <= row) { + rowColHeight.add(new ArrayList(column)); + } + List colHeights = rowColHeight.get(row); + while (colHeights.size() <= column) { + colHeights.add(0); + } + colHeights.set(column, prefH); + int maxH = prefH; + for (Integer colHeight : colHeights) { + if (colHeight > maxH) { + maxH = colHeight; + } + } + if (table.getRowHeight(row) != maxH) { + table.setRowHeight(row, maxH); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButton.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButton.java index 99eac65cde..4b7e347278 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButton.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButton.java @@ -1,227 +1,227 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Button; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -public class DesktopButton extends DesktopAbstractComponent implements Button { - - protected Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - - protected Action action; - protected String icon; - - protected long responseEndTs = 0; - protected boolean shouldBeFocused = true; - - protected PropertyChangeListener actionPropertyChangeListener; - protected boolean disableOnClick = false; - protected boolean useResponsePending = false; - - public DesktopButton() { - impl = createImplementation(); - impl.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - if (action != null) { - if (shouldBeFocused && !impl.isFocusOwner() && impl.isFocusable()) { - return; - } - - if (useResponsePending && e.getWhen() <= responseEndTs) { - return; - } - - if (disableOnClick) { - impl.setEnabled(false); - } - - try { - userActionsLog.trace("Button (id = {}, caption = {}) on frame {} was clicked", id, caption, - frame == null ? " NULL " : frame.getId()); - - action.actionPerform(DesktopButton.this); - } finally { - responseEndTs = System.currentTimeMillis(); - } - } - } - }); - DesktopComponentsHelper.adjustSize(impl); - } - - protected JButton createImplementation() { - return new JButton(); - } - - @Override - public com.haulmont.cuba.gui.components.Action getAction() { - return action; - } - - @Override - public void setAction(Action action) { - if (action != this.action) { - if (this.action != null) { - this.action.removeOwner(this); - this.action.removePropertyChangeListener(actionPropertyChangeListener); - } - - this.action = action; - - if (action != null) { - String caption = action.getCaption(); - if (caption != null && getCaption() == null) { - setCaption(caption); - } - - String description = action.getDescription(); - if (description == null && action.getShortcutCombination() != null) { - description = action.getShortcutCombination().format(); - } - if (description != null && getDescription() == null) { - setDescription(description); - } - - setEnabled(action.isEnabled()); - setVisible(action.isVisible()); - - if (action.getIcon() != null && getIcon() == null) { - setIcon(action.getIcon()); - } - - action.addOwner(this); - - actionPropertyChangeListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Action.PROP_ICON.equals(evt.getPropertyName())) { - setIcon(DesktopButton.this.action.getIcon()); - } else if (Action.PROP_CAPTION.equals(evt.getPropertyName())) { - setCaption(DesktopButton.this.action.getCaption()); - } else if (Action.PROP_DESCRIPTION.equals(evt.getPropertyName())) { - setDescription(DesktopButton.this.action.getDescription()); - } else if (Action.PROP_ENABLED.equals(evt.getPropertyName())) { - setEnabled(DesktopButton.this.action.isEnabled()); - } else if (Action.PROP_VISIBLE.equals(evt.getPropertyName())) { - setVisible(DesktopButton.this.action.isVisible()); - } - } - }; - action.addPropertyChangeListener(actionPropertyChangeListener); - - assignAutoDebugId(); - } - } - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - impl.setText(caption == null ? "" : caption); - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } - - @Override - public String getIcon() { - return icon; - } - - @Override - public void setIcon(String icon) { - this.icon = icon; - if (icon != null) - impl.setIcon(App.getInstance().getResources().getIcon(icon)); - else - impl.setIcon(null); - } - - public boolean isShouldBeFocused() { - return shouldBeFocused; - } - - public void setShouldBeFocused(boolean shouldBeFocused) { - this.shouldBeFocused = shouldBeFocused; - } - - @Override - protected String getAlternativeDebugId() { - if (StringUtils.isNotEmpty(id)) { - return id; - } - if (action != null && StringUtils.isNotEmpty(action.getId())) { - return action.getId(); - } - - return getClass().getSimpleName(); - } - - @Override - public boolean isFocusable() { - return impl.isFocusable(); - } - - @Override - public void setFocusable(boolean focusable) { - impl.setFocusable(focusable); - } - - @Override - public void setDisableOnClick(boolean disableOnClick) { - this.disableOnClick = disableOnClick; - } - - @Override - public boolean isDisableOnClick() { - return disableOnClick; - } - - @Override - public boolean isUseResponsePending() { - return useResponsePending; - } - - @Override - public void setUseResponsePending(boolean useResponsePending) { - this.useResponsePending = useResponsePending; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Button; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class DesktopButton extends DesktopAbstractComponent implements Button { + + protected Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + + protected Action action; + protected String icon; + + protected long responseEndTs = 0; + protected boolean shouldBeFocused = true; + + protected PropertyChangeListener actionPropertyChangeListener; + protected boolean disableOnClick = false; + protected boolean useResponsePending = false; + + public DesktopButton() { + impl = createImplementation(); + impl.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + if (action != null) { + if (shouldBeFocused && !impl.isFocusOwner() && impl.isFocusable()) { + return; + } + + if (useResponsePending && e.getWhen() <= responseEndTs) { + return; + } + + if (disableOnClick) { + impl.setEnabled(false); + } + + try { + userActionsLog.trace("Button (id = {}, caption = {}) on frame {} was clicked", id, caption, + frame == null ? " NULL " : frame.getId()); + + action.actionPerform(DesktopButton.this); + } finally { + responseEndTs = System.currentTimeMillis(); + } + } + } + }); + DesktopComponentsHelper.adjustSize(impl); + } + + protected JButton createImplementation() { + return new JButton(); + } + + @Override + public com.haulmont.cuba.gui.components.Action getAction() { + return action; + } + + @Override + public void setAction(Action action) { + if (action != this.action) { + if (this.action != null) { + this.action.removeOwner(this); + this.action.removePropertyChangeListener(actionPropertyChangeListener); + } + + this.action = action; + + if (action != null) { + String caption = action.getCaption(); + if (caption != null && getCaption() == null) { + setCaption(caption); + } + + String description = action.getDescription(); + if (description == null && action.getShortcutCombination() != null) { + description = action.getShortcutCombination().format(); + } + if (description != null && getDescription() == null) { + setDescription(description); + } + + setEnabled(action.isEnabled()); + setVisible(action.isVisible()); + + if (action.getIcon() != null && getIcon() == null) { + setIcon(action.getIcon()); + } + + action.addOwner(this); + + actionPropertyChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Action.PROP_ICON.equals(evt.getPropertyName())) { + setIcon(DesktopButton.this.action.getIcon()); + } else if (Action.PROP_CAPTION.equals(evt.getPropertyName())) { + setCaption(DesktopButton.this.action.getCaption()); + } else if (Action.PROP_DESCRIPTION.equals(evt.getPropertyName())) { + setDescription(DesktopButton.this.action.getDescription()); + } else if (Action.PROP_ENABLED.equals(evt.getPropertyName())) { + setEnabled(DesktopButton.this.action.isEnabled()); + } else if (Action.PROP_VISIBLE.equals(evt.getPropertyName())) { + setVisible(DesktopButton.this.action.isVisible()); + } + } + }; + action.addPropertyChangeListener(actionPropertyChangeListener); + + assignAutoDebugId(); + } + } + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + impl.setText(caption == null ? "" : caption); + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } + + @Override + public String getIcon() { + return icon; + } + + @Override + public void setIcon(String icon) { + this.icon = icon; + if (icon != null) + impl.setIcon(App.getInstance().getResources().getIcon(icon)); + else + impl.setIcon(null); + } + + public boolean isShouldBeFocused() { + return shouldBeFocused; + } + + public void setShouldBeFocused(boolean shouldBeFocused) { + this.shouldBeFocused = shouldBeFocused; + } + + @Override + protected String getAlternativeDebugId() { + if (StringUtils.isNotEmpty(id)) { + return id; + } + if (action != null && StringUtils.isNotEmpty(action.getId())) { + return action.getId(); + } + + return getClass().getSimpleName(); + } + + @Override + public boolean isFocusable() { + return impl.isFocusable(); + } + + @Override + public void setFocusable(boolean focusable) { + impl.setFocusable(focusable); + } + + @Override + public void setDisableOnClick(boolean disableOnClick) { + this.disableOnClick = disableOnClick; + } + + @Override + public boolean isDisableOnClick() { + return disableOnClick; + } + + @Override + public boolean isUseResponsePending() { + return useResponsePending; + } + + @Override + public void setUseResponsePending(boolean useResponsePending) { + this.useResponsePending = useResponsePending; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButtonsPanel.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButtonsPanel.java index 96c91dde12..c87b194edc 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButtonsPanel.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopButtonsPanel.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.ButtonsPanel; -import com.haulmont.cuba.gui.components.Component; - -import javax.swing.*; - -public class DesktopButtonsPanel extends DesktopHBox implements ButtonsPanel { - - public DesktopButtonsPanel() { - setSpacing(true); - } - - public void setFocusableForAllButtons(boolean focusable) { - for (Component button : getComponents()) { - JComponent jButton = DesktopComponentsHelper.unwrap(button); - if (button instanceof DesktopButton) { - ((DesktopButton) button).setShouldBeFocused(focusable); - } - jButton.setFocusable(focusable); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.ButtonsPanel; +import com.haulmont.cuba.gui.components.Component; + +import javax.swing.*; + +public class DesktopButtonsPanel extends DesktopHBox implements ButtonsPanel { + + public DesktopButtonsPanel() { + setSpacing(true); + } + + public void setFocusableForAllButtons(boolean focusable) { + for (Component button : getComponents()) { + JComponent jButton = DesktopComponentsHelper.unwrap(button); + if (button instanceof DesktopButton) { + ((DesktopButton) button).setShouldBeFocused(focusable); + } + jButton.setFocusable(focusable); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopCheckBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopCheckBox.java index b437ab9f6f..6f7e923187 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopCheckBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopCheckBox.java @@ -1,244 +1,244 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.gui.components.CheckBox; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.FieldGroup; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.ObjectUtils; - -import javax.swing.*; - -public class DesktopCheckBox extends DesktopAbstractField implements CheckBox { - protected Datasource datasource; - protected boolean updatingInstance; - protected Object prevValue; - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - public DesktopCheckBox() { - impl = new JCheckBox(); - impl.addActionListener(e -> { - updateInstance(); - fireChangeListeners(impl.isSelected()); - }); - } - - @SuppressWarnings("unchecked") - @Override - public Boolean getValue() { - return impl.isSelected(); - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (value == null) { - value = false; - } - - if (!ObjectUtils.equals(prevValue, value)) { - updateComponent(value); - updateInstance(); - fireChangeListeners(value); - } - } - - private void updateComponent(Object value) { - impl.setSelected(value != null && BooleanUtils.isTrue((Boolean) value)); - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - @SuppressWarnings("unchecked") - @Override - public void setDatasource(Datasource datasource, String property) { - this.datasource = datasource; - - if (datasource == null) { - setValue(null); - return; - } - resolveMetaPropertyPath(datasource.getMetaClass(), property); - - itemChangeListener = e -> { - if (updatingInstance) - return; - Boolean value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); - if (value == null) { - value = false; - } - - updateComponent(value); - fireChangeListeners(value); - }; - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) { - return; - } - - if (e.getProperty().equals(metaPropertyPath.toString())) { - Object value = e.getValue(); - if (e.getValue() == null) { - value = false; - } - - updateComponent(value); - fireChangeListeners(value); - } - }; - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - if (datasource.getItemIfValid() != null) { - Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); - - if (!ObjectUtils.equals(prevValue, newValue)) { - updateComponent(newValue); - fireChangeListeners(newValue); - } - } - - if (metaProperty.isReadOnly()) { - setEditable(false); - } - - initBeanValidator(); - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - if (!(parent instanceof FieldGroup)) { - impl.setText(caption); - } - } - - @Override - public void setParent(Component parent) { - super.setParent(parent); - - if (parent instanceof FieldGroup) { - impl.setText(null); - } - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } - - @Override - protected void setEditableToComponent(boolean editable) { - updateEnabled(); - } - - @Override - public void updateEnabled() { - impl.setEnabled(editable && isEnabledWithParent()); - } - - protected void updateInstance() { - if (updatingInstance) - return; - - updatingInstance = true; - try { - if ((datasource != null) && (metaPropertyPath != null)) { - boolean value = impl.isSelected(); - if (datasource.getItem() != null) { - InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); - } - } - } finally { - updatingInstance = false; - } - } - - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = newValue; - if (!ObjectUtils.equals(oldValue, newValue)) { - fireValueChanged(oldValue, newValue); - } - } - - @Override - public boolean isChecked() { - return impl.isSelected(); - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.gui.components.CheckBox; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.FieldGroup; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.ObjectUtils; + +import javax.swing.*; + +public class DesktopCheckBox extends DesktopAbstractField implements CheckBox { + protected Datasource datasource; + protected boolean updatingInstance; + protected Object prevValue; + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + public DesktopCheckBox() { + impl = new JCheckBox(); + impl.addActionListener(e -> { + updateInstance(); + fireChangeListeners(impl.isSelected()); + }); + } + + @SuppressWarnings("unchecked") + @Override + public Boolean getValue() { + return impl.isSelected(); + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (value == null) { + value = false; + } + + if (!ObjectUtils.equals(prevValue, value)) { + updateComponent(value); + updateInstance(); + fireChangeListeners(value); + } + } + + private void updateComponent(Object value) { + impl.setSelected(value != null && BooleanUtils.isTrue((Boolean) value)); + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + @SuppressWarnings("unchecked") + @Override + public void setDatasource(Datasource datasource, String property) { + this.datasource = datasource; + + if (datasource == null) { + setValue(null); + return; + } + resolveMetaPropertyPath(datasource.getMetaClass(), property); + + itemChangeListener = e -> { + if (updatingInstance) + return; + Boolean value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); + if (value == null) { + value = false; + } + + updateComponent(value); + fireChangeListeners(value); + }; + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) { + return; + } + + if (e.getProperty().equals(metaPropertyPath.toString())) { + Object value = e.getValue(); + if (e.getValue() == null) { + value = false; + } + + updateComponent(value); + fireChangeListeners(value); + } + }; + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + if (datasource.getItemIfValid() != null) { + Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); + + if (!ObjectUtils.equals(prevValue, newValue)) { + updateComponent(newValue); + fireChangeListeners(newValue); + } + } + + if (metaProperty.isReadOnly()) { + setEditable(false); + } + + initBeanValidator(); + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + if (!(parent instanceof FieldGroup)) { + impl.setText(caption); + } + } + + @Override + public void setParent(Component parent) { + super.setParent(parent); + + if (parent instanceof FieldGroup) { + impl.setText(null); + } + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } + + @Override + protected void setEditableToComponent(boolean editable) { + updateEnabled(); + } + + @Override + public void updateEnabled() { + impl.setEnabled(editable && isEnabledWithParent()); + } + + protected void updateInstance() { + if (updatingInstance) + return; + + updatingInstance = true; + try { + if ((datasource != null) && (metaPropertyPath != null)) { + boolean value = impl.isSelected(); + if (datasource.getItem() != null) { + InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); + } + } + } finally { + updatingInstance = false; + } + } + + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = newValue; + if (!ObjectUtils.equals(oldValue, newValue)) { + fireValueChanged(oldValue, newValue); + } + } + + @Override + public boolean isChecked() { + return impl.isSelected(); + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponent.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponent.java index 0e0f09adaf..43b50fc833 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponent.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponent.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.Component; - -/** - * - * Desktop components require to know their container. - * - * When its size or alignment changes, component asks container to update him. - * - */ -public interface DesktopComponent extends Component { - void setContainer(DesktopContainer container); - - void setExpanded(boolean expanded); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.Component; + +/** + * + * Desktop components require to know their container. + * + * When its size or alignment changes, component asks container to update him. + * + */ +public interface DesktopComponent extends Component { + void setContainer(DesktopContainer container); + + void setExpanded(boolean expanded); +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponentsHelper.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponentsHelper.java index 28ee2a72c8..4144ec4d5b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponentsHelper.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopComponentsHelper.java @@ -1,461 +1,461 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DetachedFrame; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; -import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; -import com.haulmont.cuba.desktop.sys.vcl.Flushable; -import com.haulmont.cuba.desktop.sys.vcl.FocusableComponent; -import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import org.slf4j.LoggerFactory; - -import javax.swing.Action; -import javax.swing.*; -import javax.swing.BoxLayout; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.util.Collections; - -public class DesktopComponentsHelper { - - public static final int BUTTON_HEIGHT = 30; - public static final int FIELD_HEIGHT = 28; - - // todo move nimbus constants to theme - public static final Color defaultBgColor = (Color) UIManager.get("nimbusLightBackground"); - public static final Color requiredBgColor = (Color) UIManager.get("cubaRequiredBackground"); - - /** - * Returns underlying Swing component implementation. - * - * @param component GUI component - * @return Swing component - * @see #getComposition(com.haulmont.cuba.gui.components.Component) - */ - public static JComponent unwrap(Component component) { - Object comp = component; - while (comp instanceof Component.Wrapper) { - comp = ((Component.Wrapper) comp).getComponent(); - } - return (JComponent) comp; - } - - /** - * Returns underlying Swing component, which serves as the outermost container for the supplied GUI component. - * For simple components like {@link com.haulmont.cuba.gui.components.Button} this method returns the same - * result as {@link #unwrap(com.haulmont.cuba.gui.components.Component)}. - * - * @param component GUI component - * @return Swing component - * @see #unwrap(com.haulmont.cuba.gui.components.Component) - */ - public static JComponent getComposition(Component component) { - Object comp = component; - while (comp instanceof Component.Wrapper) { - comp = ((Component.Wrapper) comp).getComposition(); - } - return (JComponent) comp; - } - - public static int convertMessageType(Frame.MessageMode messageType) { - switch (messageType) { - case CONFIRMATION: - case CONFIRMATION_HTML: - return JOptionPane.QUESTION_MESSAGE; - case WARNING: - case WARNING_HTML: - return JOptionPane.WARNING_MESSAGE; - default: - return JOptionPane.INFORMATION_MESSAGE; - } - } - - public static int convertNotificationType(com.haulmont.cuba.gui.components.Frame.NotificationType type) { - switch (type) { - case WARNING: - case WARNING_HTML: - return JOptionPane.WARNING_MESSAGE; - case ERROR: - case ERROR_HTML: - return JOptionPane.ERROR_MESSAGE; - case HUMANIZED: - case HUMANIZED_HTML: - return JOptionPane.INFORMATION_MESSAGE; - case TRAY: - case TRAY_HTML: - return JOptionPane.WARNING_MESSAGE; - default: - return JOptionPane.PLAIN_MESSAGE; - } - } - - public static void adjustSize(JButton button) { - button.setPreferredSize(new Dimension(0, BUTTON_HEIGHT)); - button.setMaximumSize(new Dimension(Integer.MAX_VALUE, BUTTON_HEIGHT)); - } - - public static void adjustSize(JComboBox comboBox) { - comboBox.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); - } - - public static void adjustSize(JTextField textField) { - textField.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); - } - - public static void adjustDateFieldSize(JPanel dateFieldComposition) { - dateFieldComposition.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); - } - - /** - * Convert {@link KeyCombination} to {@link KeyStroke}. - * - * @param combination Key combination to convert - * @return KeyStroke - */ - public static KeyStroke convertKeyCombination(KeyCombination combination) { - KeyCombination.Modifier[] modifiers = combination.getModifiers(); - int modifiersMask = 0; - if (modifiers != null && modifiers.length > 0) { - for (KeyCombination.Modifier modifier : modifiers) { - modifiersMask = modifiersMask | convertModifier(modifier); - } - } - return KeyStroke.getKeyStroke(combination.getKey().getVirtualKey(), modifiersMask, false); - } - - /** - * Convert {@link KeyCombination.Modifier} to {@link InputEvent} modifier constraint. - * - * @param modifier modifier to convert - * @return {@link InputEvent} modifier constraint - */ - public static int convertModifier(KeyCombination.Modifier modifier) { - switch (modifier) { - case CTRL: - return InputEvent.CTRL_DOWN_MASK; - case ALT: - return InputEvent.ALT_DOWN_MASK; - case SHIFT: - return InputEvent.SHIFT_DOWN_MASK; - default: - throw new IllegalArgumentException("Modifier " + modifier.name() + " not recognized"); - } - } - - /** - * Make JTable handle TAB key as all other components - move focus to next/previous components. - *

Default Swing behaviour for table is to move focus to next/previous cell inside the table.

- * @param table table instance - */ - public static void correctTableFocusTraversal(JTable table) { - table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, - Collections.singleton(AWTKeyStroke.getAWTKeyStroke("TAB"))); - table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, - Collections.singleton(AWTKeyStroke.getAWTKeyStroke("shift TAB"))); - } - - /** - * Add shortcut action to any JComponent. - * - * @param name name of action that used as action key in {@link InputMap} and {@link ActionMap}. - * @param component - * @param key - * @param action - */ - public static void addShortcutAction(String name, JComponent component, KeyStroke key, Action action) { - ActionMap actionMap = component.getActionMap(); - InputMap inputMap = component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - inputMap.put(key, name); - actionMap.put(name, action); - } - - public static void decorateMissingValue(JComponent jComponent, boolean missingValueState) { - jComponent.setBackground(missingValueState ? requiredBgColor : defaultBgColor); - } - - /** - * @return {@link TopLevelFrame} of container - */ - public static TopLevelFrame getTopLevelFrame(Container container) { - Container prevContainer; - Container parent = container; - do { - prevContainer = parent; - if (parent instanceof DetachedFrame) { - parent = ((DetachedFrame) parent).getParentContainer(); - } if (parent instanceof JPopupMenu) { - parent = ((JPopupMenu) parent).getInvoker().getParent(); - } else { - parent = parent.getParent(); - } - } while (parent != null); - - if (!(prevContainer instanceof TopLevelFrame)) { - if (prevContainer instanceof JComponent) { - Object tableForEditor = ((JComponent) prevContainer).getClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE); - if (tableForEditor != null) { - return getTopLevelFrame((java.awt.Component) tableForEditor); - } - } - - return App.getInstance().getMainFrame(); - } - - return (TopLevelFrame) prevContainer; - } - - /** - * @return {@link TopLevelFrame} of component - */ - public static TopLevelFrame getTopLevelFrame(java.awt.Component component) { - Container prevContainer; - Container parent = component instanceof Container ? (Container) component : component.getParent(); - do { - prevContainer = parent; - if (parent instanceof DetachedFrame) { - parent = ((DetachedFrame) parent).getParentContainer(); - } if (parent instanceof JPopupMenu) { - parent = ((JPopupMenu) parent).getInvoker().getParent(); - } else { - parent = parent.getParent(); - } - } while (parent != null); - - if (!(prevContainer instanceof TopLevelFrame)) { - if (prevContainer instanceof JComponent) { - Object tableForEditor = ((JComponent) prevContainer).getClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE); - if (tableForEditor != null) { - return getTopLevelFrame((Container) tableForEditor); - } - } - - return App.getInstance().getMainFrame(); - } - - return (TopLevelFrame) prevContainer; - } - - /** - * Returns {@link TopLevelFrame} of component. - * - * @param component - * @return {@link TopLevelFrame} of component - */ - public static TopLevelFrame getTopLevelFrame(DesktopAbstractComponent component) { - return getTopLevelFrame(component.getComposition()); - } - - /** - * Returns {@link TopLevelFrame} of frame. - * - * @param frame - * @return {@link TopLevelFrame} of component - */ - public static TopLevelFrame getTopLevelFrame(Frame frame) { - if (frame instanceof DesktopWindow) { - return ((DesktopWindow) frame).getWindowManager().getFrame(); - } else if (frame instanceof DesktopFrame) { - return getTopLevelFrame((frame).getFrame()); - } else if (frame instanceof AbstractFrame) { - Component.Wrapper wrapper = (Component.Wrapper) ((AbstractFrame) frame).getComposition(); - if (wrapper instanceof DesktopWindow) { - return ((DesktopWindow) wrapper).getWindowManager().getFrame(); - } else if (wrapper instanceof DesktopFrame) { - return getTopLevelFrame(((DesktopFrame) wrapper).getFrame()); - } else { - return getTopLevelFrame((Container) wrapper.getComposition()); - } - } else { - throw new IllegalArgumentException("Can not get top level frame for " + frame); - } - } - - /** - * Determines whether component will be displayed on the screen. - * - * @param component component - * @return true if the component and all of its ancestors are visible - */ - public static boolean isRecursivelyVisible(java.awt.Component component) { - if (component.getParent() instanceof JTabbedPane) { - JTabbedPane jTabbedPane = (JTabbedPane) component.getParent(); - - boolean tabVisible = false; - for (java.awt.Component childComponent : jTabbedPane.getComponents()) { - if (childComponent == component) { - tabVisible = true; - break; - } - } - - return tabVisible && isRecursivelyVisible(component.getParent()); - } - - if (component.getParent() instanceof CollapsiblePanel) { - return isRecursivelyVisible(component.getParent()); - } - - return component.isVisible() && (component.getParent() == null || isRecursivelyVisible(component.getParent())); - } - - /** - * Determines whether component will be displayed on the screen. - * - * @param component component - * @return true if the component and all of its ancestors are visible - */ - public static boolean isRecursivelyEnabled(java.awt.Component component) { - if (component.getParent() instanceof JTabbedPane) { - JTabbedPane jTabbedPane = (JTabbedPane) component.getParent(); - - boolean tabVisible = false; - for (java.awt.Component childComponent : jTabbedPane.getComponents()) { - if (childComponent == component) { - tabVisible = true; - break; - } - } - - return tabVisible && isRecursivelyEnabled(component.getParent()); - } - - return component.isEnabled() && (component.getParent() == null || isRecursivelyEnabled(component.getParent())) - && isRecursivelyVisible(component); - } - - /** - * Determines real size of HTML label with text on screen. - * - * @param html text with html markup - * @return size of label - */ - public static Dimension measureHtmlText(String html) { - JFrame testFrame = new JFrame(); - testFrame.setLayout(new BoxLayout(testFrame.getContentPane(), BoxLayout.PAGE_AXIS)); - JLabel testLabel = new JLabel(html); - testFrame.add(testLabel); - testFrame.pack(); - - Dimension size = testLabel.getSize(); - - testFrame.dispose(); - - return new Dimension(size); - } - - /** - * Flush changes in current focus owner if needed - */ - public static void flushCurrentInputField() { - java.awt.Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (focusOwner instanceof Flushable) { - ((Flushable) focusOwner).flushValue(); - } else if (focusOwner != null && focusOwner.getParent() instanceof Flushable) { - ((Flushable) focusOwner.getParent()).flushValue(); - } - } - - @Deprecated - public static void addEnterShortcut(com.haulmont.cuba.gui.components.TextField textField, final Runnable runnable) { - JTextField impl = (JTextField) DesktopComponentsHelper.unwrap(textField); - - impl.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); - impl.getActionMap().put("enter", new ValidationAwareAction() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - runnable.run(); - } - }); - } - - public static RootPaneContainer getSwingWindow(java.awt.Component component) { - java.awt.Component parent = component; - while (parent != null) { - if (parent instanceof RootPaneContainer) { - return (RootPaneContainer) parent; - } - - parent = parent.getParent(); - } - - return null; - } - - public static void focusProblemComponent(ValidationErrors errors) { - Component component = null; - if (!errors.getAll().isEmpty()) { - component = errors.getAll().iterator().next().component; - } - - if (component != null) { - try { - final JComponent jComponent = DesktopComponentsHelper.unwrap(component); - java.awt.Component c = jComponent; - java.awt.Component prevC = null; - while (c != null) { - if (c instanceof JTabbedPane && !((JTabbedPane) c).getSelectedComponent().equals(prevC)) { - final JTabbedPane tabbedPane = (JTabbedPane) c; - - // do not focus tabbed pane on programmaticaly selection change - JTabbedPaneExt.setFocusOnSelectionChange(false); - tabbedPane.setSelectedComponent(prevC); - break; - } - if (c instanceof CollapsiblePanel && !((CollapsiblePanel) c).isExpanded()) { - ((CollapsiblePanel) c).setExpanded(true); - break; - } - prevC = c; - c = c.getParent(); - } - - if (!JTabbedPaneExt.isFocusOnSelectionChange()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JTabbedPaneExt.setFocusOnSelectionChange(true); - } - }); - } - - if (jComponent instanceof FocusableComponent) { - ((FocusableComponent) jComponent).focus(); - } else { - // focus first up component - c = jComponent; - while (c != null) { - if (c.isFocusable()) { - c.requestFocus(); - break; - } - c = c.getParent(); - } - } - } catch (Exception e) { - LoggerFactory.getLogger(DesktopComponentsHelper.class).warn("Error while problem component focusing", e); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DetachedFrame; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; +import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; +import com.haulmont.cuba.desktop.sys.vcl.Flushable; +import com.haulmont.cuba.desktop.sys.vcl.FocusableComponent; +import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import org.slf4j.LoggerFactory; + +import javax.swing.Action; +import javax.swing.*; +import javax.swing.BoxLayout; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.util.Collections; + +public class DesktopComponentsHelper { + + public static final int BUTTON_HEIGHT = 30; + public static final int FIELD_HEIGHT = 28; + + // todo move nimbus constants to theme + public static final Color defaultBgColor = (Color) UIManager.get("nimbusLightBackground"); + public static final Color requiredBgColor = (Color) UIManager.get("cubaRequiredBackground"); + + /** + * Returns underlying Swing component implementation. + * + * @param component GUI component + * @return Swing component + * @see #getComposition(com.haulmont.cuba.gui.components.Component) + */ + public static JComponent unwrap(Component component) { + Object comp = component; + while (comp instanceof Component.Wrapper) { + comp = ((Component.Wrapper) comp).getComponent(); + } + return (JComponent) comp; + } + + /** + * Returns underlying Swing component, which serves as the outermost container for the supplied GUI component. + * For simple components like {@link com.haulmont.cuba.gui.components.Button} this method returns the same + * result as {@link #unwrap(com.haulmont.cuba.gui.components.Component)}. + * + * @param component GUI component + * @return Swing component + * @see #unwrap(com.haulmont.cuba.gui.components.Component) + */ + public static JComponent getComposition(Component component) { + Object comp = component; + while (comp instanceof Component.Wrapper) { + comp = ((Component.Wrapper) comp).getComposition(); + } + return (JComponent) comp; + } + + public static int convertMessageType(Frame.MessageMode messageType) { + switch (messageType) { + case CONFIRMATION: + case CONFIRMATION_HTML: + return JOptionPane.QUESTION_MESSAGE; + case WARNING: + case WARNING_HTML: + return JOptionPane.WARNING_MESSAGE; + default: + return JOptionPane.INFORMATION_MESSAGE; + } + } + + public static int convertNotificationType(com.haulmont.cuba.gui.components.Frame.NotificationType type) { + switch (type) { + case WARNING: + case WARNING_HTML: + return JOptionPane.WARNING_MESSAGE; + case ERROR: + case ERROR_HTML: + return JOptionPane.ERROR_MESSAGE; + case HUMANIZED: + case HUMANIZED_HTML: + return JOptionPane.INFORMATION_MESSAGE; + case TRAY: + case TRAY_HTML: + return JOptionPane.WARNING_MESSAGE; + default: + return JOptionPane.PLAIN_MESSAGE; + } + } + + public static void adjustSize(JButton button) { + button.setPreferredSize(new Dimension(0, BUTTON_HEIGHT)); + button.setMaximumSize(new Dimension(Integer.MAX_VALUE, BUTTON_HEIGHT)); + } + + public static void adjustSize(JComboBox comboBox) { + comboBox.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); + } + + public static void adjustSize(JTextField textField) { + textField.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); + } + + public static void adjustDateFieldSize(JPanel dateFieldComposition) { + dateFieldComposition.setPreferredSize(new Dimension(0, FIELD_HEIGHT)); + } + + /** + * Convert {@link KeyCombination} to {@link KeyStroke}. + * + * @param combination Key combination to convert + * @return KeyStroke + */ + public static KeyStroke convertKeyCombination(KeyCombination combination) { + KeyCombination.Modifier[] modifiers = combination.getModifiers(); + int modifiersMask = 0; + if (modifiers != null && modifiers.length > 0) { + for (KeyCombination.Modifier modifier : modifiers) { + modifiersMask = modifiersMask | convertModifier(modifier); + } + } + return KeyStroke.getKeyStroke(combination.getKey().getVirtualKey(), modifiersMask, false); + } + + /** + * Convert {@link KeyCombination.Modifier} to {@link InputEvent} modifier constraint. + * + * @param modifier modifier to convert + * @return {@link InputEvent} modifier constraint + */ + public static int convertModifier(KeyCombination.Modifier modifier) { + switch (modifier) { + case CTRL: + return InputEvent.CTRL_DOWN_MASK; + case ALT: + return InputEvent.ALT_DOWN_MASK; + case SHIFT: + return InputEvent.SHIFT_DOWN_MASK; + default: + throw new IllegalArgumentException("Modifier " + modifier.name() + " not recognized"); + } + } + + /** + * Make JTable handle TAB key as all other components - move focus to next/previous components. + *

Default Swing behaviour for table is to move focus to next/previous cell inside the table.

+ * @param table table instance + */ + public static void correctTableFocusTraversal(JTable table) { + table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, + Collections.singleton(AWTKeyStroke.getAWTKeyStroke("TAB"))); + table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, + Collections.singleton(AWTKeyStroke.getAWTKeyStroke("shift TAB"))); + } + + /** + * Add shortcut action to any JComponent. + * + * @param name name of action that used as action key in {@link InputMap} and {@link ActionMap}. + * @param component + * @param key + * @param action + */ + public static void addShortcutAction(String name, JComponent component, KeyStroke key, Action action) { + ActionMap actionMap = component.getActionMap(); + InputMap inputMap = component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(key, name); + actionMap.put(name, action); + } + + public static void decorateMissingValue(JComponent jComponent, boolean missingValueState) { + jComponent.setBackground(missingValueState ? requiredBgColor : defaultBgColor); + } + + /** + * @return {@link TopLevelFrame} of container + */ + public static TopLevelFrame getTopLevelFrame(Container container) { + Container prevContainer; + Container parent = container; + do { + prevContainer = parent; + if (parent instanceof DetachedFrame) { + parent = ((DetachedFrame) parent).getParentContainer(); + } if (parent instanceof JPopupMenu) { + parent = ((JPopupMenu) parent).getInvoker().getParent(); + } else { + parent = parent.getParent(); + } + } while (parent != null); + + if (!(prevContainer instanceof TopLevelFrame)) { + if (prevContainer instanceof JComponent) { + Object tableForEditor = ((JComponent) prevContainer).getClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE); + if (tableForEditor != null) { + return getTopLevelFrame((java.awt.Component) tableForEditor); + } + } + + return App.getInstance().getMainFrame(); + } + + return (TopLevelFrame) prevContainer; + } + + /** + * @return {@link TopLevelFrame} of component + */ + public static TopLevelFrame getTopLevelFrame(java.awt.Component component) { + Container prevContainer; + Container parent = component instanceof Container ? (Container) component : component.getParent(); + do { + prevContainer = parent; + if (parent instanceof DetachedFrame) { + parent = ((DetachedFrame) parent).getParentContainer(); + } if (parent instanceof JPopupMenu) { + parent = ((JPopupMenu) parent).getInvoker().getParent(); + } else { + parent = parent.getParent(); + } + } while (parent != null); + + if (!(prevContainer instanceof TopLevelFrame)) { + if (prevContainer instanceof JComponent) { + Object tableForEditor = ((JComponent) prevContainer).getClientProperty(DesktopTableCellEditor.CELL_EDITOR_TABLE); + if (tableForEditor != null) { + return getTopLevelFrame((Container) tableForEditor); + } + } + + return App.getInstance().getMainFrame(); + } + + return (TopLevelFrame) prevContainer; + } + + /** + * Returns {@link TopLevelFrame} of component. + * + * @param component + * @return {@link TopLevelFrame} of component + */ + public static TopLevelFrame getTopLevelFrame(DesktopAbstractComponent component) { + return getTopLevelFrame(component.getComposition()); + } + + /** + * Returns {@link TopLevelFrame} of frame. + * + * @param frame + * @return {@link TopLevelFrame} of component + */ + public static TopLevelFrame getTopLevelFrame(Frame frame) { + if (frame instanceof DesktopWindow) { + return ((DesktopWindow) frame).getWindowManager().getFrame(); + } else if (frame instanceof DesktopFrame) { + return getTopLevelFrame((frame).getFrame()); + } else if (frame instanceof AbstractFrame) { + Component.Wrapper wrapper = (Component.Wrapper) ((AbstractFrame) frame).getComposition(); + if (wrapper instanceof DesktopWindow) { + return ((DesktopWindow) wrapper).getWindowManager().getFrame(); + } else if (wrapper instanceof DesktopFrame) { + return getTopLevelFrame(((DesktopFrame) wrapper).getFrame()); + } else { + return getTopLevelFrame((Container) wrapper.getComposition()); + } + } else { + throw new IllegalArgumentException("Can not get top level frame for " + frame); + } + } + + /** + * Determines whether component will be displayed on the screen. + * + * @param component component + * @return true if the component and all of its ancestors are visible + */ + public static boolean isRecursivelyVisible(java.awt.Component component) { + if (component.getParent() instanceof JTabbedPane) { + JTabbedPane jTabbedPane = (JTabbedPane) component.getParent(); + + boolean tabVisible = false; + for (java.awt.Component childComponent : jTabbedPane.getComponents()) { + if (childComponent == component) { + tabVisible = true; + break; + } + } + + return tabVisible && isRecursivelyVisible(component.getParent()); + } + + if (component.getParent() instanceof CollapsiblePanel) { + return isRecursivelyVisible(component.getParent()); + } + + return component.isVisible() && (component.getParent() == null || isRecursivelyVisible(component.getParent())); + } + + /** + * Determines whether component will be displayed on the screen. + * + * @param component component + * @return true if the component and all of its ancestors are visible + */ + public static boolean isRecursivelyEnabled(java.awt.Component component) { + if (component.getParent() instanceof JTabbedPane) { + JTabbedPane jTabbedPane = (JTabbedPane) component.getParent(); + + boolean tabVisible = false; + for (java.awt.Component childComponent : jTabbedPane.getComponents()) { + if (childComponent == component) { + tabVisible = true; + break; + } + } + + return tabVisible && isRecursivelyEnabled(component.getParent()); + } + + return component.isEnabled() && (component.getParent() == null || isRecursivelyEnabled(component.getParent())) + && isRecursivelyVisible(component); + } + + /** + * Determines real size of HTML label with text on screen. + * + * @param html text with html markup + * @return size of label + */ + public static Dimension measureHtmlText(String html) { + JFrame testFrame = new JFrame(); + testFrame.setLayout(new BoxLayout(testFrame.getContentPane(), BoxLayout.PAGE_AXIS)); + JLabel testLabel = new JLabel(html); + testFrame.add(testLabel); + testFrame.pack(); + + Dimension size = testLabel.getSize(); + + testFrame.dispose(); + + return new Dimension(size); + } + + /** + * Flush changes in current focus owner if needed + */ + public static void flushCurrentInputField() { + java.awt.Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if (focusOwner instanceof Flushable) { + ((Flushable) focusOwner).flushValue(); + } else if (focusOwner != null && focusOwner.getParent() instanceof Flushable) { + ((Flushable) focusOwner.getParent()).flushValue(); + } + } + + @Deprecated + public static void addEnterShortcut(com.haulmont.cuba.gui.components.TextField textField, final Runnable runnable) { + JTextField impl = (JTextField) DesktopComponentsHelper.unwrap(textField); + + impl.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); + impl.getActionMap().put("enter", new ValidationAwareAction() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + runnable.run(); + } + }); + } + + public static RootPaneContainer getSwingWindow(java.awt.Component component) { + java.awt.Component parent = component; + while (parent != null) { + if (parent instanceof RootPaneContainer) { + return (RootPaneContainer) parent; + } + + parent = parent.getParent(); + } + + return null; + } + + public static void focusProblemComponent(ValidationErrors errors) { + Component component = null; + if (!errors.getAll().isEmpty()) { + component = errors.getAll().iterator().next().component; + } + + if (component != null) { + try { + final JComponent jComponent = DesktopComponentsHelper.unwrap(component); + java.awt.Component c = jComponent; + java.awt.Component prevC = null; + while (c != null) { + if (c instanceof JTabbedPane && !((JTabbedPane) c).getSelectedComponent().equals(prevC)) { + final JTabbedPane tabbedPane = (JTabbedPane) c; + + // do not focus tabbed pane on programmaticaly selection change + JTabbedPaneExt.setFocusOnSelectionChange(false); + tabbedPane.setSelectedComponent(prevC); + break; + } + if (c instanceof CollapsiblePanel && !((CollapsiblePanel) c).isExpanded()) { + ((CollapsiblePanel) c).setExpanded(true); + break; + } + prevC = c; + c = c.getParent(); + } + + if (!JTabbedPaneExt.isFocusOnSelectionChange()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JTabbedPaneExt.setFocusOnSelectionChange(true); + } + }); + } + + if (jComponent instanceof FocusableComponent) { + ((FocusableComponent) jComponent).focus(); + } else { + // focus first up component + c = jComponent; + while (c != null) { + if (c.isFocusable()) { + c.requestFocus(); + break; + } + c = c.getParent(); + } + } + } catch (Exception e) { + LoggerFactory.getLogger(DesktopComponentsHelper.class).warn("Error while problem component focusing", e); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopContainer.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopContainer.java index 87983c2f25..0ba0b051a9 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopContainer.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopContainer.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.Component; - -public interface DesktopContainer extends Component.Container { - - /* - * Updates child component after size or alignment change. - * Called by child component. - * General implementation is to call layout to update / reset component's constraints. - */ - void updateComponent(Component child); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.Component; + +public interface DesktopContainer extends Component.Container { + + /* + * Updates child component after size or alignment change. + * Called by child component. + * General implementation is to call layout to update / reset component's constraints. + */ + void updateComponent(Component child); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopDateField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopDateField.java index 892dd4d75c..48bdd92c9a 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopDateField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopDateField.java @@ -1,714 +1,714 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.annotation.IgnoreUserTimeZone; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.MigBoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.vcl.DatePicker.DatePicker; -import com.haulmont.cuba.desktop.sys.vcl.Flushable; -import com.haulmont.cuba.desktop.sys.vcl.FocusableComponent; -import com.haulmont.cuba.gui.components.DateField; -import com.haulmont.cuba.gui.components.Frame.NotificationType; -import com.haulmont.cuba.gui.components.RequiredValueMissingException; -import com.haulmont.cuba.gui.components.ValidationException; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.jdesktop.swingx.JXDatePicker; - -import javax.persistence.TemporalType; -import javax.swing.*; -import javax.validation.constraints.Future; -import javax.validation.constraints.Past; -import java.awt.*; -import java.text.ParseException; -import java.util.*; -import java.util.List; - -public class DesktopDateField extends DesktopAbstractField implements DateField { - protected Messages messages; - protected Resolution resolution; - protected Datasource datasource; - protected String dateTimeFormat; - protected String dateFormat; - protected String timeFormat; - - protected boolean updatingInstance; - - protected JXDatePicker datePicker; - protected DesktopTimeField timeField; - protected boolean valid = true; - - protected Object prevValue = null; - - protected TimeZone timeZone; - protected UserSession userSession; - protected TimeZones timeZones = AppBeans.get(TimeZones.NAME); - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - protected Date startDate; - protected Date endDate; - - protected boolean updateTimeFieldResolution = false; - - public DesktopDateField() { - impl = new FocusableComposition(); - - messages = AppBeans.get(Messages.NAME); - initComponentParts(); - setResolution(Resolution.MIN); - - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - userSession = sessionSource.getUserSession(); - Locale locale = userSession.getLocale(); - setDateFormat(Datatypes.getFormatStringsNN(locale).getDateTimeFormat()); - DesktopComponentsHelper.adjustDateFieldSize(impl); - } - - protected void initComponentParts() { - BoxLayoutAdapter adapter = new MigBoxLayoutAdapter(impl); - adapter.setSpacing(false); - adapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); - adapter.setExpandLayout(true); - impl.setLayout(adapter.getLayout()); - - datePicker = new FlushableDatePicker(); - - Dimension size = getDefaultDimension(); - datePicker.setPreferredSize(size); - datePicker.setMinimumSize(size); - - timeField = new DesktopTimeField(); - timeField.addValueChangeListener(e -> { - if (!checkRange(constructDate())) { - return; - } - - if (!updateTimeFieldResolution) { - updateInstance(); - } - }); - - datePicker.addPropertyChangeListener(evt -> { - if ("date".equals(evt.getPropertyName())) { - if (!checkRange(constructDate())) { - return; - } - - updateInstance(); - updateMissingValueState(); - } - }); - } - - protected void updateLayout() { - impl.removeAll(); - impl.add(datePicker, "growx, w 100%"); - if (resolution.ordinal() < Resolution.DAY.ordinal()) { - impl.add(timeField.getImpl()); - } - } - - @Override - public void setId(String id) { - super.setId(id); - - if (id != null && App.getInstance().isTestMode()) { - timeField.setId("timepart"); - datePicker.setName("datepart"); - } - } - - @Override - public Resolution getResolution() { - return resolution; - } - - @Override - public void setResolution(Resolution resolution) { - _setResolution(resolution); - updateLayout(); - } - - protected void _setResolution(Resolution resolution) { - this.resolution = resolution; - if (resolution.ordinal() < Resolution.DAY.ordinal()) { - timeField.setResolution(resolution); - // while changing resolution, timeField loses its value, so we need to set it again - updateTimeFieldResolution = true; - timeField.setValue(datePicker.getDate()); - updateTimeFieldResolution = false; - } - } - - @Override - public String getDateFormat() { - return dateTimeFormat; - } - - @Override - public void setDateFormat(String dateFormat) { - dateTimeFormat = dateFormat; - StringBuilder date = new StringBuilder(dateFormat); - StringBuilder time = new StringBuilder(dateFormat); - int timeStartPos = findTimeStartPos(dateFormat); - if (timeStartPos >= 0) { - time.delete(0, timeStartPos); - timeFormat = StringUtils.trimToEmpty(time.toString()); - timeField.setFormat(timeFormat); - _setResolution(resolution); - date.delete(timeStartPos, dateFormat.length()); - } else if (resolution.ordinal() < Resolution.DAY.ordinal()) { - _setResolution(Resolution.DAY); - } - - this.dateFormat = StringUtils.trimToEmpty(date.toString()); - datePicker.setFormats(this.dateFormat); - - updateLayout(); - } - - protected int findTimeStartPos(String dateTimeFormat) { - List positions = new ArrayList<>(); - - char[] signs = new char[]{'H', 'h', 'm', 's'}; - for (char sign : signs) { - int pos = dateTimeFormat.indexOf(sign); - if (pos > -1) { - positions.add(pos); - } - } - return positions.isEmpty() ? -1 : Collections.min(positions); - } - - @Override - public TimeZone getTimeZone() { - return timeZone; - } - - @Override - public void setTimeZone(TimeZone timeZone) { - TimeZone prevTimeZone = this.timeZone; - Date value = getValue(); - this.timeZone = timeZone; - if (value != null && !ObjectUtils.equals(prevTimeZone, timeZone)) { - Date newValue = timeZones.convert(value, - TimeZone.getDefault(), timeZone != null ? timeZone : TimeZone.getDefault()); - updateComponent(newValue); - } - } - - @Override - public void setRangeStart(Date value) { - startDate = toUserDate(value); - } - - @Override - public Date getRangeStart() { - return toServerDate(startDate); - } - - @Override - public void setRangeEnd(Date value) { - endDate = toUserDate(value); - } - - @Override - public Date getRangeEnd() { - return toServerDate(endDate); - } - - protected boolean checkRange(Date value) { - if (updatingInstance) { - return true; - } - - if (value != null) { - Date rangeStart = getRangeStart(); - if (rangeStart != null && value.before(rangeStart)) { - handleDateOutOfRange(value); - return false; - } - - Date rangeEnd = getRangeEnd(); - if (rangeEnd != null && value.after(rangeEnd)) { - handleDateOutOfRange(value); - return false; - } - } - - return true; - } - - protected void handleDateOutOfRange(Date value) { - if (getFrame() != null) { - getFrame().showNotification(messages.getMainMessage("dateField.dateOutOfRangeMessage"), - NotificationType.TRAY); - } - - updatingInstance = true; - try { - datePicker.setDate((Date) prevValue); - timeField.setValue((Date) prevValue); - } finally { - updatingInstance = false; - } - } - - @Override - public void requestFocus() { - SwingUtilities.invokeLater(() -> { - datePicker.requestFocus(); - }); - } - - @SuppressWarnings("unchecked") - @Override - public Date getValue() { - try { - return constructDate(); - } catch (Exception e) { - return null; - } - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (!ObjectUtils.equals(prevValue, value)) { - Date targetDate = (Date) value; - - updateInstance(targetDate); - updateComponent(toUserDate((Date) value)); - fireChangeListeners(value); - } - } - - protected Date toUserDate(Date date) { - return timeZone == null ? date : timeZones.convert(date, TimeZone.getDefault(), timeZone); - } - - protected Date toServerDate(Date date) { - return timeZone == null ? date : timeZones.convert(date, timeZone, TimeZone.getDefault()); - } - - @Override - public void validate() throws ValidationException { - if (!isVisible() || !isEditableWithParent() || !isEnabled()) - return; - - try { - constructDate(); - super.validate(); - } catch (RequiredValueMissingException e) { - throw e; - } catch (Exception e) { - throw new ValidationException(e); - } - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - @Override - public void setDatasource(Datasource datasource, String property) { - this.datasource = datasource; - - if (datasource == null) { - setValue(null); - return; - } - - resolveMetaPropertyPath(datasource.getMetaClass(), property); - if (metaProperty.getRange().isDatatype() - && metaProperty.getRange().asDatatype().getJavaClass().equals(Date.class) - && timeZone == null) { - Object ignoreUserTimeZone = metaProperty.getAnnotations().get(IgnoreUserTimeZone.class.getName()); - if (!Boolean.TRUE.equals(ignoreUserTimeZone)) { - timeZone = userSession.getTimeZone(); - } - } - - itemChangeListener = e -> { - if (updatingInstance) { - return; - } - Date value = getEntityValue(e.getItem()); - updateComponent(toUserDate(value)); - fireChangeListeners(value); - }; - //noinspection unchecked - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) { - return; - } - if (e.getProperty().equals(metaPropertyPath.toString())) { - updateComponent(toUserDate((Date) e.getValue())); - fireChangeListeners(e.getValue()); - } - }; - //noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - if (datasource.getState() == Datasource.State.VALID && datasource.getItem() != null) { - if (property.equals(metaPropertyPath.toString())) { - Date value = getEntityValue(datasource.getItem()); - updateComponent(toUserDate(value)); - fireChangeListeners(value); - } - } - - initRequired(metaPropertyPath); - initDateFormat(metaProperty); - - if (metaProperty.isReadOnly()) { - setEditable(false); - } - - initBeanValidator(); - setDateRangeByProperty(metaProperty); - } - - protected void initDateFormat(MetaProperty metaProperty) { - TemporalType tt = null; - if (metaProperty.getRange().asDatatype().getJavaClass().equals(java.sql.Date.class)) { - tt = TemporalType.DATE; - } else if (metaProperty.getAnnotations() != null) { - tt = (TemporalType) metaProperty.getAnnotations().get(MetadataTools.TEMPORAL_ANN_NAME); - } - - setResolution(tt == TemporalType.DATE - ? DateField.Resolution.DAY - : Resolution.MIN); - - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - String formatStr = messageTools.getDefaultDateFormat(tt); - setDateFormat(formatStr); - } - - protected void setDateRangeByProperty(MetaProperty metaProperty) { - if (metaProperty.getAnnotations().get(Past.class.getName()) != null) { - TimeSource timeSource = AppBeans.get(TimeSource.NAME); - Date currentTimestamp = timeSource.currentTimestamp(); - - Calendar calendar = Calendar.getInstance(userSession.getLocale()); - calendar.setTime(currentTimestamp); - calendar.set(Calendar.HOUR_OF_DAY, 23); - calendar.set(Calendar.MINUTE, 59); - calendar.set(Calendar.SECOND, 59); - calendar.set(Calendar.MILLISECOND, 999); - - setRangeEnd(calendar.getTime()); - } else if (metaProperty.getAnnotations().get(Future.class.getName()) != null) { - TimeSource timeSource = AppBeans.get(TimeSource.NAME); - Date currentTimestamp = timeSource.currentTimestamp(); - - Calendar calendar = Calendar.getInstance(userSession.getLocale()); - calendar.setTime(currentTimestamp); - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - if (metaProperty.getRange().asDatatype().getJavaClass().equals(java.sql.Date.class)) { - calendar.add(Calendar.DATE, 1); - } - - setRangeStart(calendar.getTime()); - } - } - - protected Date getEntityValue(Entity item) { - return InstanceUtils.getValueEx(item, metaPropertyPath.getPath()); - } - - protected void updateComponent(Date value) { - updatingInstance = true; - try { - setDateParts(value); - valid = true; - } finally { - updatingInstance = false; - } - updateMissingValueState(); - } - - protected void fireChangeListeners(Object newValue) { - if (!ObjectUtils.equals(prevValue, newValue)) { - Object oldValue = prevValue; - - prevValue = newValue; - - fireValueChanged(oldValue, newValue); - } - } - - protected void setDateParts(Date value) { - datePicker.setDate(value); - timeField.setValueInternal(value); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - datePicker.setEnabled(isEnabledWithParent()); - timeField.setEnabled(isEnabledWithParent()); - } - - @Override - protected void setEditableToComponent(boolean editable) { - datePicker.setEditable(editable); - timeField.setEditable(editable); - updateMissingValueState(); - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - requestContainerUpdate(); - } - - @Override - public String getDescription() { - return datePicker.getToolTipText(); - } - - @Override - public void setDescription(String description) { - if (!ObjectUtils.equals(this.getDescription(), description)) { - datePicker.getEditor().setToolTipText(description); - timeField.setDescription(description); - DesktopToolTipManager.getInstance().registerTooltip(datePicker.getEditor()); - - requestContainerUpdate(); - } - } - - protected void updateInstance() { - if (updatingInstance) { - return; - } - - updatingInstance = true; - try { - if (datasource != null && metaPropertyPath != null) { - Date value = constructDate(); - if (ObjectUtils.equals(prevValue, value)) { - valid = true; - return; - } - setValueToDs(value); - } - valid = true; - } catch (RuntimeException e) { - valid = false; - } finally { - updatingInstance = false; - } - if (valid) { - Object newValue = getValue(); - fireChangeListeners(newValue); - } - } - - protected void updateInstance(Date value) { - if (updatingInstance) { - return; - } - - updatingInstance = true; - try { - if (datasource != null && metaPropertyPath != null) { - setValueToDs(value); - } - valid = true; - } catch (RuntimeException e) { - valid = false; - } finally { - updatingInstance = false; - } - } - - protected void setValueToDs(Date value) { - if (datasource.getItem() != null) { - Object obj = value; - Datatype datatype = metaProperty.getRange().asDatatype(); - if (!datatype.getJavaClass().equals(Date.class)) { - String str = Datatypes.getNN(Date.class).format(value); - try { - obj = datatype.parse(str); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } - InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), obj); - } - } - - protected Date constructDate() { - final Date datePickerDate = datePicker.getDate(); - if (datePickerDate == null) { - return null; - } - - Calendar c = Calendar.getInstance(userSession.getLocale()); - c.setTime(datePickerDate); - if (timeField.getValue() == null) { - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - } else { - Calendar c2 = Calendar.getInstance(userSession.getLocale()); - c2.setTime(timeField.getValue()); - - c.set(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY)); - c.set(Calendar.MINUTE, c2.get(Calendar.MINUTE)); - c.set(Calendar.SECOND, c2.get(Calendar.SECOND)); - } - - //noinspection UnnecessaryLocalVariable - Date serverDate = toServerDate(c.getTime()); - return serverDate; - } - - protected boolean isHourUsed() { - return resolution != null && resolution.ordinal() <= Resolution.HOUR.ordinal(); - } - - protected boolean isMinUsed() { - return resolution != null && resolution.ordinal() <= Resolution.MIN.ordinal(); - } - - public JXDatePicker getDatePicker() { - return datePicker; - } - - public DesktopTimeField getTimeField() { - return timeField; - } - - @Override - public void updateMissingValueState() { - boolean value = required && isEditableWithParent() && datePicker.getEditor().getValue() == null; - decorateMissingValue(datePicker.getEditor(), value); - if (isHourUsed()) { - decorateMissingValue(timeField.getImpl(), value); - timeField.getImpl().repaint(); - } - } - - protected void flush() { - if (isEditable() && isEnabled()) { - try { - datePicker.getEditor().commitEdit(); - } catch (ParseException e) { - return; - } - - updateInstance(); - updateMissingValueState(); - } - } - - protected Dimension getDefaultDimension() { - UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); - if (lafDefaults.getDimension("DateField.dimension") != null) { // take it from desktop theme - return lafDefaults.getDimension("DateField.dimension"); - } - return new Dimension(110, DesktopComponentsHelper.FIELD_HEIGHT); - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } - - public class FocusableComposition extends JPanel implements FocusableComponent, Flushable { - - @Override - public void focus() { - DesktopDateField.this.datePicker.requestFocus(); - } - - @Override - public void flushValue() { - flush(); - } - } - - public class FlushableDatePicker extends DatePicker implements Flushable { - - @Override - public void flushValue() { - flush(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.annotation.IgnoreUserTimeZone; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.MigBoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.vcl.DatePicker.DatePicker; +import com.haulmont.cuba.desktop.sys.vcl.Flushable; +import com.haulmont.cuba.desktop.sys.vcl.FocusableComponent; +import com.haulmont.cuba.gui.components.DateField; +import com.haulmont.cuba.gui.components.Frame.NotificationType; +import com.haulmont.cuba.gui.components.RequiredValueMissingException; +import com.haulmont.cuba.gui.components.ValidationException; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.jdesktop.swingx.JXDatePicker; + +import javax.persistence.TemporalType; +import javax.swing.*; +import javax.validation.constraints.Future; +import javax.validation.constraints.Past; +import java.awt.*; +import java.text.ParseException; +import java.util.*; +import java.util.List; + +public class DesktopDateField extends DesktopAbstractField implements DateField { + protected Messages messages; + protected Resolution resolution; + protected Datasource datasource; + protected String dateTimeFormat; + protected String dateFormat; + protected String timeFormat; + + protected boolean updatingInstance; + + protected JXDatePicker datePicker; + protected DesktopTimeField timeField; + protected boolean valid = true; + + protected Object prevValue = null; + + protected TimeZone timeZone; + protected UserSession userSession; + protected TimeZones timeZones = AppBeans.get(TimeZones.NAME); + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + protected Date startDate; + protected Date endDate; + + protected boolean updateTimeFieldResolution = false; + + public DesktopDateField() { + impl = new FocusableComposition(); + + messages = AppBeans.get(Messages.NAME); + initComponentParts(); + setResolution(Resolution.MIN); + + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + userSession = sessionSource.getUserSession(); + Locale locale = userSession.getLocale(); + setDateFormat(Datatypes.getFormatStringsNN(locale).getDateTimeFormat()); + DesktopComponentsHelper.adjustDateFieldSize(impl); + } + + protected void initComponentParts() { + BoxLayoutAdapter adapter = new MigBoxLayoutAdapter(impl); + adapter.setSpacing(false); + adapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); + adapter.setExpandLayout(true); + impl.setLayout(adapter.getLayout()); + + datePicker = new FlushableDatePicker(); + + Dimension size = getDefaultDimension(); + datePicker.setPreferredSize(size); + datePicker.setMinimumSize(size); + + timeField = new DesktopTimeField(); + timeField.addValueChangeListener(e -> { + if (!checkRange(constructDate())) { + return; + } + + if (!updateTimeFieldResolution) { + updateInstance(); + } + }); + + datePicker.addPropertyChangeListener(evt -> { + if ("date".equals(evt.getPropertyName())) { + if (!checkRange(constructDate())) { + return; + } + + updateInstance(); + updateMissingValueState(); + } + }); + } + + protected void updateLayout() { + impl.removeAll(); + impl.add(datePicker, "growx, w 100%"); + if (resolution.ordinal() < Resolution.DAY.ordinal()) { + impl.add(timeField.getImpl()); + } + } + + @Override + public void setId(String id) { + super.setId(id); + + if (id != null && App.getInstance().isTestMode()) { + timeField.setId("timepart"); + datePicker.setName("datepart"); + } + } + + @Override + public Resolution getResolution() { + return resolution; + } + + @Override + public void setResolution(Resolution resolution) { + _setResolution(resolution); + updateLayout(); + } + + protected void _setResolution(Resolution resolution) { + this.resolution = resolution; + if (resolution.ordinal() < Resolution.DAY.ordinal()) { + timeField.setResolution(resolution); + // while changing resolution, timeField loses its value, so we need to set it again + updateTimeFieldResolution = true; + timeField.setValue(datePicker.getDate()); + updateTimeFieldResolution = false; + } + } + + @Override + public String getDateFormat() { + return dateTimeFormat; + } + + @Override + public void setDateFormat(String dateFormat) { + dateTimeFormat = dateFormat; + StringBuilder date = new StringBuilder(dateFormat); + StringBuilder time = new StringBuilder(dateFormat); + int timeStartPos = findTimeStartPos(dateFormat); + if (timeStartPos >= 0) { + time.delete(0, timeStartPos); + timeFormat = StringUtils.trimToEmpty(time.toString()); + timeField.setFormat(timeFormat); + _setResolution(resolution); + date.delete(timeStartPos, dateFormat.length()); + } else if (resolution.ordinal() < Resolution.DAY.ordinal()) { + _setResolution(Resolution.DAY); + } + + this.dateFormat = StringUtils.trimToEmpty(date.toString()); + datePicker.setFormats(this.dateFormat); + + updateLayout(); + } + + protected int findTimeStartPos(String dateTimeFormat) { + List positions = new ArrayList<>(); + + char[] signs = new char[]{'H', 'h', 'm', 's'}; + for (char sign : signs) { + int pos = dateTimeFormat.indexOf(sign); + if (pos > -1) { + positions.add(pos); + } + } + return positions.isEmpty() ? -1 : Collections.min(positions); + } + + @Override + public TimeZone getTimeZone() { + return timeZone; + } + + @Override + public void setTimeZone(TimeZone timeZone) { + TimeZone prevTimeZone = this.timeZone; + Date value = getValue(); + this.timeZone = timeZone; + if (value != null && !ObjectUtils.equals(prevTimeZone, timeZone)) { + Date newValue = timeZones.convert(value, + TimeZone.getDefault(), timeZone != null ? timeZone : TimeZone.getDefault()); + updateComponent(newValue); + } + } + + @Override + public void setRangeStart(Date value) { + startDate = toUserDate(value); + } + + @Override + public Date getRangeStart() { + return toServerDate(startDate); + } + + @Override + public void setRangeEnd(Date value) { + endDate = toUserDate(value); + } + + @Override + public Date getRangeEnd() { + return toServerDate(endDate); + } + + protected boolean checkRange(Date value) { + if (updatingInstance) { + return true; + } + + if (value != null) { + Date rangeStart = getRangeStart(); + if (rangeStart != null && value.before(rangeStart)) { + handleDateOutOfRange(value); + return false; + } + + Date rangeEnd = getRangeEnd(); + if (rangeEnd != null && value.after(rangeEnd)) { + handleDateOutOfRange(value); + return false; + } + } + + return true; + } + + protected void handleDateOutOfRange(Date value) { + if (getFrame() != null) { + getFrame().showNotification(messages.getMainMessage("dateField.dateOutOfRangeMessage"), + NotificationType.TRAY); + } + + updatingInstance = true; + try { + datePicker.setDate((Date) prevValue); + timeField.setValue((Date) prevValue); + } finally { + updatingInstance = false; + } + } + + @Override + public void requestFocus() { + SwingUtilities.invokeLater(() -> { + datePicker.requestFocus(); + }); + } + + @SuppressWarnings("unchecked") + @Override + public Date getValue() { + try { + return constructDate(); + } catch (Exception e) { + return null; + } + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (!ObjectUtils.equals(prevValue, value)) { + Date targetDate = (Date) value; + + updateInstance(targetDate); + updateComponent(toUserDate((Date) value)); + fireChangeListeners(value); + } + } + + protected Date toUserDate(Date date) { + return timeZone == null ? date : timeZones.convert(date, TimeZone.getDefault(), timeZone); + } + + protected Date toServerDate(Date date) { + return timeZone == null ? date : timeZones.convert(date, timeZone, TimeZone.getDefault()); + } + + @Override + public void validate() throws ValidationException { + if (!isVisible() || !isEditableWithParent() || !isEnabled()) + return; + + try { + constructDate(); + super.validate(); + } catch (RequiredValueMissingException e) { + throw e; + } catch (Exception e) { + throw new ValidationException(e); + } + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + @Override + public void setDatasource(Datasource datasource, String property) { + this.datasource = datasource; + + if (datasource == null) { + setValue(null); + return; + } + + resolveMetaPropertyPath(datasource.getMetaClass(), property); + if (metaProperty.getRange().isDatatype() + && metaProperty.getRange().asDatatype().getJavaClass().equals(Date.class) + && timeZone == null) { + Object ignoreUserTimeZone = metaProperty.getAnnotations().get(IgnoreUserTimeZone.class.getName()); + if (!Boolean.TRUE.equals(ignoreUserTimeZone)) { + timeZone = userSession.getTimeZone(); + } + } + + itemChangeListener = e -> { + if (updatingInstance) { + return; + } + Date value = getEntityValue(e.getItem()); + updateComponent(toUserDate(value)); + fireChangeListeners(value); + }; + //noinspection unchecked + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) { + return; + } + if (e.getProperty().equals(metaPropertyPath.toString())) { + updateComponent(toUserDate((Date) e.getValue())); + fireChangeListeners(e.getValue()); + } + }; + //noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + if (datasource.getState() == Datasource.State.VALID && datasource.getItem() != null) { + if (property.equals(metaPropertyPath.toString())) { + Date value = getEntityValue(datasource.getItem()); + updateComponent(toUserDate(value)); + fireChangeListeners(value); + } + } + + initRequired(metaPropertyPath); + initDateFormat(metaProperty); + + if (metaProperty.isReadOnly()) { + setEditable(false); + } + + initBeanValidator(); + setDateRangeByProperty(metaProperty); + } + + protected void initDateFormat(MetaProperty metaProperty) { + TemporalType tt = null; + if (metaProperty.getRange().asDatatype().getJavaClass().equals(java.sql.Date.class)) { + tt = TemporalType.DATE; + } else if (metaProperty.getAnnotations() != null) { + tt = (TemporalType) metaProperty.getAnnotations().get(MetadataTools.TEMPORAL_ANN_NAME); + } + + setResolution(tt == TemporalType.DATE + ? DateField.Resolution.DAY + : Resolution.MIN); + + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + String formatStr = messageTools.getDefaultDateFormat(tt); + setDateFormat(formatStr); + } + + protected void setDateRangeByProperty(MetaProperty metaProperty) { + if (metaProperty.getAnnotations().get(Past.class.getName()) != null) { + TimeSource timeSource = AppBeans.get(TimeSource.NAME); + Date currentTimestamp = timeSource.currentTimestamp(); + + Calendar calendar = Calendar.getInstance(userSession.getLocale()); + calendar.setTime(currentTimestamp); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + + setRangeEnd(calendar.getTime()); + } else if (metaProperty.getAnnotations().get(Future.class.getName()) != null) { + TimeSource timeSource = AppBeans.get(TimeSource.NAME); + Date currentTimestamp = timeSource.currentTimestamp(); + + Calendar calendar = Calendar.getInstance(userSession.getLocale()); + calendar.setTime(currentTimestamp); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + if (metaProperty.getRange().asDatatype().getJavaClass().equals(java.sql.Date.class)) { + calendar.add(Calendar.DATE, 1); + } + + setRangeStart(calendar.getTime()); + } + } + + protected Date getEntityValue(Entity item) { + return InstanceUtils.getValueEx(item, metaPropertyPath.getPath()); + } + + protected void updateComponent(Date value) { + updatingInstance = true; + try { + setDateParts(value); + valid = true; + } finally { + updatingInstance = false; + } + updateMissingValueState(); + } + + protected void fireChangeListeners(Object newValue) { + if (!ObjectUtils.equals(prevValue, newValue)) { + Object oldValue = prevValue; + + prevValue = newValue; + + fireValueChanged(oldValue, newValue); + } + } + + protected void setDateParts(Date value) { + datePicker.setDate(value); + timeField.setValueInternal(value); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + datePicker.setEnabled(isEnabledWithParent()); + timeField.setEnabled(isEnabledWithParent()); + } + + @Override + protected void setEditableToComponent(boolean editable) { + datePicker.setEditable(editable); + timeField.setEditable(editable); + updateMissingValueState(); + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + requestContainerUpdate(); + } + + @Override + public String getDescription() { + return datePicker.getToolTipText(); + } + + @Override + public void setDescription(String description) { + if (!ObjectUtils.equals(this.getDescription(), description)) { + datePicker.getEditor().setToolTipText(description); + timeField.setDescription(description); + DesktopToolTipManager.getInstance().registerTooltip(datePicker.getEditor()); + + requestContainerUpdate(); + } + } + + protected void updateInstance() { + if (updatingInstance) { + return; + } + + updatingInstance = true; + try { + if (datasource != null && metaPropertyPath != null) { + Date value = constructDate(); + if (ObjectUtils.equals(prevValue, value)) { + valid = true; + return; + } + setValueToDs(value); + } + valid = true; + } catch (RuntimeException e) { + valid = false; + } finally { + updatingInstance = false; + } + if (valid) { + Object newValue = getValue(); + fireChangeListeners(newValue); + } + } + + protected void updateInstance(Date value) { + if (updatingInstance) { + return; + } + + updatingInstance = true; + try { + if (datasource != null && metaPropertyPath != null) { + setValueToDs(value); + } + valid = true; + } catch (RuntimeException e) { + valid = false; + } finally { + updatingInstance = false; + } + } + + protected void setValueToDs(Date value) { + if (datasource.getItem() != null) { + Object obj = value; + Datatype datatype = metaProperty.getRange().asDatatype(); + if (!datatype.getJavaClass().equals(Date.class)) { + String str = Datatypes.getNN(Date.class).format(value); + try { + obj = datatype.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), obj); + } + } + + protected Date constructDate() { + final Date datePickerDate = datePicker.getDate(); + if (datePickerDate == null) { + return null; + } + + Calendar c = Calendar.getInstance(userSession.getLocale()); + c.setTime(datePickerDate); + if (timeField.getValue() == null) { + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + } else { + Calendar c2 = Calendar.getInstance(userSession.getLocale()); + c2.setTime(timeField.getValue()); + + c.set(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY)); + c.set(Calendar.MINUTE, c2.get(Calendar.MINUTE)); + c.set(Calendar.SECOND, c2.get(Calendar.SECOND)); + } + + //noinspection UnnecessaryLocalVariable + Date serverDate = toServerDate(c.getTime()); + return serverDate; + } + + protected boolean isHourUsed() { + return resolution != null && resolution.ordinal() <= Resolution.HOUR.ordinal(); + } + + protected boolean isMinUsed() { + return resolution != null && resolution.ordinal() <= Resolution.MIN.ordinal(); + } + + public JXDatePicker getDatePicker() { + return datePicker; + } + + public DesktopTimeField getTimeField() { + return timeField; + } + + @Override + public void updateMissingValueState() { + boolean value = required && isEditableWithParent() && datePicker.getEditor().getValue() == null; + decorateMissingValue(datePicker.getEditor(), value); + if (isHourUsed()) { + decorateMissingValue(timeField.getImpl(), value); + timeField.getImpl().repaint(); + } + } + + protected void flush() { + if (isEditable() && isEnabled()) { + try { + datePicker.getEditor().commitEdit(); + } catch (ParseException e) { + return; + } + + updateInstance(); + updateMissingValueState(); + } + } + + protected Dimension getDefaultDimension() { + UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); + if (lafDefaults.getDimension("DateField.dimension") != null) { // take it from desktop theme + return lafDefaults.getDimension("DateField.dimension"); + } + return new Dimension(110, DesktopComponentsHelper.FIELD_HEIGHT); + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } + + public class FocusableComposition extends JPanel implements FocusableComponent, Flushable { + + @Override + public void focus() { + DesktopDateField.this.datePicker.requestFocus(); + } + + @Override + public void flushValue() { + flush(); + } + } + + public class FlushableDatePicker extends DatePicker implements Flushable { + + @Override + public void flushValue() { + flush(); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopEmbedded.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopEmbedded.java index aaba27d13e..8a4d913654 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopEmbedded.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopEmbedded.java @@ -1,181 +1,181 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.Embedded; -import com.haulmont.cuba.gui.export.ExportDataProvider; - -import javax.annotation.Nullable; -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Map; - -public class DesktopEmbedded extends DesktopAbstractComponent implements Embedded { - - private Type type; // only IMAGE currently supported, hope object and browser will never needed for desktop - private Image image; - - public DesktopEmbedded() { - type = Type.IMAGE; - impl = new ImagePanel(); - } - - private void setContents(BufferedImage image, String description) { - this.image = image; - impl.setToolTipText(description); - impl.repaint(); - // todo when width = -1 or height = -1 set width to image.getWidth() and height to image.getHeight(), need screen to test it - } - - @Override - public void setMIMEType(String mt) { - // do nothing, desktop components don't render any MIME types - } - - @Override - public void setSource(@Nullable URL src) { - if (src != null) { - try { - BufferedImage image = ImageIO.read(src); - setContents(image, src.getFile()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } else { - setContents(null, null); - } - } - - @Override - public void setSource(@Nullable String src) { - if (src != null) { - // the same as in WebEmbedded - if (src.startsWith("http") || src.startsWith("https")) { - try { - setSource(new URL(src)); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } else { - throw new UnsupportedOperationException("Unsupported source for image"); - } - } else { - setContents(null, null); - } - } - - @Override - public void setSource(String fileName,@Nullable InputStream src) { - if (src != null) { - try { - BufferedImage image = ImageIO.read(src); - setContents(image, fileName); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - try { - src.close(); - } catch (IOException e) { - // nothing - } - } - } else { - setContents(null, null); - } - } - - @Override - public void setSource(String fileName,@Nullable ExportDataProvider dataProvider) { - if (dataProvider != null) { - try { - BufferedImage image = ImageIO.read(dataProvider.provide()); - setContents(image, fileName); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - dataProvider.close(); - } - } else { - setContents(null, null); - } - } - - @Override - public void setRelativeSource(String src) { - throw new UnsupportedOperationException("setRelativeSource is not implemented for DesktopEmbedded"); - } - - @Override - public void resetSource() { - setContents(null, null); - } - - @Override - public void addParameter(String name, String value) { - throw new UnsupportedOperationException("Any embedded except of image is not supported"); - } - - @Override - public void removeParameter(String name) { - throw new UnsupportedOperationException("Any embedded except of image is not supported"); - } - - @Override - public Map getParameters() { - throw new UnsupportedOperationException("Any embedded except of image is not supported"); - } - - @Override - public void setType(Type t) { - if (t != Type.IMAGE) { - throw new UnsupportedOperationException("Any embedded except of image is not supported"); - } - type = t; - } - - @Override - public Type getType() { - return type; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - private class ImagePanel extends JPanel { - @Override - public void paint(Graphics g) { - if (image != null) { - // automatically resizes to fit width & height - g.drawImage(image, 0, 0, getWidth(), getHeight(), null); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.Embedded; +import com.haulmont.cuba.gui.export.ExportDataProvider; + +import javax.annotation.Nullable; +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +public class DesktopEmbedded extends DesktopAbstractComponent implements Embedded { + + private Type type; // only IMAGE currently supported, hope object and browser will never needed for desktop + private Image image; + + public DesktopEmbedded() { + type = Type.IMAGE; + impl = new ImagePanel(); + } + + private void setContents(BufferedImage image, String description) { + this.image = image; + impl.setToolTipText(description); + impl.repaint(); + // todo when width = -1 or height = -1 set width to image.getWidth() and height to image.getHeight(), need screen to test it + } + + @Override + public void setMIMEType(String mt) { + // do nothing, desktop components don't render any MIME types + } + + @Override + public void setSource(@Nullable URL src) { + if (src != null) { + try { + BufferedImage image = ImageIO.read(src); + setContents(image, src.getFile()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + setContents(null, null); + } + } + + @Override + public void setSource(@Nullable String src) { + if (src != null) { + // the same as in WebEmbedded + if (src.startsWith("http") || src.startsWith("https")) { + try { + setSource(new URL(src)); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } else { + throw new UnsupportedOperationException("Unsupported source for image"); + } + } else { + setContents(null, null); + } + } + + @Override + public void setSource(String fileName,@Nullable InputStream src) { + if (src != null) { + try { + BufferedImage image = ImageIO.read(src); + setContents(image, fileName); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + src.close(); + } catch (IOException e) { + // nothing + } + } + } else { + setContents(null, null); + } + } + + @Override + public void setSource(String fileName,@Nullable ExportDataProvider dataProvider) { + if (dataProvider != null) { + try { + BufferedImage image = ImageIO.read(dataProvider.provide()); + setContents(image, fileName); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + dataProvider.close(); + } + } else { + setContents(null, null); + } + } + + @Override + public void setRelativeSource(String src) { + throw new UnsupportedOperationException("setRelativeSource is not implemented for DesktopEmbedded"); + } + + @Override + public void resetSource() { + setContents(null, null); + } + + @Override + public void addParameter(String name, String value) { + throw new UnsupportedOperationException("Any embedded except of image is not supported"); + } + + @Override + public void removeParameter(String name) { + throw new UnsupportedOperationException("Any embedded except of image is not supported"); + } + + @Override + public Map getParameters() { + throw new UnsupportedOperationException("Any embedded except of image is not supported"); + } + + @Override + public void setType(Type t) { + if (t != Type.IMAGE) { + throw new UnsupportedOperationException("Any embedded except of image is not supported"); + } + type = t; + } + + @Override + public Type getType() { + return type; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + private class ImagePanel extends JPanel { + @Override + public void paint(Graphics g) { + if (image != null) { + // automatically resizes to fit width & height + g.drawImage(image, 0, 0, getWidth(), getHeight(), null); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopExportDisplay.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopExportDisplay.java index cef763dbd1..b44b74f774 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopExportDisplay.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopExportDisplay.java @@ -1,233 +1,233 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.Action.Status; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.executors.BackgroundWorker; -import com.haulmont.cuba.gui.export.ExportDataProvider; -import com.haulmont.cuba.gui.export.ExportDisplay; -import com.haulmont.cuba.gui.export.ExportFormat; -import com.haulmont.cuba.gui.export.FileDataProvider; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.context.annotation.Scope; - -import javax.inject.Inject; -import javax.swing.*; -import java.awt.*; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Allows to show exported data in external desktop app or download it. - */ -@org.springframework.stereotype.Component(ExportDisplay.NAME) -@Scope("prototype") -public class DesktopExportDisplay implements ExportDisplay { - - private static final String RESERVED_SYMBOLS = "\\/:*?\"<>|"; - - @Inject - protected BackgroundWorker backgroundWorker; - - @Inject - protected Messages messages; - - protected Frame frame; - - public DesktopExportDisplay() { - } - - /** - * Show/Download resource at client side - * - * @param dataProvider {@link ExportDataProvider} - * @param resourceName ResourceName for client side - * @param format {@link ExportFormat} - * @see com.haulmont.cuba.gui.export.FileDataProvider - * @see com.haulmont.cuba.gui.export.ByteArrayDataProvider - */ - @Override - public void show(final ExportDataProvider dataProvider, String resourceName, ExportFormat format) { - backgroundWorker.checkUIAccess(); - - String fileName = resourceName; - if (format != null) { - if (StringUtils.isEmpty(getFileExt(fileName))) - fileName += "." + format.getFileExt(); - } - - String dialogMessage = messages.getMessage(getClass(), "export.saveFile"); - String correctName = StringUtils.replaceChars(fileName, RESERVED_SYMBOLS, "_"); - dialogMessage = String.format(dialogMessage, correctName); - - final String finalFileName = correctName; - String fileCaption = messages.getMessage(getClass(), "export.fileCaption"); - getFrame().getWindowManager().showOptionDialog(fileCaption, dialogMessage, Frame.MessageType.CONFIRMATION, - new com.haulmont.cuba.gui.components.Action[]{ - new AbstractAction("action.openFile", Status.PRIMARY) { - @Override - public void actionPerform(Component component) { - openFileAction(finalFileName, dataProvider); - } - }, - new AbstractAction("action.saveFile") { - @Override - public void actionPerform(Component component) { - saveFileAction(finalFileName, getFrame(), dataProvider); - } - }, - new AbstractAction("actions.Cancel") { - @Override - public void actionPerform(Component component) { - // do nothing - } - } - }); - } - - private void saveFileAction(String fileName, JFrame frame, ExportDataProvider dataProvider) { - JFileChooser fileChooser = new JFileChooser(); - fileChooser.setSelectedFile(new File(fileName)); - if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) { - File selectedFile = fileChooser.getSelectedFile(); - boolean success = saveFile(dataProvider, selectedFile); - TopLevelFrame mainFrame = App.getInstance().getMainFrame(); - if (success) { - mainFrame.showNotification(messages.getMessage(DesktopExportDisplay.class, "export.saveSuccess"), Frame.NotificationType.TRAY); - } else { - mainFrame.showNotification(messages.getMessage(DesktopExportDisplay.class, "export.saveError"), Frame.NotificationType.ERROR); - } - } - } - - private void openFileAction(String finalFileName, ExportDataProvider dataProvider) { - File destFile = null; - try { - destFile = File.createTempFile("get_" + FilenameUtils.getBaseName(finalFileName), "." + getFileExt(finalFileName)); - } catch (IOException e) { - String message = messages.getMessage(DesktopExportDisplay.class, "export.tempFileError"); - getFrame().getWindowManager().showNotification(message, Frame.NotificationType.WARNING); - } - - if (destFile != null) { - if (Desktop.isDesktopSupported() && saveFile(dataProvider, destFile)) { - try { - Desktop.getDesktop().open(destFile); - } catch (IOException ex) { - String message = messages.getMessage(DesktopExportDisplay.class, "export.openError"); - getFrame().getWindowManager().showNotification(message, - Frame.NotificationType.WARNING); - } - } - } - } - - /** - * Show/Download resource at client side - * - * @param dataProvider {@link ExportDataProvider} - * @param resourceName ResourceName for client side - * @see com.haulmont.cuba.gui.export.FileDataProvider - * @see com.haulmont.cuba.gui.export.ByteArrayDataProvider - */ - @Override - public void show(ExportDataProvider dataProvider, String resourceName) { - String extension = getFileExt(resourceName); - ExportFormat format = ExportFormat.getByExtension(extension); - show(dataProvider, resourceName, format); - } - - /** - * Show/Download file at client side - * - * @param fileDescriptor File descriptor - * @param format {@link ExportFormat} - */ - @Override - public void show(FileDescriptor fileDescriptor, ExportFormat format) { - show(new FileDataProvider(fileDescriptor), fileDescriptor.getName(), format); - } - - @Override - public void show(FileDescriptor fileDescriptor) { - ExportFormat format = ExportFormat.getByExtension(fileDescriptor.getExtension()); - show(fileDescriptor, format); - } - - @Override - public void setFrame(Frame frame) { - this.frame = frame; - } - - protected boolean saveFile(ExportDataProvider dataProvider, File destinationFile) { - try { - if (!destinationFile.exists()) { - boolean crateResult = destinationFile.createNewFile(); - if (!crateResult) - throw new IOException("Couldn't create file"); - } - - InputStream fileInput = null; - try { - fileInput = dataProvider.provide(); - FileOutputStream outputStream = new FileOutputStream(destinationFile); - - IOUtils.copy(fileInput, outputStream); - - IOUtils.closeQuietly(fileInput); - IOUtils.closeQuietly(outputStream); - } finally { - if (fileInput != null) { - IOUtils.closeQuietly(fileInput); - } - } - } catch (IOException e) { - String message = messages.getMessage(DesktopExportDisplay.class, "export.saveError"); - getFrame().getWindowManager().showNotification(message, com.haulmont.cuba.gui.components.Frame.NotificationType.WARNING); - return false; - } - return true; - } - - protected String getFileExt(String fileName) { - int i = fileName.lastIndexOf('.'); - if (i > -1) - return StringUtils.substring(fileName, i + 1, i + 20); - else - return ""; - } - - protected TopLevelFrame getFrame() { - if (frame != null) { - return DesktopComponentsHelper.getTopLevelFrame(frame); - } else { - return App.getInstance().getMainFrame(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.Action.Status; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.executors.BackgroundWorker; +import com.haulmont.cuba.gui.export.ExportDataProvider; +import com.haulmont.cuba.gui.export.ExportDisplay; +import com.haulmont.cuba.gui.export.ExportFormat; +import com.haulmont.cuba.gui.export.FileDataProvider; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.context.annotation.Scope; + +import javax.inject.Inject; +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Allows to show exported data in external desktop app or download it. + */ +@org.springframework.stereotype.Component(ExportDisplay.NAME) +@Scope("prototype") +public class DesktopExportDisplay implements ExportDisplay { + + private static final String RESERVED_SYMBOLS = "\\/:*?\"<>|"; + + @Inject + protected BackgroundWorker backgroundWorker; + + @Inject + protected Messages messages; + + protected Frame frame; + + public DesktopExportDisplay() { + } + + /** + * Show/Download resource at client side + * + * @param dataProvider {@link ExportDataProvider} + * @param resourceName ResourceName for client side + * @param format {@link ExportFormat} + * @see com.haulmont.cuba.gui.export.FileDataProvider + * @see com.haulmont.cuba.gui.export.ByteArrayDataProvider + */ + @Override + public void show(final ExportDataProvider dataProvider, String resourceName, ExportFormat format) { + backgroundWorker.checkUIAccess(); + + String fileName = resourceName; + if (format != null) { + if (StringUtils.isEmpty(getFileExt(fileName))) + fileName += "." + format.getFileExt(); + } + + String dialogMessage = messages.getMessage(getClass(), "export.saveFile"); + String correctName = StringUtils.replaceChars(fileName, RESERVED_SYMBOLS, "_"); + dialogMessage = String.format(dialogMessage, correctName); + + final String finalFileName = correctName; + String fileCaption = messages.getMessage(getClass(), "export.fileCaption"); + getFrame().getWindowManager().showOptionDialog(fileCaption, dialogMessage, Frame.MessageType.CONFIRMATION, + new com.haulmont.cuba.gui.components.Action[]{ + new AbstractAction("action.openFile", Status.PRIMARY) { + @Override + public void actionPerform(Component component) { + openFileAction(finalFileName, dataProvider); + } + }, + new AbstractAction("action.saveFile") { + @Override + public void actionPerform(Component component) { + saveFileAction(finalFileName, getFrame(), dataProvider); + } + }, + new AbstractAction("actions.Cancel") { + @Override + public void actionPerform(Component component) { + // do nothing + } + } + }); + } + + private void saveFileAction(String fileName, JFrame frame, ExportDataProvider dataProvider) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setSelectedFile(new File(fileName)); + if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + boolean success = saveFile(dataProvider, selectedFile); + TopLevelFrame mainFrame = App.getInstance().getMainFrame(); + if (success) { + mainFrame.showNotification(messages.getMessage(DesktopExportDisplay.class, "export.saveSuccess"), Frame.NotificationType.TRAY); + } else { + mainFrame.showNotification(messages.getMessage(DesktopExportDisplay.class, "export.saveError"), Frame.NotificationType.ERROR); + } + } + } + + private void openFileAction(String finalFileName, ExportDataProvider dataProvider) { + File destFile = null; + try { + destFile = File.createTempFile("get_" + FilenameUtils.getBaseName(finalFileName), "." + getFileExt(finalFileName)); + } catch (IOException e) { + String message = messages.getMessage(DesktopExportDisplay.class, "export.tempFileError"); + getFrame().getWindowManager().showNotification(message, Frame.NotificationType.WARNING); + } + + if (destFile != null) { + if (Desktop.isDesktopSupported() && saveFile(dataProvider, destFile)) { + try { + Desktop.getDesktop().open(destFile); + } catch (IOException ex) { + String message = messages.getMessage(DesktopExportDisplay.class, "export.openError"); + getFrame().getWindowManager().showNotification(message, + Frame.NotificationType.WARNING); + } + } + } + } + + /** + * Show/Download resource at client side + * + * @param dataProvider {@link ExportDataProvider} + * @param resourceName ResourceName for client side + * @see com.haulmont.cuba.gui.export.FileDataProvider + * @see com.haulmont.cuba.gui.export.ByteArrayDataProvider + */ + @Override + public void show(ExportDataProvider dataProvider, String resourceName) { + String extension = getFileExt(resourceName); + ExportFormat format = ExportFormat.getByExtension(extension); + show(dataProvider, resourceName, format); + } + + /** + * Show/Download file at client side + * + * @param fileDescriptor File descriptor + * @param format {@link ExportFormat} + */ + @Override + public void show(FileDescriptor fileDescriptor, ExportFormat format) { + show(new FileDataProvider(fileDescriptor), fileDescriptor.getName(), format); + } + + @Override + public void show(FileDescriptor fileDescriptor) { + ExportFormat format = ExportFormat.getByExtension(fileDescriptor.getExtension()); + show(fileDescriptor, format); + } + + @Override + public void setFrame(Frame frame) { + this.frame = frame; + } + + protected boolean saveFile(ExportDataProvider dataProvider, File destinationFile) { + try { + if (!destinationFile.exists()) { + boolean crateResult = destinationFile.createNewFile(); + if (!crateResult) + throw new IOException("Couldn't create file"); + } + + InputStream fileInput = null; + try { + fileInput = dataProvider.provide(); + FileOutputStream outputStream = new FileOutputStream(destinationFile); + + IOUtils.copy(fileInput, outputStream); + + IOUtils.closeQuietly(fileInput); + IOUtils.closeQuietly(outputStream); + } finally { + if (fileInput != null) { + IOUtils.closeQuietly(fileInput); + } + } + } catch (IOException e) { + String message = messages.getMessage(DesktopExportDisplay.class, "export.saveError"); + getFrame().getWindowManager().showNotification(message, com.haulmont.cuba.gui.components.Frame.NotificationType.WARNING); + return false; + } + return true; + } + + protected String getFileExt(String fileName) { + int i = fileName.lastIndexOf('.'); + if (i > -1) + return StringUtils.substring(fileName, i + 1, i + 20); + else + return ""; + } + + protected TopLevelFrame getFrame() { + if (frame != null) { + return DesktopComponentsHelper.getTopLevelFrame(frame); + } else { + return App.getInstance().getMainFrame(); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFieldGroup.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFieldGroup.java index 2d2708c51a..4d74630693 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFieldGroup.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFieldGroup.java @@ -1,1645 +1,1645 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.google.common.base.Strings; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; -import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; -import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Formatter; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import net.miginfocom.layout.CC; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.awt.*; -import java.util.*; -import java.util.List; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -public class DesktopFieldGroup extends DesktopAbstractComponent - implements FieldGroup, AutoExpanding, Component.UiPermissionAware { - - private final Logger log = LoggerFactory.getLogger(DesktopFieldGroup.class); - - public static final String DEFAULT_FIELD_WIDTH = "200px"; - - protected String description; - - protected MigLayout layout; - protected Datasource datasource; - protected CollapsiblePanel collapsiblePanel; - - protected int rows = 0; - protected int cols = 1; - - protected boolean editable = true; - protected boolean borderVisible = false; - - protected FieldCaptionAlignment captionAlignment; - - protected Map fields = new HashMap<>(); - protected List> columnFieldMapping = new ArrayList<>(); - { - columnFieldMapping.add(new ArrayList<>()); - } - - protected Map columnFieldCaptionWidth = null; - protected int fieldCaptionWidth = -1; - - protected boolean requestUpdateCaptionWidth = false; - - protected List editableChangeListeners = new ArrayList<>(); - - protected FieldGroupFieldFactory fieldFactory; - - public DesktopFieldGroup() { - LC lc = new LC(); - lc.hideMode(3); // Invisible components will not participate in the layout at all and it will for instance not take up a grid cell. - lc.insets("0 0 0 0"); - if (LayoutAdapter.isDebug()) { - lc.debug(1000); - } - - layout = new MigLayout(lc); - impl = new JPanel(layout); - assignClassDebugProperty(impl); - collapsiblePanel = new CollapsiblePanel(super.getComposition()); - assignClassDebugProperty(collapsiblePanel); - collapsiblePanel.setBorderVisible(false); - - setWidth(Component.AUTO_SIZE); - - fieldFactory = AppBeans.get(FieldGroupFieldFactory.NAME); - } - - /** - * @return flat list of column fields - */ - protected List getColumnOrderedFields() { - return columnFieldMapping.stream() - .flatMap(List::stream) - .collect(Collectors.toList()); - } - - @Override - public FieldConfig createField(String id) { - return new FieldConfigImpl(id); - } - - @Override - public List getFields() { - return getColumnOrderedFields(); - } - - @Override - public List getFields(int column) { - return Collections.unmodifiableList(columnFieldMapping.get(column)); - } - - @Override - public FieldConfig getField(int column, int row) { - return columnFieldMapping.get(column).get(row); - } - - @Override - public FieldConfig getField(String fieldId) { - for (final Map.Entry entry : fields.entrySet()) { - if (entry.getKey().equals(fieldId)) { - return entry.getValue(); - } - } - return null; - } - - @Override - public FieldConfig getFieldNN(String fieldId) { - FieldConfig fieldConfig = fields.get(fieldId); - if (fieldConfig == null) { - throw new IllegalArgumentException("Unable to find field with id " + fieldId); - } - - return fieldConfig; - } - - @Override - public void add(Component childComponent) { - throw new UnsupportedOperationException("Add component is not supported by FieldGroup component"); - } - - @Override - public void remove(Component childComponent) { - throw new UnsupportedOperationException("Remove component is not supported by FieldGroup component"); - } - - @Override - public void removeAll() { - throw new UnsupportedOperationException("Remove all components are not supported by FieldGroup component"); - } - - @Nullable - @Override - public Component getOwnComponent(String id) { - FieldConfig fieldConfig = getField(id); - if (fieldConfig != null && fieldConfig.isBound()) { - return fieldConfig.getComponent(); - } - return null; - } - - @Nullable - @Override - public Component getComponent(String id) { - return ComponentsHelper.getComponent(this, id); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public List getOwnComponents() { - return getColumnOrderedFields().stream() - .filter(FieldConfig::isBound) - .map(FieldConfig::getComponent) - .collect(Collectors.toList()); - } - - @Override - public void addField(FieldConfig field) { - addField(field, 0); - } - - @Override - public void addField(FieldConfig fc, int colIndex) { - checkArgument(!fields.containsKey(fc.getId()), "Field is already registered"); - checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field does not belong to this FieldGroup"); - - if (colIndex < 0 || colIndex >= getColumns()) { - throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", - colIndex, getColumns())); - } - - addFieldInternal(fc, colIndex, -1); - } - - @Override - public void addField(FieldConfig fc, int colIndex, int rowIndex) { - checkArgument(!fields.containsKey(fc.getId()), "Field is already registered"); - checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field does not belong to this FieldGroup"); - - if (colIndex < 0 || colIndex >= getColumns()) { - throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", - colIndex, getColumns())); - } - List colFields = columnFieldMapping.get(colIndex); - if (rowIndex < 0 || rowIndex > colFields.size()) { - throw new IllegalArgumentException(String.format("Illegal row number %s, available amount of rows is %s", - rowIndex, getRows())); - } - - addFieldInternal(fc, colIndex, rowIndex); - } - - protected void addFieldInternal(FieldConfig fc, int colIndex, int rowIndex) { - List colFields = columnFieldMapping.get(colIndex); - if (rowIndex == -1) { - rowIndex = colFields.size(); - } - - fields.put(fc.getId(), fc); - colFields.add(rowIndex, fc); - - FieldConfigImpl fci = (FieldConfigImpl) fc; - - fci.setColumn(colIndex); - fci.setManaged(true); - - if (fc.getComponent() != null) { - managedFieldComponentAssigned(fci, fci.getAttachMode()); - - impl.revalidate(); - impl.repaint(); - } - } - - @Override - public void removeField(String fieldId) { - removeField(getFieldNN(fieldId)); - } - - @Override - public void removeField(FieldConfig fc) { - checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field is not belong to this FieldGroup"); - - if (fields.values().contains(fc)) { - int colIndex = ((FieldConfigImpl) fc).getColumn(); - columnFieldMapping.get(colIndex).remove(fc); - fields.remove(fc.getId()); - - boolean wasBound = fc.isBound(); - if (fc.isBound()) { - FieldConfigImpl fci = (FieldConfigImpl) fc; - - impl.remove(fci.getCompositionNN().getComposition()); - if (fci.getLabel() != null) { - impl.remove(fci.getLabel()); - } - if (fci.getToolTipButton() != null) { - impl.remove(fci.getToolTipButton()); - } - - reattachColumnFields(colIndex); - - this.rows = detectRowsCount(); - } - - ((FieldConfigImpl) fc).setManaged(false); - - if (fc.getComponent() != null) { - fc.getComponent().setParent(null); - } - - if (wasBound) { - impl.revalidate(); - impl.repaint(); - } - } - } - - @Override - public void requestFocus() { - for (FieldConfig fc : getColumnOrderedFields()) { - Component component = fc.getComponent(); - if (component != null - && component.isEnabled() - && component.isVisible() - && component instanceof Focusable - && ((Focusable) component).isFocusable()) { - - component.requestFocus(); - break; - } - } - } - - @Override - public void requestFocus(String fieldId) { - FieldConfig field = getFieldNN(fieldId); - Component componentField = field.getComponentNN(); - componentField.requestFocus(); - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public void setDatasource(final Datasource datasource) { - if (this.datasource != null) { - throw new UnsupportedOperationException("Changing datasource is not supported by the FieldGroup component"); - } - - this.datasource = datasource; - - assignAutoDebugId(); - } - - @Override - public void bind() { - bindDeclarativeFieldConfigs(); - } - - protected void bindDeclarativeFieldConfigs() { - List reattachColumns = new ArrayList<>(); - - for (FieldConfig fc : getColumnOrderedFields()) { - if (!fc.isCustom() && !fc.isBound()) { - FieldConfigImpl fci = (FieldConfigImpl) fc; - - Datasource targetDs = fc.getTargetDatasource(); - if (targetDs == null) { - throw new IllegalStateException(String.format("Unable to get datasource for field '%s'", id)); - } - - FieldGroupFieldFactory.GeneratedField generatedField = fieldFactory.createField(fc); - Component fieldComponent = generatedField.getComponent(); - - fci.assignComponent(fieldComponent); - fci.setAttachMode(generatedField.getAttachMode()); - - setupFieldComponent(fci); - - DesktopAbstractComponent fieldImpl = (DesktopAbstractComponent) fieldComponent; - fci.setComposition(fieldImpl); - - if (fci.getDescription() != null) { - ToolTipButton tooltipBtn = new ToolTipButton(); - tooltipBtn.setVisible(fieldComponent.isVisible()); - tooltipBtn.setToolTipText(fci.getDescription()); - fci.setToolTipButton(new ToolTipButton()); - } else { - fci.setToolTipButton(null); - } - - assignTypicalAttributes(fieldComponent); - - if (generatedField.getAttachMode() == FieldAttachMode.APPLY_DEFAULTS) { - applyFieldDefaults(fci); - } - - int columnIndex = fci.getColumn(); - if (!reattachColumns.contains(columnIndex)) { - reattachColumns.add(columnIndex); - } - } - } - - if (!reattachColumns.isEmpty()) { - this.rows = detectRowsCount(); - - for (Integer reattachColumnIndex : reattachColumns) { - reattachColumnFields(reattachColumnIndex); - } - } - - impl.revalidate(); - impl.repaint(); - } - - protected void setupFieldComponent(FieldConfig fieldConfig) { - Component fieldComponent = fieldConfig.getComponent(); - - if (fieldComponent instanceof DesktopCheckBox) { - fieldComponent.setAlignment(Alignment.MIDDLE_LEFT); - } - } - - protected void reattachColumnFields(int colIndex) { - fields.values().stream() - .filter(FieldConfig::isBound) - .map(fieldConfig -> ((FieldConfigImpl) fieldConfig)) - .filter(fci -> fci.getColumn() == colIndex) - .forEach(fci -> { - impl.remove(fci.getCompositionNN().getComposition()); - if (fci.getLabel() != null) { - impl.remove(fci.getLabel()); - } - if (fci.getToolTipButton() != null) { - impl.remove(fci.getToolTipButton()); - } - }); - - List columnFCs = columnFieldMapping.get(colIndex); - int insertRowIndex = 0; - for (FieldConfig fc : columnFCs) { - if (fc.isBound()) { - FieldConfigImpl fci = (FieldConfigImpl) fc; - - Component fieldComponent = fci.getComponentNN(); - JComponent composition = fieldComponent.unwrapComposition(JComponent.class); - - JLabel label = fci.getLabel(); - if (label != null) { - int preferredCaptionWidth = getPreferredCaptionWidth(colIndex); - if (preferredCaptionWidth > 0) { - label.setPreferredSize(new Dimension(preferredCaptionWidth, 25)); - label.setMaximumSize(new Dimension(preferredCaptionWidth, 25)); - label.setMinimumSize(new Dimension(preferredCaptionWidth, 25)); - } else { - label.setPreferredSize(new Dimension(label.getPreferredSize().width, 25)); - } - label.setVisible(fieldComponent.isVisible()); - - CC labelCc = new CC(); - MigLayoutHelper.applyAlignment(labelCc, Alignment.TOP_LEFT); - - impl.add(label, labelCc.cell(colIndex * 3, insertRowIndex, 1, 1)); - } - - if (Strings.isNullOrEmpty(fci.getDescription())) { - fci.setToolTipButton(null); - } else if (fci.getToolTipButton() == null) { - ToolTipButton toolTipButton = new ToolTipButton(); - toolTipButton.setToolTipText(fci.getDescription()); - toolTipButton.setVisible(fieldComponent.isVisible()); - fci.setToolTipButton(toolTipButton); - } - - ToolTipButton toolTipButton = fci.getToolTipButton(); - if (toolTipButton != null) { - toolTipButton.setVisible(fieldComponent.isVisible()); - DesktopToolTipManager.getInstance().registerTooltip(toolTipButton); - impl.add(toolTipButton, new CC().cell(colIndex * 3 + 2, insertRowIndex, 1, 1).alignY("top")); - } - - CC cell = new CC().cell(colIndex * 3 + 1, insertRowIndex, 1, 1); - - MigLayoutHelper.applyWidth(cell, (int) fieldComponent.getWidth(), fieldComponent.getWidthUnits(), false); - MigLayoutHelper.applyHeight(cell, (int) fieldComponent.getHeight(), fieldComponent.getHeightUnits(), false); - MigLayoutHelper.applyAlignment(cell, fieldComponent.getAlignment()); - - composition.putClientProperty(getSwingPropertyId(), fci.getId()); - impl.add(composition, cell); - - insertRowIndex++; - } - } - - impl.validate(); - impl.repaint(); - } - - protected int detectRowsCount() { - int rowsCount = 0; - for (List fields : columnFieldMapping) { - long boundCount = fields.stream() - .filter(FieldConfig::isBound) - .count(); - - rowsCount = (int) Math.max(rowsCount, boundCount); - } - return Math.max(rowsCount, 1); - } - - protected void managedFieldComponentAssigned(FieldConfigImpl fci, FieldAttachMode mode) { - DesktopAbstractComponent fieldImpl = (DesktopAbstractComponent) fci.getComponentNN(); - fci.setComposition(fieldImpl); - - if (fci.getDescription() != null) { - ToolTipButton tooltipBtn = new ToolTipButton(); - tooltipBtn.setVisible(fci.getComponentNN().isVisible()); - tooltipBtn.setToolTipText(fci.getDescription()); - fci.setToolTipButton(new ToolTipButton()); - } else { - fci.setToolTipButton(null); - } - - if (fieldImpl.getCaption() != null) { - fci.getLabel().setText(fieldImpl.getCaption()); - } - - assignTypicalAttributes(fci.getComponentNN()); - - if (mode == FieldAttachMode.APPLY_DEFAULTS) { - applyFieldDefaults(fci); - } - - this.rows = detectRowsCount(); - - reattachColumnFields(fci.getColumn()); - } - - protected void applyFieldDefaults(FieldConfigImpl fci) { - Component fieldComponent = fci.getComponentNN(); - - if (fieldComponent instanceof Field) { - Field cubaField = (Field) fieldComponent; - - if (fci.getTargetCaption() != null) { - cubaField.setCaption(fci.getTargetCaption()); - } - if (fci.getTargetDescription() != null) { - cubaField.setDescription(fci.getTargetDescription()); - } - if (fci.getTargetRequired() != null) { - cubaField.setRequired(fci.getTargetRequired()); - } - if (fci.getTargetRequiredMessage() != null) { - cubaField.setRequiredMessage(fci.getTargetRequiredMessage()); - } - if (fci.getTargetEditable() != null) { - cubaField.setEditable(fci.getTargetEditable()); - } - if (fci.getTargetVisible() != null) { - cubaField.setVisible(fci.getTargetVisible()); - } - if (cubaField instanceof Component.Focusable && fci.getTargetTabIndex() != null) { - ((Component.Focusable) cubaField).setTabIndex(fci.getTargetTabIndex()); - } - for (Field.Validator validator : fci.getTargetValidators()) { - cubaField.addValidator(validator); - } - - if (fci.getTargetWidth() != null) { - fieldComponent.setWidth(fci.getTargetWidth()); - } else { - fieldComponent.setWidth(DEFAULT_FIELD_WIDTH); - } - } else { - DesktopAbstractComponent composition = fci.getCompositionNN(); - if (fci.getTargetCaption() != null) { - fci.getLabel().setText(fci.getTargetCaption()); - } - if (fci.getTargetVisible() != null) { - composition.setVisible(fci.getTargetVisible()); - } - if (fci.getTargetWidth() != null) { - composition.setWidth(fci.getTargetWidth()); - } else { - composition.setWidth(DEFAULT_FIELD_WIDTH); - } - } - - if (fieldComponent instanceof Component.HasFormatter && fci.getTargetFormatter() != null) { - ((Component.HasFormatter) fieldComponent).setFormatter(fci.getTargetFormatter()); - } - - if (StringUtils.isNotEmpty(fci.getTargetStylename())) { - fieldComponent.setStyleName(fci.getTargetStylename()); - } - - App app = App.getInstance(); - if (app != null && app.isTestMode()) { - fci.getCompositionNN().getComposition().setName(fci.getId()); - } - } - - protected void doSetParentEnabled(FieldConfig fc, boolean enabled) { - if (fc.getComponent() != null) { - Component component = fc.getComponent(); - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(enabled); - } - - FieldConfigImpl fci = (FieldConfigImpl) fc; - if (fci.getLabel() != null) { - fci.getLabel().setEnabled(enabled); - } - } - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - for (FieldConfig field : fields.values()) { - doSetParentEnabled(field, parentEnabled && enabled); - } - } - - @Override - public boolean isBorderVisible() { - return borderVisible; - } - - @Override - public void setBorderVisible(boolean borderVisible) { - this.borderVisible = borderVisible; - collapsiblePanel.setBorderVisible(borderVisible); - } - - @Override - public FieldCaptionAlignment getCaptionAlignment() { - return captionAlignment; - } - - @Override - public void setCaptionAlignment(FieldCaptionAlignment captionAlignment) { - this.captionAlignment = captionAlignment; - - log.warn("setCaptionAlignment not implemented for desktop"); - } - - @Override - public int getFieldCaptionWidth() { - return fieldCaptionWidth; - } - - @Override - public void setFieldCaptionWidth(int fixedCaptionWidth) { - this.fieldCaptionWidth = fixedCaptionWidth; - - updateCaptionWidths(); - } - - @Override - public int getFieldCaptionWidth(int column) { - if (columnFieldCaptionWidth != null) { - Integer value = columnFieldCaptionWidth.get(column); - return value != null ? value : -1; - } - return -1; - } - - @Override - public void setFieldCaptionWidth(int column, int width) { - if (columnFieldCaptionWidth == null) { - columnFieldCaptionWidth = new HashMap<>(); - } - columnFieldCaptionWidth.put(column, width); - - updateCaptionWidths(); - } - - protected void updateCaptionWidths() { - if (!requestUpdateCaptionWidth) { - SwingUtilities.invokeLater(() -> { - requestUpdateCaptionWidth = false; - - for (FieldConfig fieldConfig : fields.values()) { - JLabel label = ((FieldConfigImpl) fieldConfig).getLabel(); - - if (label != null) { - int col = ((FieldConfigImpl) fieldConfig).getColumn(); - int preferredCaptionWidth = getPreferredCaptionWidth(col); - - if (preferredCaptionWidth > 0) { - label.setPreferredSize(new Dimension(preferredCaptionWidth, 25)); - label.setMaximumSize(new Dimension(preferredCaptionWidth, 25)); - label.setMinimumSize(new Dimension(preferredCaptionWidth, 25)); - } - } - } - }); - requestUpdateCaptionWidth = true; - } - } - - protected int getPreferredCaptionWidth(int col) { - int preferredCaptionWidth = -1; - if (fieldCaptionWidth > 0) { - preferredCaptionWidth = fieldCaptionWidth; - } - if (columnFieldCaptionWidth != null - && columnFieldCaptionWidth.containsKey(col)) { - preferredCaptionWidth = columnFieldCaptionWidth.get(col); - } - return preferredCaptionWidth; - } - - @Override - public int getColumns() { - return cols; - } - - public int getRows() { - return rows; - } - - public DesktopAbstractComponent getCellComponent(int colIndex, int rowIndex) { - if (colIndex < 0 || colIndex >= getColumns()) { - throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", - colIndex, getColumns())); - } - List colFields = columnFieldMapping.get(colIndex); - if (rowIndex < 0 || rowIndex > colFields.size()) { - throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", - colIndex, getColumns())); - } - - for (FieldConfig fieldConfig : fields.values()) { - DesktopAbstractComponent composition = ((FieldConfigImpl) fieldConfig).getComposition(); - if (composition != null) { - JComponent jComponent = composition.getComposition(); - Object componentConstraints = layout.getComponentConstraints(jComponent); - if (componentConstraints instanceof CC) { - CC cc = (CC) componentConstraints; - if (cc.getCellY() == rowIndex) { - int ccColIndex = (cc.getCellX() - 1) / 3; - if (colIndex == ccColIndex) { - return composition; - } - } - } - } - } - return null; - } - - @Override - public void setColumns(int columns) { - if (this.cols != columns) { - this.cols = columns; - - List> oldColumnFields = this.columnFieldMapping; - this.columnFieldMapping = new ArrayList<>(); - for (int i = 0; i < columns; i++) { - if (i < oldColumnFields.size()) { - columnFieldMapping.add(oldColumnFields.get(i)); - } else { - columnFieldMapping.add(new ArrayList<>()); - } - } - } - } - - @Override - public float getColumnExpandRatio(int col) { - return 0; - } - - @Override - public void setColumnExpandRatio(int col, float ratio) { - } - - @Override - public FieldGroupFieldFactory getFieldFactory() { - return fieldFactory; - } - - @Override - public void setFieldFactory(FieldGroupFieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - } - - @Override - public void addCustomField(String fieldId, CustomFieldGenerator fieldGenerator) { - FieldConfig field = getField(fieldId); - if (field == null) { - throw new IllegalArgumentException(String.format("Field '%s' doesn't exist", fieldId)); - } - addCustomField(field, fieldGenerator); - } - - @Override - public void addCustomField(FieldConfig fc, CustomFieldGenerator fieldGenerator) { - if (!fc.isCustom()) { - throw new IllegalStateException(String.format("Field '%s' must be defined as custom", fc.getId())); - } - - FieldConfigImpl fci = (FieldConfigImpl) fc; - - Component fieldComponent = fieldGenerator.generateField(fc.getTargetDatasource(), fci.getTargetProperty()); - fc.setComponent(fieldComponent); - } - - @Override - public void setId(String id) { - super.setId(id); - - if (id != null && App.getInstance().isTestMode()) { - for (FieldConfig fc : fields.values()) { - Component fieldComponent = fc.getComponent(); - if (fieldComponent != null) { - JComponent jComponent = DesktopComponentsHelper.getComposition(fieldComponent); - if (jComponent != null) { - jComponent.setName(fc.getId()); - } - } - } - } - } - - protected void assignTypicalAttributes(Component c) { - if (c instanceof BelongToFrame) { - BelongToFrame belongToFrame = (BelongToFrame) c; - if (belongToFrame.getFrame() == null) { - belongToFrame.setFrame(getFrame()); - } - } - c.setParent(this); - } - - @Override - public boolean isEditable() { - return editable; - } - - @Override - public void setEditable(boolean editable) { - if (editable != isEditable()) { - this.editable = editable; - - EditableChangeEvent event = new EditableChangeEvent(this); - for (EditableChangeListener listener : new ArrayList<>(editableChangeListeners)) { - listener.editableChanged(event); - } - } - } - - @Override - public String getCaption() { - return collapsiblePanel.getCaption(); - } - - @Override - public void setCaption(String caption) { - collapsiblePanel.setCaption(caption); - } - - @Override - public String getDescription() { - return description; - } - - @Override - public void setDescription(String description) { - this.description = description; - } - - @Override - public JComponent getComposition() { - return collapsiblePanel; - } - - @Override - public boolean expandsWidth() { - return true; - } - - @Override - public boolean expandsHeight() { - return false; - } - - @Override - public boolean isValid() { - try { - validate(); - return true; - } catch (ValidationException e) { - return false; - } - } - - @Override - public void validate() throws ValidationException { - if (!isVisible() || !isEditableWithParent() || !isEnabled()) { - return; - } - - Map problemFields = null; // lazily initialized - - // validate column by column - List fieldsByColumns = getColumnOrderedFields(); - - for (FieldConfig fc : fieldsByColumns) { - Component fieldComponent = fc.getComponent(); - - // If has valid state - if ((fieldComponent instanceof Validatable) && - (fieldComponent instanceof Editable)) { - // If editable - try { - ((Validatable) fieldComponent).validate(); - } catch (ValidationException ex) { - if (problemFields == null) { - problemFields = new LinkedHashMap<>(); - } - problemFields.put((Validatable) fieldComponent, ex); - } - } - } - - if (problemFields != null && !problemFields.isEmpty()) { - FieldsValidationException validationException = new FieldsValidationException(); - validationException.setProblemFields(problemFields); - - throw validationException; - } - } - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { - return "fieldGroup_" + datasource.getId(); - } - - return getClass().getSimpleName(); - } - - public void updateCaptionVisibility(DesktopAbstractComponent child) { - FieldConfig field = fields.values().stream() - .filter(entry -> entry.getComponent() == child) - .findFirst() - .orElse(null); - - FieldConfigImpl fci = (FieldConfigImpl) field; - if (fci != null && fci.getLabel() != null) { - fci.getLabel().setVisible(child.isComponentVisible()); - } - } - - public void updateCaptionText(DesktopAbstractComponent child) { - FieldConfig field = fields.values().stream() - .filter(entry -> entry.getComponent() == child) - .findFirst() - .orElse(null); - - FieldConfigImpl fci = (FieldConfigImpl) field; - if (fci != null && fci.getLabel() != null) { - fci.getLabel().setText(child.getCaption()); - } - } - - public void updateChildEnabled(DesktopAbstractComponent child) { - FieldConfig field = fields.values().stream() - .filter(entry -> entry.getComponent() == child) - .findFirst() - .orElse(null); - - FieldConfigImpl fci = (FieldConfigImpl) field; - if (fci != null && fci.getLabel() != null) { - fci.getLabel().setEnabled(child.isEnabledWithParent()); - } - } - - @Override - public void applyPermission(UiPermissionDescriptor permissionDescriptor) { - checkNotNullArgument(permissionDescriptor); - - final String subComponentId = permissionDescriptor.getSubComponentId(); - final UiPermissionValue permissionValue = permissionDescriptor.getPermissionValue(); - final String screenId = permissionDescriptor.getScreenId(); - - if (subComponentId != null) { - final FieldGroup.FieldConfig field = getField(subComponentId); - if (field != null) { - if (permissionValue == UiPermissionValue.HIDE) { - field.setVisible(false); - } else if (permissionValue == UiPermissionValue.READ_ONLY) { - field.setEditable(false); - } - } else { - log.info("Couldn't find suitable component {} in window {} for UI security rule", subComponentId, screenId); - } - } else { - final String actionHolderComponentId = permissionDescriptor.getActionHolderComponentId(); - FieldConfig fieldConfig = getField(actionHolderComponentId); - if (fieldConfig == null - || fieldConfig.getComponent() == null - || !((fieldConfig.getComponent() instanceof Component.SecuredActionsHolder))) { - log.info("Couldn't find suitable component {} in window {} for UI security rule", actionHolderComponentId, screenId); - return; - } - - Component fieldComponent = fieldConfig.getComponent(); - String actionId = permissionDescriptor.getActionId(); - ActionsPermissions permissions = ((SecuredActionsHolder) fieldComponent).getActionsPermissions(); - if (permissionValue == UiPermissionValue.HIDE) { - permissions.addHiddenActionPermission(actionId); - } else if (permissionValue == UiPermissionValue.READ_ONLY) { - permissions.addDisabledActionPermission(actionId); - } - } - } - - @Override - public void addEditableChangeListener(EditableChangeListener listener) { - checkNotNullArgument(listener); - - if (!editableChangeListeners.contains(listener)) { - editableChangeListeners.add(listener); - } - } - - @Override - public void removeEditableChangeListener(EditableChangeListener listener) { - checkNotNullArgument(listener); - - editableChangeListeners.remove(listener); - } - - public class FieldConfigImpl implements FieldConfig { - protected String id; - protected Element xmlDescriptor; - protected int column; - - protected Component component; - protected DesktopAbstractComponent composition; - protected JLabel label = new JLabel(); - protected ToolTipButton toolTipButton; - - protected boolean managed = false; - - protected String targetWidth; - protected String targetStylename; - protected Datasource targetDatasource; - protected Boolean targetRequired; - protected Boolean targetEditable; - protected Boolean targetEnabled; - protected Boolean targetVisible; - protected String targetProperty; - protected Integer targetTabIndex; - protected String targetRequiredMessage; - protected CollectionDatasource targetOptionsDatasource; - protected String targetCaption; - protected String targetDescription; - protected Formatter targetFormatter; - protected boolean isTargetCustom; - - protected List targetValidators = new ArrayList<>(0); - protected FieldAttachMode attachMode = FieldAttachMode.APPLY_DEFAULTS; - - public FieldConfigImpl(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - @Override - public boolean isBound() { - return component != null; - } - - public FieldGroup getOwner() { - return DesktopFieldGroup.this; - } - - @Override - public String getWidth() { - if (composition != null && isWrapped()) { - return ComponentsHelper.getComponentWidth(composition); - } - if (component != null) { - return ComponentsHelper.getComponentWidth(component); - } - return targetWidth; - } - - @Override - public void setWidth(String width) { - if (composition != null && isWrapped()) { - composition.setWidth(width); - } else if (component != null) { - component.setWidth(width); - } else { - targetWidth = width; - } - } - - @Override - public String getStyleName() { - if (component != null) { - return component.getStyleName(); - } - return targetStylename; - } - - @Override - public void setStyleName(String stylename) { - if (component != null) { - component.setStyleName(stylename); - - if (composition != null && isWrapped()) { - composition.setStyleName(stylename); - } - } else { - this.targetStylename = stylename; - } - } - - protected boolean isWrapped() { - return component != null && !(component instanceof Field); - } - - @Override - public Datasource getTargetDatasource() { - if (component instanceof DatasourceComponent) { - return ((DatasourceComponent) component).getDatasource(); - } - if (targetDatasource != null) { - return targetDatasource; - } - return DesktopFieldGroup.this.datasource; - } - - @Override - public Datasource getDatasource() { - if (component instanceof DatasourceComponent) { - return ((DatasourceComponent) component).getDatasource(); - } - - return targetDatasource; - } - - @Override - public void setDatasource(Datasource datasource) { - checkState(this.component == null, "FieldConfig is already bound to component"); - - this.targetDatasource = datasource; - } - - @Override - public Boolean isRequired() { - if (component instanceof Field) { - return ((Field) component).isRequired(); - } - return targetRequired; - } - - @Override - public void setRequired(Boolean required) { - if (component instanceof Field) { - checkNotNullArgument(required, "Unable to reset required flag for the bound FieldConfig"); - - ((Field) component).setRequired(required); - } else { - this.targetRequired = required; - } - } - - @Override - public Boolean isEditable() { - if (component instanceof Editable) { - return ((Field) component).isEditable(); - } - return targetEditable; - } - - @Override - public void setEditable(Boolean editable) { - if (component instanceof Editable) { - checkNotNullArgument(editable, "Unable to reset editable flag for the bound FieldConfig"); - - ((Editable) component).setEditable(editable); - } else { - this.targetEditable = editable; - } - } - - @Override - public Boolean isEnabled() { - if (component != null) { - return component.isEnabled(); - } - return targetEnabled; - } - - @Override - public void setEnabled(Boolean enabled) { - if (component != null) { - checkNotNullArgument(enabled, "Unable to reset enabled flag for the bound FieldConfig"); - - component.setEnabled(enabled); - - if (composition != null && isWrapped()) { - composition.setEnabled(enabled); - } - } else { - this.targetEnabled = enabled; - } - } - - @Override - public Boolean isVisible() { - if (component != null) { - return component.isVisible(); - } - return targetVisible; - } - - @Override - public void setVisible(Boolean visible) { - if (component != null) { - checkNotNullArgument(visible, "Unable to reset visible flag for the bound FieldConfig"); - - component.setVisible(visible); - - if (composition != null && isWrapped()) { - composition.setVisible(visible); - } - } else { - this.targetVisible = visible; - } - } - - @Override - public String getProperty() { - if (component instanceof DatasourceComponent) { - MetaPropertyPath metaPropertyPath = ((DatasourceComponent) component).getMetaPropertyPath(); - return metaPropertyPath != null ? metaPropertyPath.toString() : null; - } - return targetProperty; - } - - @Override - public void setProperty(String property) { - checkState(this.component == null, "Unable to change property for bound FieldConfig"); - - this.targetProperty = property; - } - - @Override - public Integer getTabIndex() { - return targetTabIndex; - } - - @Override - public void setTabIndex(Integer tabIndex) { - if (component instanceof Focusable) { - checkNotNullArgument(tabIndex, "Unable to reset tabIndex for the bound FieldConfig"); - - ((Focusable) component).setTabIndex(tabIndex); - } else { - this.targetTabIndex = tabIndex; - } - } - - @Override - public String getRequiredError() { - return getRequiredMessage(); - } - - @Override - public void setRequiredError(String requiredError) { - setRequiredMessage(requiredError); - } - - @Override - public boolean isCustom() { - return isTargetCustom; - } - - @Override - public void setCustom(boolean custom) { - checkState(this.component == null, "Unable to change custom flag for bound FieldConfig"); - - this.isTargetCustom = custom; - } - - @Override - public String getRequiredMessage() { - if (component instanceof Field) { - return ((Field) component).getRequiredMessage(); - } - return targetRequiredMessage; - } - - @Override - public void setRequiredMessage(String requiredMessage) { - if (component instanceof Field) { - ((Field) component).setRequiredMessage(requiredMessage); - } else { - this.targetRequiredMessage = requiredMessage; - } - } - - @Nullable - @Override - public Component getComponent() { - return component; - } - - @Override - public Component getComponentNN() { - if (component == null) { - throw new IllegalStateException("FieldConfig is not bound to a Component"); - } - return component; - } - - @Override - public void setComponent(Component component) { - checkState(this.component == null, "Unable to change component for bound FieldConfig"); - - this.component = component; - - if (managed && component != null) { - managedFieldComponentAssigned(this, FieldAttachMode.APPLY_DEFAULTS); - } - } - - @Override - public void setComponent(Component component, FieldAttachMode mode) { - checkState(this.component == null, "Unable to change component for bound FieldConfig"); - - this.attachMode = mode; - this.component = component; - - if (managed && component != null) { - managedFieldComponentAssigned(this, mode); - } - } - - public void assignComponent(Component component) { - checkState(this.component == null, "Unable to change component for bound FieldConfig"); - - this.component = component; - } - - public void setAttachMode(FieldAttachMode attachMode) { - this.attachMode = attachMode; - } - - @Override - public void addValidator(Field.Validator validator) { - if (component instanceof Field) { - ((Field) component).addValidator(validator); - } else { - if (!targetValidators.contains(validator)) { - targetValidators.add(validator); - } - } - } - - @Override - public void removeValidator(Field.Validator validator) { - if (component instanceof Field) { - ((Field) component).removeValidator(validator); - } - targetValidators.remove(validator); - } - - @Override - public void setOptionsDatasource(CollectionDatasource optionsDatasource) { - if (component instanceof OptionsField) { - ((OptionsField) component).setOptionsDatasource(optionsDatasource); - } else { - this.targetOptionsDatasource = optionsDatasource; - } - } - - @Override - public CollectionDatasource getOptionsDatasource() { - if (component instanceof OptionsField) { - return ((OptionsField) component).getOptionsDatasource(); - } - return targetOptionsDatasource; - } - - @Override - public String getCaption() { - if (component instanceof Field) { - return ((Field) component).getCaption(); - } - if (composition != null && isWrapped()) { - return label.getText(); - } - return targetCaption; - } - - @Override - public void setCaption(String caption) { - if (component instanceof Field) { - ((Field) component).setCaption(caption); - } else if (composition != null && isWrapped()) { - label.setText(caption); - } else { - this.targetCaption = caption; - } - } - - @Override - public String getDescription() { - if (component instanceof Field) { - return ((Field) component).getDescription(); - } - return targetDescription; - } - - @Override - public void setDescription(String description) { - if (component instanceof Field) { - ((Field) component).setDescription(description); - } else { - this.targetDescription = description; - } - } - - @Override - public Formatter getFormatter() { - if (component instanceof HasFormatter) { - return ((HasFormatter) component).getFormatter(); - } - return targetFormatter; - } - - @Override - public void setFormatter(Formatter formatter) { - if (component instanceof HasFormatter) { - ((HasFormatter) component).setFormatter(formatter); - } else { - this.targetFormatter = formatter; - } - } - - @Override - public Element getXmlDescriptor() { - return xmlDescriptor; - } - - @Override - public void setXmlDescriptor(Element element) { - this.xmlDescriptor = element; - } - - public int getColumn() { - return column; - } - - public void setColumn(int column) { - this.column = column; - } - - @Nullable - public DesktopAbstractComponent getComposition() { - return composition; - } - - public DesktopAbstractComponent getCompositionNN() { - if (composition == null) { - throw new IllegalStateException("FieldConfig is not bound to a Component"); - } - return composition; - } - - public void setComposition(DesktopAbstractComponent composition) { - checkState(this.composition == null, "Unable to change composition for bound FieldConfig"); - - this.composition = composition; - - if (isWrapped()) { - if (targetCaption != null) { - label.setText(targetCaption); - } else { - label.setText(composition.getCaption()); - } - } - } - - public boolean isManaged() { - return managed; - } - - public void setManaged(boolean managed) { - this.managed = managed; - } - - public String getTargetWidth() { - return targetWidth; - } - - public void setTargetWidth(String targetWidth) { - this.targetWidth = targetWidth; - } - - public String getTargetStylename() { - return targetStylename; - } - - public void setTargetStylename(String targetStylename) { - this.targetStylename = targetStylename; - } - - public void setTargetDatasource(Datasource targetDatasource) { - this.targetDatasource = targetDatasource; - } - - public Boolean getTargetRequired() { - return targetRequired; - } - - public void setTargetRequired(Boolean targetRequired) { - this.targetRequired = targetRequired; - } - - public Boolean getTargetEditable() { - return targetEditable; - } - - public void setTargetEditable(Boolean targetEditable) { - this.targetEditable = targetEditable; - } - - public Boolean getTargetEnabled() { - return targetEnabled; - } - - public void setTargetEnabled(Boolean targetEnabled) { - this.targetEnabled = targetEnabled; - } - - public Boolean getTargetVisible() { - return targetVisible; - } - - public void setTargetVisible(Boolean targetVisible) { - this.targetVisible = targetVisible; - } - - public String getTargetProperty() { - return targetProperty; - } - - public void setTargetProperty(String targetProperty) { - this.targetProperty = targetProperty; - } - - public Integer getTargetTabIndex() { - return targetTabIndex; - } - - public void setTargetTabIndex(Integer targetTabIndex) { - this.targetTabIndex = targetTabIndex; - } - - public String getTargetRequiredMessage() { - return targetRequiredMessage; - } - - public void setTargetRequiredMessage(String targetRequiredMessage) { - this.targetRequiredMessage = targetRequiredMessage; - } - - public CollectionDatasource getTargetOptionsDatasource() { - return targetOptionsDatasource; - } - - public void setTargetOptionsDatasource(CollectionDatasource targetOptionsDatasource) { - this.targetOptionsDatasource = targetOptionsDatasource; - } - - public String getTargetCaption() { - return targetCaption; - } - - public void setTargetCaption(String targetCaption) { - this.targetCaption = targetCaption; - } - - public String getTargetDescription() { - return targetDescription; - } - - public void setTargetDescription(String targetDescription) { - this.targetDescription = targetDescription; - } - - public Formatter getTargetFormatter() { - return targetFormatter; - } - - public void setTargetFormatter(Formatter targetFormatter) { - this.targetFormatter = targetFormatter; - } - - public List getTargetValidators() { - return targetValidators; - } - - public void setTargetValidators(List targetValidators) { - this.targetValidators = targetValidators; - } - - public FieldAttachMode getAttachMode() { - return attachMode; - } - - public JLabel getLabel() { - return label; - } - - public void setLabel(JLabel label) { - this.label = label; - } - - public ToolTipButton getToolTipButton() { - return toolTipButton; - } - - public void setToolTipButton(ToolTipButton toolTipButton) { - this.toolTipButton = toolTipButton; - } - - @Override - public String toString() { - return "FieldConfig: " + id; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.google.common.base.Strings; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; +import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; +import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Formatter; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import net.miginfocom.layout.CC; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +public class DesktopFieldGroup extends DesktopAbstractComponent + implements FieldGroup, AutoExpanding, Component.UiPermissionAware { + + private final Logger log = LoggerFactory.getLogger(DesktopFieldGroup.class); + + public static final String DEFAULT_FIELD_WIDTH = "200px"; + + protected String description; + + protected MigLayout layout; + protected Datasource datasource; + protected CollapsiblePanel collapsiblePanel; + + protected int rows = 0; + protected int cols = 1; + + protected boolean editable = true; + protected boolean borderVisible = false; + + protected FieldCaptionAlignment captionAlignment; + + protected Map fields = new HashMap<>(); + protected List> columnFieldMapping = new ArrayList<>(); + { + columnFieldMapping.add(new ArrayList<>()); + } + + protected Map columnFieldCaptionWidth = null; + protected int fieldCaptionWidth = -1; + + protected boolean requestUpdateCaptionWidth = false; + + protected List editableChangeListeners = new ArrayList<>(); + + protected FieldGroupFieldFactory fieldFactory; + + public DesktopFieldGroup() { + LC lc = new LC(); + lc.hideMode(3); // Invisible components will not participate in the layout at all and it will for instance not take up a grid cell. + lc.insets("0 0 0 0"); + if (LayoutAdapter.isDebug()) { + lc.debug(1000); + } + + layout = new MigLayout(lc); + impl = new JPanel(layout); + assignClassDebugProperty(impl); + collapsiblePanel = new CollapsiblePanel(super.getComposition()); + assignClassDebugProperty(collapsiblePanel); + collapsiblePanel.setBorderVisible(false); + + setWidth(Component.AUTO_SIZE); + + fieldFactory = AppBeans.get(FieldGroupFieldFactory.NAME); + } + + /** + * @return flat list of column fields + */ + protected List getColumnOrderedFields() { + return columnFieldMapping.stream() + .flatMap(List::stream) + .collect(Collectors.toList()); + } + + @Override + public FieldConfig createField(String id) { + return new FieldConfigImpl(id); + } + + @Override + public List getFields() { + return getColumnOrderedFields(); + } + + @Override + public List getFields(int column) { + return Collections.unmodifiableList(columnFieldMapping.get(column)); + } + + @Override + public FieldConfig getField(int column, int row) { + return columnFieldMapping.get(column).get(row); + } + + @Override + public FieldConfig getField(String fieldId) { + for (final Map.Entry entry : fields.entrySet()) { + if (entry.getKey().equals(fieldId)) { + return entry.getValue(); + } + } + return null; + } + + @Override + public FieldConfig getFieldNN(String fieldId) { + FieldConfig fieldConfig = fields.get(fieldId); + if (fieldConfig == null) { + throw new IllegalArgumentException("Unable to find field with id " + fieldId); + } + + return fieldConfig; + } + + @Override + public void add(Component childComponent) { + throw new UnsupportedOperationException("Add component is not supported by FieldGroup component"); + } + + @Override + public void remove(Component childComponent) { + throw new UnsupportedOperationException("Remove component is not supported by FieldGroup component"); + } + + @Override + public void removeAll() { + throw new UnsupportedOperationException("Remove all components are not supported by FieldGroup component"); + } + + @Nullable + @Override + public Component getOwnComponent(String id) { + FieldConfig fieldConfig = getField(id); + if (fieldConfig != null && fieldConfig.isBound()) { + return fieldConfig.getComponent(); + } + return null; + } + + @Nullable + @Override + public Component getComponent(String id) { + return ComponentsHelper.getComponent(this, id); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public List getOwnComponents() { + return getColumnOrderedFields().stream() + .filter(FieldConfig::isBound) + .map(FieldConfig::getComponent) + .collect(Collectors.toList()); + } + + @Override + public void addField(FieldConfig field) { + addField(field, 0); + } + + @Override + public void addField(FieldConfig fc, int colIndex) { + checkArgument(!fields.containsKey(fc.getId()), "Field is already registered"); + checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field does not belong to this FieldGroup"); + + if (colIndex < 0 || colIndex >= getColumns()) { + throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", + colIndex, getColumns())); + } + + addFieldInternal(fc, colIndex, -1); + } + + @Override + public void addField(FieldConfig fc, int colIndex, int rowIndex) { + checkArgument(!fields.containsKey(fc.getId()), "Field is already registered"); + checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field does not belong to this FieldGroup"); + + if (colIndex < 0 || colIndex >= getColumns()) { + throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", + colIndex, getColumns())); + } + List colFields = columnFieldMapping.get(colIndex); + if (rowIndex < 0 || rowIndex > colFields.size()) { + throw new IllegalArgumentException(String.format("Illegal row number %s, available amount of rows is %s", + rowIndex, getRows())); + } + + addFieldInternal(fc, colIndex, rowIndex); + } + + protected void addFieldInternal(FieldConfig fc, int colIndex, int rowIndex) { + List colFields = columnFieldMapping.get(colIndex); + if (rowIndex == -1) { + rowIndex = colFields.size(); + } + + fields.put(fc.getId(), fc); + colFields.add(rowIndex, fc); + + FieldConfigImpl fci = (FieldConfigImpl) fc; + + fci.setColumn(colIndex); + fci.setManaged(true); + + if (fc.getComponent() != null) { + managedFieldComponentAssigned(fci, fci.getAttachMode()); + + impl.revalidate(); + impl.repaint(); + } + } + + @Override + public void removeField(String fieldId) { + removeField(getFieldNN(fieldId)); + } + + @Override + public void removeField(FieldConfig fc) { + checkArgument(this == ((FieldConfigImpl) fc).getOwner(), "Field is not belong to this FieldGroup"); + + if (fields.values().contains(fc)) { + int colIndex = ((FieldConfigImpl) fc).getColumn(); + columnFieldMapping.get(colIndex).remove(fc); + fields.remove(fc.getId()); + + boolean wasBound = fc.isBound(); + if (fc.isBound()) { + FieldConfigImpl fci = (FieldConfigImpl) fc; + + impl.remove(fci.getCompositionNN().getComposition()); + if (fci.getLabel() != null) { + impl.remove(fci.getLabel()); + } + if (fci.getToolTipButton() != null) { + impl.remove(fci.getToolTipButton()); + } + + reattachColumnFields(colIndex); + + this.rows = detectRowsCount(); + } + + ((FieldConfigImpl) fc).setManaged(false); + + if (fc.getComponent() != null) { + fc.getComponent().setParent(null); + } + + if (wasBound) { + impl.revalidate(); + impl.repaint(); + } + } + } + + @Override + public void requestFocus() { + for (FieldConfig fc : getColumnOrderedFields()) { + Component component = fc.getComponent(); + if (component != null + && component.isEnabled() + && component.isVisible() + && component instanceof Focusable + && ((Focusable) component).isFocusable()) { + + component.requestFocus(); + break; + } + } + } + + @Override + public void requestFocus(String fieldId) { + FieldConfig field = getFieldNN(fieldId); + Component componentField = field.getComponentNN(); + componentField.requestFocus(); + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public void setDatasource(final Datasource datasource) { + if (this.datasource != null) { + throw new UnsupportedOperationException("Changing datasource is not supported by the FieldGroup component"); + } + + this.datasource = datasource; + + assignAutoDebugId(); + } + + @Override + public void bind() { + bindDeclarativeFieldConfigs(); + } + + protected void bindDeclarativeFieldConfigs() { + List reattachColumns = new ArrayList<>(); + + for (FieldConfig fc : getColumnOrderedFields()) { + if (!fc.isCustom() && !fc.isBound()) { + FieldConfigImpl fci = (FieldConfigImpl) fc; + + Datasource targetDs = fc.getTargetDatasource(); + if (targetDs == null) { + throw new IllegalStateException(String.format("Unable to get datasource for field '%s'", id)); + } + + FieldGroupFieldFactory.GeneratedField generatedField = fieldFactory.createField(fc); + Component fieldComponent = generatedField.getComponent(); + + fci.assignComponent(fieldComponent); + fci.setAttachMode(generatedField.getAttachMode()); + + setupFieldComponent(fci); + + DesktopAbstractComponent fieldImpl = (DesktopAbstractComponent) fieldComponent; + fci.setComposition(fieldImpl); + + if (fci.getDescription() != null) { + ToolTipButton tooltipBtn = new ToolTipButton(); + tooltipBtn.setVisible(fieldComponent.isVisible()); + tooltipBtn.setToolTipText(fci.getDescription()); + fci.setToolTipButton(new ToolTipButton()); + } else { + fci.setToolTipButton(null); + } + + assignTypicalAttributes(fieldComponent); + + if (generatedField.getAttachMode() == FieldAttachMode.APPLY_DEFAULTS) { + applyFieldDefaults(fci); + } + + int columnIndex = fci.getColumn(); + if (!reattachColumns.contains(columnIndex)) { + reattachColumns.add(columnIndex); + } + } + } + + if (!reattachColumns.isEmpty()) { + this.rows = detectRowsCount(); + + for (Integer reattachColumnIndex : reattachColumns) { + reattachColumnFields(reattachColumnIndex); + } + } + + impl.revalidate(); + impl.repaint(); + } + + protected void setupFieldComponent(FieldConfig fieldConfig) { + Component fieldComponent = fieldConfig.getComponent(); + + if (fieldComponent instanceof DesktopCheckBox) { + fieldComponent.setAlignment(Alignment.MIDDLE_LEFT); + } + } + + protected void reattachColumnFields(int colIndex) { + fields.values().stream() + .filter(FieldConfig::isBound) + .map(fieldConfig -> ((FieldConfigImpl) fieldConfig)) + .filter(fci -> fci.getColumn() == colIndex) + .forEach(fci -> { + impl.remove(fci.getCompositionNN().getComposition()); + if (fci.getLabel() != null) { + impl.remove(fci.getLabel()); + } + if (fci.getToolTipButton() != null) { + impl.remove(fci.getToolTipButton()); + } + }); + + List columnFCs = columnFieldMapping.get(colIndex); + int insertRowIndex = 0; + for (FieldConfig fc : columnFCs) { + if (fc.isBound()) { + FieldConfigImpl fci = (FieldConfigImpl) fc; + + Component fieldComponent = fci.getComponentNN(); + JComponent composition = fieldComponent.unwrapComposition(JComponent.class); + + JLabel label = fci.getLabel(); + if (label != null) { + int preferredCaptionWidth = getPreferredCaptionWidth(colIndex); + if (preferredCaptionWidth > 0) { + label.setPreferredSize(new Dimension(preferredCaptionWidth, 25)); + label.setMaximumSize(new Dimension(preferredCaptionWidth, 25)); + label.setMinimumSize(new Dimension(preferredCaptionWidth, 25)); + } else { + label.setPreferredSize(new Dimension(label.getPreferredSize().width, 25)); + } + label.setVisible(fieldComponent.isVisible()); + + CC labelCc = new CC(); + MigLayoutHelper.applyAlignment(labelCc, Alignment.TOP_LEFT); + + impl.add(label, labelCc.cell(colIndex * 3, insertRowIndex, 1, 1)); + } + + if (Strings.isNullOrEmpty(fci.getDescription())) { + fci.setToolTipButton(null); + } else if (fci.getToolTipButton() == null) { + ToolTipButton toolTipButton = new ToolTipButton(); + toolTipButton.setToolTipText(fci.getDescription()); + toolTipButton.setVisible(fieldComponent.isVisible()); + fci.setToolTipButton(toolTipButton); + } + + ToolTipButton toolTipButton = fci.getToolTipButton(); + if (toolTipButton != null) { + toolTipButton.setVisible(fieldComponent.isVisible()); + DesktopToolTipManager.getInstance().registerTooltip(toolTipButton); + impl.add(toolTipButton, new CC().cell(colIndex * 3 + 2, insertRowIndex, 1, 1).alignY("top")); + } + + CC cell = new CC().cell(colIndex * 3 + 1, insertRowIndex, 1, 1); + + MigLayoutHelper.applyWidth(cell, (int) fieldComponent.getWidth(), fieldComponent.getWidthUnits(), false); + MigLayoutHelper.applyHeight(cell, (int) fieldComponent.getHeight(), fieldComponent.getHeightUnits(), false); + MigLayoutHelper.applyAlignment(cell, fieldComponent.getAlignment()); + + composition.putClientProperty(getSwingPropertyId(), fci.getId()); + impl.add(composition, cell); + + insertRowIndex++; + } + } + + impl.validate(); + impl.repaint(); + } + + protected int detectRowsCount() { + int rowsCount = 0; + for (List fields : columnFieldMapping) { + long boundCount = fields.stream() + .filter(FieldConfig::isBound) + .count(); + + rowsCount = (int) Math.max(rowsCount, boundCount); + } + return Math.max(rowsCount, 1); + } + + protected void managedFieldComponentAssigned(FieldConfigImpl fci, FieldAttachMode mode) { + DesktopAbstractComponent fieldImpl = (DesktopAbstractComponent) fci.getComponentNN(); + fci.setComposition(fieldImpl); + + if (fci.getDescription() != null) { + ToolTipButton tooltipBtn = new ToolTipButton(); + tooltipBtn.setVisible(fci.getComponentNN().isVisible()); + tooltipBtn.setToolTipText(fci.getDescription()); + fci.setToolTipButton(new ToolTipButton()); + } else { + fci.setToolTipButton(null); + } + + if (fieldImpl.getCaption() != null) { + fci.getLabel().setText(fieldImpl.getCaption()); + } + + assignTypicalAttributes(fci.getComponentNN()); + + if (mode == FieldAttachMode.APPLY_DEFAULTS) { + applyFieldDefaults(fci); + } + + this.rows = detectRowsCount(); + + reattachColumnFields(fci.getColumn()); + } + + protected void applyFieldDefaults(FieldConfigImpl fci) { + Component fieldComponent = fci.getComponentNN(); + + if (fieldComponent instanceof Field) { + Field cubaField = (Field) fieldComponent; + + if (fci.getTargetCaption() != null) { + cubaField.setCaption(fci.getTargetCaption()); + } + if (fci.getTargetDescription() != null) { + cubaField.setDescription(fci.getTargetDescription()); + } + if (fci.getTargetRequired() != null) { + cubaField.setRequired(fci.getTargetRequired()); + } + if (fci.getTargetRequiredMessage() != null) { + cubaField.setRequiredMessage(fci.getTargetRequiredMessage()); + } + if (fci.getTargetEditable() != null) { + cubaField.setEditable(fci.getTargetEditable()); + } + if (fci.getTargetVisible() != null) { + cubaField.setVisible(fci.getTargetVisible()); + } + if (cubaField instanceof Component.Focusable && fci.getTargetTabIndex() != null) { + ((Component.Focusable) cubaField).setTabIndex(fci.getTargetTabIndex()); + } + for (Field.Validator validator : fci.getTargetValidators()) { + cubaField.addValidator(validator); + } + + if (fci.getTargetWidth() != null) { + fieldComponent.setWidth(fci.getTargetWidth()); + } else { + fieldComponent.setWidth(DEFAULT_FIELD_WIDTH); + } + } else { + DesktopAbstractComponent composition = fci.getCompositionNN(); + if (fci.getTargetCaption() != null) { + fci.getLabel().setText(fci.getTargetCaption()); + } + if (fci.getTargetVisible() != null) { + composition.setVisible(fci.getTargetVisible()); + } + if (fci.getTargetWidth() != null) { + composition.setWidth(fci.getTargetWidth()); + } else { + composition.setWidth(DEFAULT_FIELD_WIDTH); + } + } + + if (fieldComponent instanceof Component.HasFormatter && fci.getTargetFormatter() != null) { + ((Component.HasFormatter) fieldComponent).setFormatter(fci.getTargetFormatter()); + } + + if (StringUtils.isNotEmpty(fci.getTargetStylename())) { + fieldComponent.setStyleName(fci.getTargetStylename()); + } + + App app = App.getInstance(); + if (app != null && app.isTestMode()) { + fci.getCompositionNN().getComposition().setName(fci.getId()); + } + } + + protected void doSetParentEnabled(FieldConfig fc, boolean enabled) { + if (fc.getComponent() != null) { + Component component = fc.getComponent(); + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(enabled); + } + + FieldConfigImpl fci = (FieldConfigImpl) fc; + if (fci.getLabel() != null) { + fci.getLabel().setEnabled(enabled); + } + } + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + for (FieldConfig field : fields.values()) { + doSetParentEnabled(field, parentEnabled && enabled); + } + } + + @Override + public boolean isBorderVisible() { + return borderVisible; + } + + @Override + public void setBorderVisible(boolean borderVisible) { + this.borderVisible = borderVisible; + collapsiblePanel.setBorderVisible(borderVisible); + } + + @Override + public FieldCaptionAlignment getCaptionAlignment() { + return captionAlignment; + } + + @Override + public void setCaptionAlignment(FieldCaptionAlignment captionAlignment) { + this.captionAlignment = captionAlignment; + + log.warn("setCaptionAlignment not implemented for desktop"); + } + + @Override + public int getFieldCaptionWidth() { + return fieldCaptionWidth; + } + + @Override + public void setFieldCaptionWidth(int fixedCaptionWidth) { + this.fieldCaptionWidth = fixedCaptionWidth; + + updateCaptionWidths(); + } + + @Override + public int getFieldCaptionWidth(int column) { + if (columnFieldCaptionWidth != null) { + Integer value = columnFieldCaptionWidth.get(column); + return value != null ? value : -1; + } + return -1; + } + + @Override + public void setFieldCaptionWidth(int column, int width) { + if (columnFieldCaptionWidth == null) { + columnFieldCaptionWidth = new HashMap<>(); + } + columnFieldCaptionWidth.put(column, width); + + updateCaptionWidths(); + } + + protected void updateCaptionWidths() { + if (!requestUpdateCaptionWidth) { + SwingUtilities.invokeLater(() -> { + requestUpdateCaptionWidth = false; + + for (FieldConfig fieldConfig : fields.values()) { + JLabel label = ((FieldConfigImpl) fieldConfig).getLabel(); + + if (label != null) { + int col = ((FieldConfigImpl) fieldConfig).getColumn(); + int preferredCaptionWidth = getPreferredCaptionWidth(col); + + if (preferredCaptionWidth > 0) { + label.setPreferredSize(new Dimension(preferredCaptionWidth, 25)); + label.setMaximumSize(new Dimension(preferredCaptionWidth, 25)); + label.setMinimumSize(new Dimension(preferredCaptionWidth, 25)); + } + } + } + }); + requestUpdateCaptionWidth = true; + } + } + + protected int getPreferredCaptionWidth(int col) { + int preferredCaptionWidth = -1; + if (fieldCaptionWidth > 0) { + preferredCaptionWidth = fieldCaptionWidth; + } + if (columnFieldCaptionWidth != null + && columnFieldCaptionWidth.containsKey(col)) { + preferredCaptionWidth = columnFieldCaptionWidth.get(col); + } + return preferredCaptionWidth; + } + + @Override + public int getColumns() { + return cols; + } + + public int getRows() { + return rows; + } + + public DesktopAbstractComponent getCellComponent(int colIndex, int rowIndex) { + if (colIndex < 0 || colIndex >= getColumns()) { + throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", + colIndex, getColumns())); + } + List colFields = columnFieldMapping.get(colIndex); + if (rowIndex < 0 || rowIndex > colFields.size()) { + throw new IllegalArgumentException(String.format("Illegal column number %s, available amount of columns is %s", + colIndex, getColumns())); + } + + for (FieldConfig fieldConfig : fields.values()) { + DesktopAbstractComponent composition = ((FieldConfigImpl) fieldConfig).getComposition(); + if (composition != null) { + JComponent jComponent = composition.getComposition(); + Object componentConstraints = layout.getComponentConstraints(jComponent); + if (componentConstraints instanceof CC) { + CC cc = (CC) componentConstraints; + if (cc.getCellY() == rowIndex) { + int ccColIndex = (cc.getCellX() - 1) / 3; + if (colIndex == ccColIndex) { + return composition; + } + } + } + } + } + return null; + } + + @Override + public void setColumns(int columns) { + if (this.cols != columns) { + this.cols = columns; + + List> oldColumnFields = this.columnFieldMapping; + this.columnFieldMapping = new ArrayList<>(); + for (int i = 0; i < columns; i++) { + if (i < oldColumnFields.size()) { + columnFieldMapping.add(oldColumnFields.get(i)); + } else { + columnFieldMapping.add(new ArrayList<>()); + } + } + } + } + + @Override + public float getColumnExpandRatio(int col) { + return 0; + } + + @Override + public void setColumnExpandRatio(int col, float ratio) { + } + + @Override + public FieldGroupFieldFactory getFieldFactory() { + return fieldFactory; + } + + @Override + public void setFieldFactory(FieldGroupFieldFactory fieldFactory) { + this.fieldFactory = fieldFactory; + } + + @Override + public void addCustomField(String fieldId, CustomFieldGenerator fieldGenerator) { + FieldConfig field = getField(fieldId); + if (field == null) { + throw new IllegalArgumentException(String.format("Field '%s' doesn't exist", fieldId)); + } + addCustomField(field, fieldGenerator); + } + + @Override + public void addCustomField(FieldConfig fc, CustomFieldGenerator fieldGenerator) { + if (!fc.isCustom()) { + throw new IllegalStateException(String.format("Field '%s' must be defined as custom", fc.getId())); + } + + FieldConfigImpl fci = (FieldConfigImpl) fc; + + Component fieldComponent = fieldGenerator.generateField(fc.getTargetDatasource(), fci.getTargetProperty()); + fc.setComponent(fieldComponent); + } + + @Override + public void setId(String id) { + super.setId(id); + + if (id != null && App.getInstance().isTestMode()) { + for (FieldConfig fc : fields.values()) { + Component fieldComponent = fc.getComponent(); + if (fieldComponent != null) { + JComponent jComponent = DesktopComponentsHelper.getComposition(fieldComponent); + if (jComponent != null) { + jComponent.setName(fc.getId()); + } + } + } + } + } + + protected void assignTypicalAttributes(Component c) { + if (c instanceof BelongToFrame) { + BelongToFrame belongToFrame = (BelongToFrame) c; + if (belongToFrame.getFrame() == null) { + belongToFrame.setFrame(getFrame()); + } + } + c.setParent(this); + } + + @Override + public boolean isEditable() { + return editable; + } + + @Override + public void setEditable(boolean editable) { + if (editable != isEditable()) { + this.editable = editable; + + EditableChangeEvent event = new EditableChangeEvent(this); + for (EditableChangeListener listener : new ArrayList<>(editableChangeListeners)) { + listener.editableChanged(event); + } + } + } + + @Override + public String getCaption() { + return collapsiblePanel.getCaption(); + } + + @Override + public void setCaption(String caption) { + collapsiblePanel.setCaption(caption); + } + + @Override + public String getDescription() { + return description; + } + + @Override + public void setDescription(String description) { + this.description = description; + } + + @Override + public JComponent getComposition() { + return collapsiblePanel; + } + + @Override + public boolean expandsWidth() { + return true; + } + + @Override + public boolean expandsHeight() { + return false; + } + + @Override + public boolean isValid() { + try { + validate(); + return true; + } catch (ValidationException e) { + return false; + } + } + + @Override + public void validate() throws ValidationException { + if (!isVisible() || !isEditableWithParent() || !isEnabled()) { + return; + } + + Map problemFields = null; // lazily initialized + + // validate column by column + List fieldsByColumns = getColumnOrderedFields(); + + for (FieldConfig fc : fieldsByColumns) { + Component fieldComponent = fc.getComponent(); + + // If has valid state + if ((fieldComponent instanceof Validatable) && + (fieldComponent instanceof Editable)) { + // If editable + try { + ((Validatable) fieldComponent).validate(); + } catch (ValidationException ex) { + if (problemFields == null) { + problemFields = new LinkedHashMap<>(); + } + problemFields.put((Validatable) fieldComponent, ex); + } + } + } + + if (problemFields != null && !problemFields.isEmpty()) { + FieldsValidationException validationException = new FieldsValidationException(); + validationException.setProblemFields(problemFields); + + throw validationException; + } + } + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { + return "fieldGroup_" + datasource.getId(); + } + + return getClass().getSimpleName(); + } + + public void updateCaptionVisibility(DesktopAbstractComponent child) { + FieldConfig field = fields.values().stream() + .filter(entry -> entry.getComponent() == child) + .findFirst() + .orElse(null); + + FieldConfigImpl fci = (FieldConfigImpl) field; + if (fci != null && fci.getLabel() != null) { + fci.getLabel().setVisible(child.isComponentVisible()); + } + } + + public void updateCaptionText(DesktopAbstractComponent child) { + FieldConfig field = fields.values().stream() + .filter(entry -> entry.getComponent() == child) + .findFirst() + .orElse(null); + + FieldConfigImpl fci = (FieldConfigImpl) field; + if (fci != null && fci.getLabel() != null) { + fci.getLabel().setText(child.getCaption()); + } + } + + public void updateChildEnabled(DesktopAbstractComponent child) { + FieldConfig field = fields.values().stream() + .filter(entry -> entry.getComponent() == child) + .findFirst() + .orElse(null); + + FieldConfigImpl fci = (FieldConfigImpl) field; + if (fci != null && fci.getLabel() != null) { + fci.getLabel().setEnabled(child.isEnabledWithParent()); + } + } + + @Override + public void applyPermission(UiPermissionDescriptor permissionDescriptor) { + checkNotNullArgument(permissionDescriptor); + + final String subComponentId = permissionDescriptor.getSubComponentId(); + final UiPermissionValue permissionValue = permissionDescriptor.getPermissionValue(); + final String screenId = permissionDescriptor.getScreenId(); + + if (subComponentId != null) { + final FieldGroup.FieldConfig field = getField(subComponentId); + if (field != null) { + if (permissionValue == UiPermissionValue.HIDE) { + field.setVisible(false); + } else if (permissionValue == UiPermissionValue.READ_ONLY) { + field.setEditable(false); + } + } else { + log.info("Couldn't find suitable component {} in window {} for UI security rule", subComponentId, screenId); + } + } else { + final String actionHolderComponentId = permissionDescriptor.getActionHolderComponentId(); + FieldConfig fieldConfig = getField(actionHolderComponentId); + if (fieldConfig == null + || fieldConfig.getComponent() == null + || !((fieldConfig.getComponent() instanceof Component.SecuredActionsHolder))) { + log.info("Couldn't find suitable component {} in window {} for UI security rule", actionHolderComponentId, screenId); + return; + } + + Component fieldComponent = fieldConfig.getComponent(); + String actionId = permissionDescriptor.getActionId(); + ActionsPermissions permissions = ((SecuredActionsHolder) fieldComponent).getActionsPermissions(); + if (permissionValue == UiPermissionValue.HIDE) { + permissions.addHiddenActionPermission(actionId); + } else if (permissionValue == UiPermissionValue.READ_ONLY) { + permissions.addDisabledActionPermission(actionId); + } + } + } + + @Override + public void addEditableChangeListener(EditableChangeListener listener) { + checkNotNullArgument(listener); + + if (!editableChangeListeners.contains(listener)) { + editableChangeListeners.add(listener); + } + } + + @Override + public void removeEditableChangeListener(EditableChangeListener listener) { + checkNotNullArgument(listener); + + editableChangeListeners.remove(listener); + } + + public class FieldConfigImpl implements FieldConfig { + protected String id; + protected Element xmlDescriptor; + protected int column; + + protected Component component; + protected DesktopAbstractComponent composition; + protected JLabel label = new JLabel(); + protected ToolTipButton toolTipButton; + + protected boolean managed = false; + + protected String targetWidth; + protected String targetStylename; + protected Datasource targetDatasource; + protected Boolean targetRequired; + protected Boolean targetEditable; + protected Boolean targetEnabled; + protected Boolean targetVisible; + protected String targetProperty; + protected Integer targetTabIndex; + protected String targetRequiredMessage; + protected CollectionDatasource targetOptionsDatasource; + protected String targetCaption; + protected String targetDescription; + protected Formatter targetFormatter; + protected boolean isTargetCustom; + + protected List targetValidators = new ArrayList<>(0); + protected FieldAttachMode attachMode = FieldAttachMode.APPLY_DEFAULTS; + + public FieldConfigImpl(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + @Override + public boolean isBound() { + return component != null; + } + + public FieldGroup getOwner() { + return DesktopFieldGroup.this; + } + + @Override + public String getWidth() { + if (composition != null && isWrapped()) { + return ComponentsHelper.getComponentWidth(composition); + } + if (component != null) { + return ComponentsHelper.getComponentWidth(component); + } + return targetWidth; + } + + @Override + public void setWidth(String width) { + if (composition != null && isWrapped()) { + composition.setWidth(width); + } else if (component != null) { + component.setWidth(width); + } else { + targetWidth = width; + } + } + + @Override + public String getStyleName() { + if (component != null) { + return component.getStyleName(); + } + return targetStylename; + } + + @Override + public void setStyleName(String stylename) { + if (component != null) { + component.setStyleName(stylename); + + if (composition != null && isWrapped()) { + composition.setStyleName(stylename); + } + } else { + this.targetStylename = stylename; + } + } + + protected boolean isWrapped() { + return component != null && !(component instanceof Field); + } + + @Override + public Datasource getTargetDatasource() { + if (component instanceof DatasourceComponent) { + return ((DatasourceComponent) component).getDatasource(); + } + if (targetDatasource != null) { + return targetDatasource; + } + return DesktopFieldGroup.this.datasource; + } + + @Override + public Datasource getDatasource() { + if (component instanceof DatasourceComponent) { + return ((DatasourceComponent) component).getDatasource(); + } + + return targetDatasource; + } + + @Override + public void setDatasource(Datasource datasource) { + checkState(this.component == null, "FieldConfig is already bound to component"); + + this.targetDatasource = datasource; + } + + @Override + public Boolean isRequired() { + if (component instanceof Field) { + return ((Field) component).isRequired(); + } + return targetRequired; + } + + @Override + public void setRequired(Boolean required) { + if (component instanceof Field) { + checkNotNullArgument(required, "Unable to reset required flag for the bound FieldConfig"); + + ((Field) component).setRequired(required); + } else { + this.targetRequired = required; + } + } + + @Override + public Boolean isEditable() { + if (component instanceof Editable) { + return ((Field) component).isEditable(); + } + return targetEditable; + } + + @Override + public void setEditable(Boolean editable) { + if (component instanceof Editable) { + checkNotNullArgument(editable, "Unable to reset editable flag for the bound FieldConfig"); + + ((Editable) component).setEditable(editable); + } else { + this.targetEditable = editable; + } + } + + @Override + public Boolean isEnabled() { + if (component != null) { + return component.isEnabled(); + } + return targetEnabled; + } + + @Override + public void setEnabled(Boolean enabled) { + if (component != null) { + checkNotNullArgument(enabled, "Unable to reset enabled flag for the bound FieldConfig"); + + component.setEnabled(enabled); + + if (composition != null && isWrapped()) { + composition.setEnabled(enabled); + } + } else { + this.targetEnabled = enabled; + } + } + + @Override + public Boolean isVisible() { + if (component != null) { + return component.isVisible(); + } + return targetVisible; + } + + @Override + public void setVisible(Boolean visible) { + if (component != null) { + checkNotNullArgument(visible, "Unable to reset visible flag for the bound FieldConfig"); + + component.setVisible(visible); + + if (composition != null && isWrapped()) { + composition.setVisible(visible); + } + } else { + this.targetVisible = visible; + } + } + + @Override + public String getProperty() { + if (component instanceof DatasourceComponent) { + MetaPropertyPath metaPropertyPath = ((DatasourceComponent) component).getMetaPropertyPath(); + return metaPropertyPath != null ? metaPropertyPath.toString() : null; + } + return targetProperty; + } + + @Override + public void setProperty(String property) { + checkState(this.component == null, "Unable to change property for bound FieldConfig"); + + this.targetProperty = property; + } + + @Override + public Integer getTabIndex() { + return targetTabIndex; + } + + @Override + public void setTabIndex(Integer tabIndex) { + if (component instanceof Focusable) { + checkNotNullArgument(tabIndex, "Unable to reset tabIndex for the bound FieldConfig"); + + ((Focusable) component).setTabIndex(tabIndex); + } else { + this.targetTabIndex = tabIndex; + } + } + + @Override + public String getRequiredError() { + return getRequiredMessage(); + } + + @Override + public void setRequiredError(String requiredError) { + setRequiredMessage(requiredError); + } + + @Override + public boolean isCustom() { + return isTargetCustom; + } + + @Override + public void setCustom(boolean custom) { + checkState(this.component == null, "Unable to change custom flag for bound FieldConfig"); + + this.isTargetCustom = custom; + } + + @Override + public String getRequiredMessage() { + if (component instanceof Field) { + return ((Field) component).getRequiredMessage(); + } + return targetRequiredMessage; + } + + @Override + public void setRequiredMessage(String requiredMessage) { + if (component instanceof Field) { + ((Field) component).setRequiredMessage(requiredMessage); + } else { + this.targetRequiredMessage = requiredMessage; + } + } + + @Nullable + @Override + public Component getComponent() { + return component; + } + + @Override + public Component getComponentNN() { + if (component == null) { + throw new IllegalStateException("FieldConfig is not bound to a Component"); + } + return component; + } + + @Override + public void setComponent(Component component) { + checkState(this.component == null, "Unable to change component for bound FieldConfig"); + + this.component = component; + + if (managed && component != null) { + managedFieldComponentAssigned(this, FieldAttachMode.APPLY_DEFAULTS); + } + } + + @Override + public void setComponent(Component component, FieldAttachMode mode) { + checkState(this.component == null, "Unable to change component for bound FieldConfig"); + + this.attachMode = mode; + this.component = component; + + if (managed && component != null) { + managedFieldComponentAssigned(this, mode); + } + } + + public void assignComponent(Component component) { + checkState(this.component == null, "Unable to change component for bound FieldConfig"); + + this.component = component; + } + + public void setAttachMode(FieldAttachMode attachMode) { + this.attachMode = attachMode; + } + + @Override + public void addValidator(Field.Validator validator) { + if (component instanceof Field) { + ((Field) component).addValidator(validator); + } else { + if (!targetValidators.contains(validator)) { + targetValidators.add(validator); + } + } + } + + @Override + public void removeValidator(Field.Validator validator) { + if (component instanceof Field) { + ((Field) component).removeValidator(validator); + } + targetValidators.remove(validator); + } + + @Override + public void setOptionsDatasource(CollectionDatasource optionsDatasource) { + if (component instanceof OptionsField) { + ((OptionsField) component).setOptionsDatasource(optionsDatasource); + } else { + this.targetOptionsDatasource = optionsDatasource; + } + } + + @Override + public CollectionDatasource getOptionsDatasource() { + if (component instanceof OptionsField) { + return ((OptionsField) component).getOptionsDatasource(); + } + return targetOptionsDatasource; + } + + @Override + public String getCaption() { + if (component instanceof Field) { + return ((Field) component).getCaption(); + } + if (composition != null && isWrapped()) { + return label.getText(); + } + return targetCaption; + } + + @Override + public void setCaption(String caption) { + if (component instanceof Field) { + ((Field) component).setCaption(caption); + } else if (composition != null && isWrapped()) { + label.setText(caption); + } else { + this.targetCaption = caption; + } + } + + @Override + public String getDescription() { + if (component instanceof Field) { + return ((Field) component).getDescription(); + } + return targetDescription; + } + + @Override + public void setDescription(String description) { + if (component instanceof Field) { + ((Field) component).setDescription(description); + } else { + this.targetDescription = description; + } + } + + @Override + public Formatter getFormatter() { + if (component instanceof HasFormatter) { + return ((HasFormatter) component).getFormatter(); + } + return targetFormatter; + } + + @Override + public void setFormatter(Formatter formatter) { + if (component instanceof HasFormatter) { + ((HasFormatter) component).setFormatter(formatter); + } else { + this.targetFormatter = formatter; + } + } + + @Override + public Element getXmlDescriptor() { + return xmlDescriptor; + } + + @Override + public void setXmlDescriptor(Element element) { + this.xmlDescriptor = element; + } + + public int getColumn() { + return column; + } + + public void setColumn(int column) { + this.column = column; + } + + @Nullable + public DesktopAbstractComponent getComposition() { + return composition; + } + + public DesktopAbstractComponent getCompositionNN() { + if (composition == null) { + throw new IllegalStateException("FieldConfig is not bound to a Component"); + } + return composition; + } + + public void setComposition(DesktopAbstractComponent composition) { + checkState(this.composition == null, "Unable to change composition for bound FieldConfig"); + + this.composition = composition; + + if (isWrapped()) { + if (targetCaption != null) { + label.setText(targetCaption); + } else { + label.setText(composition.getCaption()); + } + } + } + + public boolean isManaged() { + return managed; + } + + public void setManaged(boolean managed) { + this.managed = managed; + } + + public String getTargetWidth() { + return targetWidth; + } + + public void setTargetWidth(String targetWidth) { + this.targetWidth = targetWidth; + } + + public String getTargetStylename() { + return targetStylename; + } + + public void setTargetStylename(String targetStylename) { + this.targetStylename = targetStylename; + } + + public void setTargetDatasource(Datasource targetDatasource) { + this.targetDatasource = targetDatasource; + } + + public Boolean getTargetRequired() { + return targetRequired; + } + + public void setTargetRequired(Boolean targetRequired) { + this.targetRequired = targetRequired; + } + + public Boolean getTargetEditable() { + return targetEditable; + } + + public void setTargetEditable(Boolean targetEditable) { + this.targetEditable = targetEditable; + } + + public Boolean getTargetEnabled() { + return targetEnabled; + } + + public void setTargetEnabled(Boolean targetEnabled) { + this.targetEnabled = targetEnabled; + } + + public Boolean getTargetVisible() { + return targetVisible; + } + + public void setTargetVisible(Boolean targetVisible) { + this.targetVisible = targetVisible; + } + + public String getTargetProperty() { + return targetProperty; + } + + public void setTargetProperty(String targetProperty) { + this.targetProperty = targetProperty; + } + + public Integer getTargetTabIndex() { + return targetTabIndex; + } + + public void setTargetTabIndex(Integer targetTabIndex) { + this.targetTabIndex = targetTabIndex; + } + + public String getTargetRequiredMessage() { + return targetRequiredMessage; + } + + public void setTargetRequiredMessage(String targetRequiredMessage) { + this.targetRequiredMessage = targetRequiredMessage; + } + + public CollectionDatasource getTargetOptionsDatasource() { + return targetOptionsDatasource; + } + + public void setTargetOptionsDatasource(CollectionDatasource targetOptionsDatasource) { + this.targetOptionsDatasource = targetOptionsDatasource; + } + + public String getTargetCaption() { + return targetCaption; + } + + public void setTargetCaption(String targetCaption) { + this.targetCaption = targetCaption; + } + + public String getTargetDescription() { + return targetDescription; + } + + public void setTargetDescription(String targetDescription) { + this.targetDescription = targetDescription; + } + + public Formatter getTargetFormatter() { + return targetFormatter; + } + + public void setTargetFormatter(Formatter targetFormatter) { + this.targetFormatter = targetFormatter; + } + + public List getTargetValidators() { + return targetValidators; + } + + public void setTargetValidators(List targetValidators) { + this.targetValidators = targetValidators; + } + + public FieldAttachMode getAttachMode() { + return attachMode; + } + + public JLabel getLabel() { + return label; + } + + public void setLabel(JLabel label) { + this.label = label; + } + + public ToolTipButton getToolTipButton() { + return toolTipButton; + } + + public void setToolTipButton(ToolTipButton toolTipButton) { + this.toolTipButton = toolTipButton; + } + + @Override + public String toString() { + return "FieldConfig: " + id; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileMultiUploadField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileMultiUploadField.java index 8423ea8ce6..6fcf21498b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileMultiUploadField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileMultiUploadField.java @@ -1,331 +1,331 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopResources; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.gui.components.FileMultiUploadField; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.compatibility.MultiUploadFieldListenerWrapper; -import com.haulmont.cuba.gui.upload.FileUploadingAPI; -import org.apache.commons.io.FileUtils; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.*; - -import static com.haulmont.cuba.gui.upload.FileUploadingAPI.FileInfo; - -public class DesktopFileMultiUploadField extends DesktopAbstractUploadComponent implements FileMultiUploadField { - - protected static final String DEFAULT_ICON = "/components/multiupload/multiupload-button.png"; - - protected FileUploadingAPI fileUploading; - - protected Map filesMap = new LinkedHashMap<>(); - protected String icon; - - protected List fileUploadStartListeners; // lazily initialized list - protected List fileUploadFinishListeners; // lazily initialized list - protected List fileUploadErrorListeners; // lazily initialized list - protected List queueUploadCompleteListeners; // lazily initialized list - - public DesktopFileMultiUploadField() { - fileUploading = AppBeans.get(FileUploadingAPI.NAME); - - final JFileChooser fileChooser = new JFileChooser(); - fileChooser.setMultiSelectionEnabled(true); - - DesktopResources resources = App.getInstance().getResources(); - Messages messages = AppBeans.get(Messages.NAME); - String caption = messages.getMessage(getClass(), "upload.selectFiles"); - impl = new JButton(); - impl.setAction(new AbstractAction(caption, resources.getIcon(DEFAULT_ICON)) { - @Override - public void actionPerformed(ActionEvent e) { - if (fileChooser.showOpenDialog(impl) == JFileChooser.APPROVE_OPTION) { - processFiles(fileChooser.getSelectedFiles()); - } - } - }); - DesktopComponentsHelper.adjustSize(impl); - } - - protected void processFiles(File[] files) { - if (checkFiles(files)) { - uploadFiles(files); - } - } - - protected void uploadFiles(File[] files) { - for (File file : files) { - try { - fireFileUploadStart(file.getName(), file.length()); - - FileInfo fileInfo = fileUploading.createFile(); - UUID tempFileId = fileInfo.getId(); - File tmpFile = fileInfo.getFile(); - - FileUtils.copyFile(file, tmpFile); - - filesMap.put(tempFileId, file.getName()); - - fireFileUploadFinish(file.getName(), file.length()); - } catch (Exception ex) { - Messages messages = AppBeans.get(Messages.NAME); - String uploadError = messages.formatMessage(DesktopFileMultiUploadField.class, - "multiupload.uploadError", file.getName()); - - TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(this); - topLevelFrame.showNotification(uploadError, Frame.NotificationType.ERROR); - - fireFileUploadError(file.getName(), file.length(), ex); - } - } - - fireQueueUploadComplete(); - } - - protected boolean checkFiles(File[] files) { - for (File file : files) { - if (file.length() > getActualFileSizeLimit()) { - notifyFileSizeExceedLimit(file); - return false; - } - - if (hasInvalidExtension(file.getName())) { - notifyFileExtensionNotAllowed(file); - return false; - } - } - return true; - } - - protected boolean hasInvalidExtension(String name) { - if (getPermittedExtensions() != null && !getPermittedExtensions().isEmpty()) { - if (name.lastIndexOf(".") > 0) { - String fileExtension = name.substring(name.lastIndexOf("."), name.length()); - return !getPermittedExtensions().contains(fileExtension.toLowerCase()); - } else { - return true; - } - } - return false; - } - - protected void notifyFileSizeExceedLimit(File file) { - Messages messages = AppBeans.get(Messages.NAME); - String warningMsg = messages.formatMainMessage("upload.fileTooBig.message", file.getName(), getFileSizeLimitString()); - getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); - } - - protected void notifyFileExtensionNotAllowed(File file) { - Messages messages = AppBeans.get(Messages.NAME); - String warningMsg = messages.formatMainMessage("upload.fileIncorrectExtension.message", file.getName()); - getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); - } - - @Override - public void addListener(UploadListener listener) { - MultiUploadFieldListenerWrapper wrapper = new MultiUploadFieldListenerWrapper(listener); - - addFileUploadStartListener(wrapper); - addFileUploadFinishListener(wrapper); - addFileUploadErrorListener(wrapper); - addQueueUploadCompleteListener(wrapper); - } - - @Override - public void removeListener(UploadListener listener) { - MultiUploadFieldListenerWrapper wrapper = new MultiUploadFieldListenerWrapper(listener); - - removeFileUploadStartListener(wrapper); - removeFileUploadFinishListener(wrapper); - removeFileUploadErrorListener(wrapper); - removeQueueUploadCompleteListener(wrapper); - } - - @Override - public Map getUploadsMap() { - return Collections.unmodifiableMap(filesMap); - } - - @Override - public void clearUploads() { - filesMap.clear(); - } - - @Override - public String getCaption() { - return impl.getText(); - } - - @Override - public void setCaption(String caption) { - impl.setText(caption); - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } - - @Override - public String getIcon() { - return icon; - } - - @Override - public void setIcon(String icon) { - this.icon = icon; - if (icon != null) - impl.setIcon(App.getInstance().getResources().getIcon(icon)); - else - impl.setIcon(null); - } - - protected void fireFileUploadStart(String fileName, long contentLength) { - if (fileUploadStartListeners != null && !fileUploadStartListeners.isEmpty()) { - FileUploadStartEvent e = new FileUploadStartEvent(fileName, contentLength); - for (FileUploadStartListener listener : new ArrayList<>(fileUploadStartListeners)) { - listener.fileUploadStart(e); - } - } - } - - protected void fireFileUploadFinish(String fileName, long contentLength) { - if (fileUploadFinishListeners != null && !fileUploadFinishListeners.isEmpty()) { - FileUploadFinishEvent e = new FileUploadFinishEvent(fileName, contentLength); - for (FileUploadFinishListener listener : new ArrayList<>(fileUploadFinishListeners)) { - listener.fileUploadFinish(e); - } - } - } - - protected void fireFileUploadError(String fileName, long contentLength, Exception cause) { - if (fileUploadErrorListeners != null && !fileUploadErrorListeners.isEmpty()) { - FileUploadErrorEvent e = new FileUploadErrorEvent(fileName, contentLength, cause); - for (FileUploadErrorListener listener : new ArrayList<>(fileUploadErrorListeners)) { - listener.fileUploadError(e); - } - } - } - - protected void fireQueueUploadComplete() { - if (queueUploadCompleteListeners != null) { - for (QueueUploadCompleteListener listener : new ArrayList<>(queueUploadCompleteListeners)) { - listener.queueUploadComplete(); - } - } - } - - @Override - public void addFileUploadStartListener(FileUploadStartListener listener) { - if (fileUploadStartListeners == null) { - fileUploadStartListeners = new ArrayList<>(); - } - if (!fileUploadStartListeners.contains(listener)) { - fileUploadStartListeners.add(listener); - } - } - - @Override - public void removeFileUploadStartListener(FileUploadStartListener listener) { - if (fileUploadStartListeners != null) { - fileUploadStartListeners.remove(listener); - } - } - - @Override - public void addFileUploadFinishListener(FileUploadFinishListener listener) { - if (fileUploadFinishListeners == null) { - fileUploadFinishListeners = new ArrayList<>(); - } - if (!fileUploadFinishListeners.contains(listener)) { - fileUploadFinishListeners.add(listener); - } - } - - @Override - public void removeFileUploadFinishListener(FileUploadFinishListener listener) { - if (fileUploadFinishListeners != null) { - fileUploadFinishListeners.remove(listener); - } - } - - @Override - public void addFileUploadErrorListener(FileUploadErrorListener listener) { - if (fileUploadErrorListeners == null) { - fileUploadErrorListeners = new ArrayList<>(); - } - if (!fileUploadErrorListeners.isEmpty()) { - fileUploadErrorListeners.add(listener); - } - } - - @Override - public void removeFileUploadErrorListener(FileUploadErrorListener listener) { - if (fileUploadErrorListeners != null) { - fileUploadErrorListeners.remove(listener); - } - } - - @Override - public void addQueueUploadCompleteListener(QueueUploadCompleteListener listener) { - if (queueUploadCompleteListeners == null) { - queueUploadCompleteListeners = new ArrayList<>(); - } - if (!queueUploadCompleteListeners.contains(listener)) { - queueUploadCompleteListeners.add(listener); - } - } - - @Override - public void removeQueueUploadCompleteListener(QueueUploadCompleteListener listener) { - if (queueUploadCompleteListeners != null) { - queueUploadCompleteListeners.remove(listener); - } - } - - @Override - public String getAccept() { - // do nothing - return null; - } - - @Override - public void setAccept(String accept) { - // do nothing - } - - @Override - public void setFileSizeLimit(long fileSizeLimit) { - this.fileSizeLimit = fileSizeLimit; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopResources; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.gui.components.FileMultiUploadField; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.compatibility.MultiUploadFieldListenerWrapper; +import com.haulmont.cuba.gui.upload.FileUploadingAPI; +import org.apache.commons.io.FileUtils; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.*; + +import static com.haulmont.cuba.gui.upload.FileUploadingAPI.FileInfo; + +public class DesktopFileMultiUploadField extends DesktopAbstractUploadComponent implements FileMultiUploadField { + + protected static final String DEFAULT_ICON = "/components/multiupload/multiupload-button.png"; + + protected FileUploadingAPI fileUploading; + + protected Map filesMap = new LinkedHashMap<>(); + protected String icon; + + protected List fileUploadStartListeners; // lazily initialized list + protected List fileUploadFinishListeners; // lazily initialized list + protected List fileUploadErrorListeners; // lazily initialized list + protected List queueUploadCompleteListeners; // lazily initialized list + + public DesktopFileMultiUploadField() { + fileUploading = AppBeans.get(FileUploadingAPI.NAME); + + final JFileChooser fileChooser = new JFileChooser(); + fileChooser.setMultiSelectionEnabled(true); + + DesktopResources resources = App.getInstance().getResources(); + Messages messages = AppBeans.get(Messages.NAME); + String caption = messages.getMessage(getClass(), "upload.selectFiles"); + impl = new JButton(); + impl.setAction(new AbstractAction(caption, resources.getIcon(DEFAULT_ICON)) { + @Override + public void actionPerformed(ActionEvent e) { + if (fileChooser.showOpenDialog(impl) == JFileChooser.APPROVE_OPTION) { + processFiles(fileChooser.getSelectedFiles()); + } + } + }); + DesktopComponentsHelper.adjustSize(impl); + } + + protected void processFiles(File[] files) { + if (checkFiles(files)) { + uploadFiles(files); + } + } + + protected void uploadFiles(File[] files) { + for (File file : files) { + try { + fireFileUploadStart(file.getName(), file.length()); + + FileInfo fileInfo = fileUploading.createFile(); + UUID tempFileId = fileInfo.getId(); + File tmpFile = fileInfo.getFile(); + + FileUtils.copyFile(file, tmpFile); + + filesMap.put(tempFileId, file.getName()); + + fireFileUploadFinish(file.getName(), file.length()); + } catch (Exception ex) { + Messages messages = AppBeans.get(Messages.NAME); + String uploadError = messages.formatMessage(DesktopFileMultiUploadField.class, + "multiupload.uploadError", file.getName()); + + TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(this); + topLevelFrame.showNotification(uploadError, Frame.NotificationType.ERROR); + + fireFileUploadError(file.getName(), file.length(), ex); + } + } + + fireQueueUploadComplete(); + } + + protected boolean checkFiles(File[] files) { + for (File file : files) { + if (file.length() > getActualFileSizeLimit()) { + notifyFileSizeExceedLimit(file); + return false; + } + + if (hasInvalidExtension(file.getName())) { + notifyFileExtensionNotAllowed(file); + return false; + } + } + return true; + } + + protected boolean hasInvalidExtension(String name) { + if (getPermittedExtensions() != null && !getPermittedExtensions().isEmpty()) { + if (name.lastIndexOf(".") > 0) { + String fileExtension = name.substring(name.lastIndexOf("."), name.length()); + return !getPermittedExtensions().contains(fileExtension.toLowerCase()); + } else { + return true; + } + } + return false; + } + + protected void notifyFileSizeExceedLimit(File file) { + Messages messages = AppBeans.get(Messages.NAME); + String warningMsg = messages.formatMainMessage("upload.fileTooBig.message", file.getName(), getFileSizeLimitString()); + getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); + } + + protected void notifyFileExtensionNotAllowed(File file) { + Messages messages = AppBeans.get(Messages.NAME); + String warningMsg = messages.formatMainMessage("upload.fileIncorrectExtension.message", file.getName()); + getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); + } + + @Override + public void addListener(UploadListener listener) { + MultiUploadFieldListenerWrapper wrapper = new MultiUploadFieldListenerWrapper(listener); + + addFileUploadStartListener(wrapper); + addFileUploadFinishListener(wrapper); + addFileUploadErrorListener(wrapper); + addQueueUploadCompleteListener(wrapper); + } + + @Override + public void removeListener(UploadListener listener) { + MultiUploadFieldListenerWrapper wrapper = new MultiUploadFieldListenerWrapper(listener); + + removeFileUploadStartListener(wrapper); + removeFileUploadFinishListener(wrapper); + removeFileUploadErrorListener(wrapper); + removeQueueUploadCompleteListener(wrapper); + } + + @Override + public Map getUploadsMap() { + return Collections.unmodifiableMap(filesMap); + } + + @Override + public void clearUploads() { + filesMap.clear(); + } + + @Override + public String getCaption() { + return impl.getText(); + } + + @Override + public void setCaption(String caption) { + impl.setText(caption); + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } + + @Override + public String getIcon() { + return icon; + } + + @Override + public void setIcon(String icon) { + this.icon = icon; + if (icon != null) + impl.setIcon(App.getInstance().getResources().getIcon(icon)); + else + impl.setIcon(null); + } + + protected void fireFileUploadStart(String fileName, long contentLength) { + if (fileUploadStartListeners != null && !fileUploadStartListeners.isEmpty()) { + FileUploadStartEvent e = new FileUploadStartEvent(fileName, contentLength); + for (FileUploadStartListener listener : new ArrayList<>(fileUploadStartListeners)) { + listener.fileUploadStart(e); + } + } + } + + protected void fireFileUploadFinish(String fileName, long contentLength) { + if (fileUploadFinishListeners != null && !fileUploadFinishListeners.isEmpty()) { + FileUploadFinishEvent e = new FileUploadFinishEvent(fileName, contentLength); + for (FileUploadFinishListener listener : new ArrayList<>(fileUploadFinishListeners)) { + listener.fileUploadFinish(e); + } + } + } + + protected void fireFileUploadError(String fileName, long contentLength, Exception cause) { + if (fileUploadErrorListeners != null && !fileUploadErrorListeners.isEmpty()) { + FileUploadErrorEvent e = new FileUploadErrorEvent(fileName, contentLength, cause); + for (FileUploadErrorListener listener : new ArrayList<>(fileUploadErrorListeners)) { + listener.fileUploadError(e); + } + } + } + + protected void fireQueueUploadComplete() { + if (queueUploadCompleteListeners != null) { + for (QueueUploadCompleteListener listener : new ArrayList<>(queueUploadCompleteListeners)) { + listener.queueUploadComplete(); + } + } + } + + @Override + public void addFileUploadStartListener(FileUploadStartListener listener) { + if (fileUploadStartListeners == null) { + fileUploadStartListeners = new ArrayList<>(); + } + if (!fileUploadStartListeners.contains(listener)) { + fileUploadStartListeners.add(listener); + } + } + + @Override + public void removeFileUploadStartListener(FileUploadStartListener listener) { + if (fileUploadStartListeners != null) { + fileUploadStartListeners.remove(listener); + } + } + + @Override + public void addFileUploadFinishListener(FileUploadFinishListener listener) { + if (fileUploadFinishListeners == null) { + fileUploadFinishListeners = new ArrayList<>(); + } + if (!fileUploadFinishListeners.contains(listener)) { + fileUploadFinishListeners.add(listener); + } + } + + @Override + public void removeFileUploadFinishListener(FileUploadFinishListener listener) { + if (fileUploadFinishListeners != null) { + fileUploadFinishListeners.remove(listener); + } + } + + @Override + public void addFileUploadErrorListener(FileUploadErrorListener listener) { + if (fileUploadErrorListeners == null) { + fileUploadErrorListeners = new ArrayList<>(); + } + if (!fileUploadErrorListeners.isEmpty()) { + fileUploadErrorListeners.add(listener); + } + } + + @Override + public void removeFileUploadErrorListener(FileUploadErrorListener listener) { + if (fileUploadErrorListeners != null) { + fileUploadErrorListeners.remove(listener); + } + } + + @Override + public void addQueueUploadCompleteListener(QueueUploadCompleteListener listener) { + if (queueUploadCompleteListeners == null) { + queueUploadCompleteListeners = new ArrayList<>(); + } + if (!queueUploadCompleteListeners.contains(listener)) { + queueUploadCompleteListeners.add(listener); + } + } + + @Override + public void removeQueueUploadCompleteListener(QueueUploadCompleteListener listener) { + if (queueUploadCompleteListeners != null) { + queueUploadCompleteListeners.remove(listener); + } + } + + @Override + public String getAccept() { + // do nothing + return null; + } + + @Override + public void setAccept(String accept) { + // do nothing + } + + @Override + public void setFileSizeLimit(long fileSizeLimit) { + this.fileSizeLimit = fileSizeLimit; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileUploadField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileUploadField.java index 450d22fa00..c3ae165918 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileUploadField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFileUploadField.java @@ -1,818 +1,818 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.app.FileStorageService; -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.gui.backgroundwork.BackgroundWorkProgressWindow; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.compatibility.FileUploadFieldListenerWrapper; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import com.haulmont.cuba.gui.executors.BackgroundTask; -import com.haulmont.cuba.gui.executors.TaskLifeCycle; -import com.haulmont.cuba.gui.export.ExportDisplay; -import com.haulmont.cuba.gui.export.FileDataProvider; -import com.haulmont.cuba.gui.upload.FileUploadingAPI; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.io.*; -import java.util.*; - -import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; -import static com.haulmont.cuba.gui.upload.FileUploadingAPI.FileInfo; - -public class DesktopFileUploadField extends DesktopAbstractUploadField implements FileUploadField { - - private final Logger log = LoggerFactory.getLogger(DesktopFileUploadField.class); - - protected FileUploadingAPI fileUploading; - protected Messages messages; - protected ExportDisplay exportDisplay; - - protected FileContentProvider contentProvider; - - protected volatile boolean isUploadingState = false; - - protected String fileName; - protected Button uploadButton; - protected FileStoragePutMode mode = FileStoragePutMode.MANUAL; - - protected Datasource datasource; - - protected boolean updatingInstance; - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemChangeListener securityItemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - protected UUID fileId; - protected UUID tempFileId; - - protected List fileUploadStartListeners; // lazily initialized list - protected List fileUploadFinishListeners; // lazily initialized list - protected List fileUploadSucceedListeners; // lazily initialized list - protected List fileUploadErrorListeners; // lazily initialized list - - protected List beforeValueClearListeners; // lazily initialized list - protected List afterValueClearListeners; // lazily initialized list - - protected FileDescriptor prevValue; - - public DesktopFileUploadField() { - fileUploading = AppBeans.get(FileUploadingAPI.NAME); - messages = AppBeans.get(Messages.NAME); - exportDisplay = AppBeans.get(ExportDisplay.NAME); - - ComponentsFactory componentsFactory = AppBeans.get(ComponentsFactory.NAME); - uploadButton = (Button) componentsFactory.createComponent(Button.NAME); - final JFileChooser fileChooser = new JFileChooser(); - uploadButton.setAction(new AbstractAction("") { - @Override - public void actionPerform(Component component) { - if (fileChooser.showOpenDialog(uploadButton.unwrap(JButton.class)) == JFileChooser.APPROVE_OPTION) { - uploadFile(fileChooser.getSelectedFile()); - } - } - }); - uploadButton.setCaption(messages.getMessage(getClass(), "export.selectFile")); - - initImpl(); - } - - protected void initImpl() { - impl = new CubaFileUploadWrapper(uploadButton); - impl.setFileNameButtonClickListener(() -> { - FileDescriptor value = getValue(); - if (value == null) - return; - - switch (mode) { - case MANUAL: - String name = getFileName(); - String fileName1 = StringUtils.isEmpty(name) ? value.getName() : name; - exportDisplay.show(DesktopFileUploadField.this::getFileContent, fileName1); - break; - case IMMEDIATE: - exportDisplay.show(value); - } - }); - impl.setClearButtonListener(this::clearButtonClicked); - } - - protected void clearButtonClicked() { - boolean preventClearAction = false; - if (beforeValueClearListeners != null) { - BeforeValueClearEvent beforeValueClearEvent = new BeforeValueClearEvent(this); - for (BeforeValueClearListener listener : new ArrayList<>(beforeValueClearListeners)) { - listener.beforeValueClearPerformed(beforeValueClearEvent); - } - preventClearAction = beforeValueClearEvent.isClearPrevented(); - } - - if (!preventClearAction) { - setValue(null); - fileName = null; - } - - if (afterValueClearListeners != null) { - AfterValueClearEvent afterValueClearEvent = new AfterValueClearEvent(this, !preventClearAction); - for (AfterValueClearListener listener : new ArrayList<>(afterValueClearListeners)) { - listener.afterValueClearPerformed(afterValueClearEvent); - } - } - } - - protected void uploadFile(File file) { - if (file.length() > getActualFileSizeLimit()) { - String warningMsg = messages.formatMainMessage("upload.fileTooBig.message", file.getName(), getFileSizeLimitString()); - getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); - } else if (hasInvalidExtension(file.getName())) { - String warningMsg = messages.formatMainMessage("upload.fileIncorrectExtension.message", file.getName()); - getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); - } else { - boolean success = true; - try { - isUploadingState = true; - - fileName = file.getName(); - fireFileUploadStart(file.getName(), file.length()); - - FileInfo fileInfo = fileUploading.createFile(); - tempFileId = fileInfo.getId(); - File tmpFile = fileInfo.getFile(); - - FileUtils.copyFile(file, tmpFile); - - fileId = tempFileId; - saveFile(getFileDescriptor()); - - isUploadingState = false; - } catch (Exception ex) { - success = false; - try { - fileUploading.deleteFile(tempFileId); - tempFileId = null; - } catch (FileStorageException e) { - throw new RuntimeException("Unable to delete file from temp storage", ex); - } - - fireFileUploadError(file.getName(), file.length(), ex); - } finally { - fireFileUploadFinish(file.getName(), file.length()); - } - - if (success) { - fireFileUploadSucceed(file.getName(), file.length()); - } - } - } - - protected void saveFile(FileDescriptor fileDescriptor) { - switch (mode) { - case MANUAL: - setValue(fileDescriptor); - break; - case IMMEDIATE: - BackgroundTask uploadProgress = - new BackgroundTask(2400, getFrame()) { - @Override - public Map getParams() { - return ParamsMap.of("fileId", fileId, "fileName", getFileName()); - } - - @Override - public FileDescriptor run(final TaskLifeCycle taskLifeCycle) throws Exception { - return fileUploading.putFileIntoStorage(taskLifeCycle); - } - - @Override - public void done(FileDescriptor result) { - FileDescriptor descriptor = commitFileDescriptor(result); - setValue(descriptor); - } - }; - - long fileSize = fileUploading.getFile(fileId).length(); - BackgroundWorkProgressWindow.show(uploadProgress, messages.getMainMessage("FileUploadField.uploadingFile"), - null, fileSize, true, true); - break; - } - } - - protected FileDescriptor commitFileDescriptor(FileDescriptor fileDescriptor) { - if (datasource != null) { - return datasource.getDataSupplier().commit(fileDescriptor); - } - - if (getFrame().getDsContext().getDataSupplier() != null) { - return getFrame().getDsContext().getDataSupplier().commit(fileDescriptor); - } - - return AppBeans.get(DataManager.class).commit(fileDescriptor); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - impl.setWidth(width); - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - impl.setHeight(height); - } - - protected boolean hasInvalidExtension(String name) { - Set permittedExtensions = getPermittedExtensions(); - if (permittedExtensions != null && !permittedExtensions.isEmpty()) { - if (name.lastIndexOf(".") > 0) { - String fileExtension = name.substring(name.lastIndexOf("."), name.length()); - return !permittedExtensions.contains(fileExtension.toLowerCase()); - } else { - return true; - } - } - return false; - } - - @Override - public String getFileName() { - if (StringUtils.isEmpty(fileName)) - return null; - - String[] strings = fileName.split("[/\\\\]"); - return strings[strings.length - 1]; - } - - @Override - public FileDescriptor getFileDescriptor() { - if (fileId != null) { - return fileUploading.getFileDescriptor(fileId, fileName); - } else { - return null; - } - } - - @Override - public byte[] getBytes() { - byte[] bytes = null; - try { - if (fileId != null) { - File file = fileUploading.getFile(fileId); - FileInputStream fileInputStream = new FileInputStream(file); - ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); - IOUtils.copy(fileInputStream, byteOutput); - bytes = byteOutput.toByteArray(); - } - } catch (Exception e) { - throw new RuntimeException("Unable to read file content from temp storage", e); - } - - return bytes; - } - - @Override - public UUID getFileId() { - return fileId; - } - - @Override - public void addListener(Listener listener) { - FileUploadFieldListenerWrapper wrapper = new FileUploadFieldListenerWrapper(listener); - - addFileUploadStartListener(wrapper); - addFileUploadErrorListener(wrapper); - addFileUploadFinishListener(wrapper); - addFileUploadSucceedListener(wrapper); - } - @Override - public void removeListener(Listener listener) { - FileUploadFieldListenerWrapper wrapper = new FileUploadFieldListenerWrapper(listener); - - removeFileUploadStartListener(wrapper); - removeFileUploadErrorListener(wrapper); - removeFileUploadFinishListener(wrapper); - removeFileUploadSucceedListener(wrapper); - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - impl.setCaption(caption); - requestContainerUpdate(); - } - - @Override - public T getValue() { - return (T) prevValue; - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (!ObjectUtils.equals(prevValue, value)) { - updateInstance(value); - updateComponent((FileDescriptor) value); - fireChangeListeners(value); - } else { - updateComponent(prevValue); - } - - if (value == null || !PersistenceHelper.isNew(value)) { - fileId = null; - tempFileId = null; - } - } - - @Override - protected void setEditableToComponent(boolean editable) { - impl.setEditable(editable); - } - - @Override - public void setRequired(boolean required) { - super.setRequired(required); - impl.setRequired(required); - } - - @Override - public boolean isRequired() { - return impl.isRequired(); - } - - @Override - public void requestFocus() { - super.requestFocus(); - uploadButton.requestFocus(); - } - - @Override - public void setDescription(String description) { - impl.setDescription(description); - impl.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - requestContainerUpdate(); - } - - @Override - public String getDescription() { - return impl.getDescription(); - } - - protected void fireFileUploadStart(String fileName, long contentLength) { - if (fileUploadStartListeners != null && !fileUploadStartListeners.isEmpty()) { - FileUploadStartEvent e = new FileUploadStartEvent(fileName, contentLength); - for (FileUploadStartListener listener : new ArrayList<>(fileUploadStartListeners)) { - listener.fileUploadStart(e); - } - } - } - - protected void fireFileUploadFinish(String fileName, long contentLength) { - if (fileUploadFinishListeners != null && !fileUploadFinishListeners.isEmpty()) { - FileUploadFinishEvent e = new FileUploadFinishEvent(fileName, contentLength); - for (FileUploadFinishListener listener : new ArrayList<>(fileUploadFinishListeners)) { - listener.fileUploadFinish(e); - } - } - } - - protected void fireFileUploadError(String fileName, long contentLength, Exception cause) { - if (fileUploadErrorListeners != null && !fileUploadErrorListeners.isEmpty()) { - FileUploadErrorEvent e = new FileUploadErrorEvent(fileName, contentLength, cause); - for (FileUploadErrorListener listener : new ArrayList<>(fileUploadErrorListeners)) { - listener.fileUploadError(e); - } - } - } - - protected void fireFileUploadSucceed(String fileName, long contentLength) { - if (fileUploadSucceedListeners != null && !fileUploadSucceedListeners.isEmpty()) { - FileUploadSucceedEvent e = new FileUploadSucceedEvent(fileName, contentLength); - for (FileUploadSucceedListener listener : new ArrayList<>(fileUploadSucceedListeners)) { - listener.fileUploadSucceed(e); - } - } - } - - @Override - public void addFileUploadStartListener(FileUploadStartListener listener) { - if (fileUploadStartListeners == null) { - fileUploadStartListeners = new ArrayList<>(); - } - if (!fileUploadStartListeners.contains(listener)) { - fileUploadStartListeners.add(listener); - } - } - @Override - public void removeFileUploadStartListener(FileUploadStartListener listener) { - if (fileUploadStartListeners != null) { - fileUploadStartListeners.remove(listener); - } - } - - @Override - public void addFileUploadFinishListener(FileUploadFinishListener listener) { - if (fileUploadFinishListeners == null) { - fileUploadFinishListeners = new ArrayList<>(); - } - if (!fileUploadFinishListeners.contains(listener)) { - fileUploadFinishListeners.add(listener); - } - } - @Override - public void removeFileUploadFinishListener(FileUploadFinishListener listener) { - if (fileUploadFinishListeners != null) { - fileUploadFinishListeners.remove(listener); - } - } - - @Override - public void addFileUploadErrorListener(FileUploadErrorListener listener) { - if (fileUploadErrorListeners == null) { - fileUploadErrorListeners = new ArrayList<>(); - } - if (!fileUploadErrorListeners.isEmpty()) { - fileUploadErrorListeners.add(listener); - } - } - @Override - public void removeFileUploadErrorListener(FileUploadErrorListener listener) { - if (fileUploadErrorListeners != null) { - fileUploadErrorListeners.remove(listener); - } - } - - @Override - public void addFileUploadSucceedListener(FileUploadSucceedListener listener) { - if (fileUploadSucceedListeners == null) { - fileUploadSucceedListeners = new ArrayList<>(); - } - if (!fileUploadSucceedListeners.contains(listener)) { - fileUploadSucceedListeners.add(listener); - } - } - @Override - public void removeFileUploadSucceedListener(FileUploadSucceedListener listener) { - if (fileUploadSucceedListeners != null) { - fileUploadSucceedListeners.remove(listener); - } - } - - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = (FileDescriptor) newValue; - if (!ObjectUtils.equals(oldValue, newValue)) { - fireValueChanged(oldValue, newValue); - } - } - - @Override - public void setFileSizeLimit(long fileSizeLimit) { - this.fileSizeLimit = fileSizeLimit; - } - - @Override - public InputStream getFileContent() { - if (contentProvider != null) { - return contentProvider.provide(); - } - - FileDescriptor fileDescriptor = getValue(); - switch (mode) { - case MANUAL: - if (fileId == null) { - return new FileDataProvider(fileDescriptor).provide(); - } - - File file = fileUploading.getFile(fileId); - if (file != null) { - try { - return new FileInputStream(file); - } catch (FileNotFoundException e) { - log.error("Unable to get content of {}", file, e); - } - return null; - } - - FileStorageService fileStorageService = AppBeans.get(FileStorageService.NAME); - - try { - if (fileStorageService.fileExists(fileDescriptor)) { - return new FileDataProvider(fileDescriptor).provide(); - } - } catch (FileStorageException e) { - log.error("Unable to get content of {}", fileDescriptor, e); - return null; - } - break; - case IMMEDIATE: - if (fileDescriptor != null) { - return new FileDataProvider(fileDescriptor).provide(); - } - } - return null; - } - - @Override - public void setContentProvider(FileContentProvider contentProvider) { - this.contentProvider = contentProvider; - } - - @Override - public FileContentProvider getContentProvider() { - return contentProvider; - } - - @Override - public String getAccept() { - // do nothing - return null; - } - - @Override - public void setAccept(String accept) { - // do nothing - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - @Override - public void setDatasource(Datasource datasource, String property) { - this.datasource = datasource; - - if (datasource == null) { - setValue(null); - return; - } - - MetaClass metaClass = datasource.getMetaClass(); - resolveMetaPropertyPath(metaClass, property); - - itemChangeListener = e -> { - if (updatingInstance) - return; - FileDescriptor descriptor = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); - updateComponent(descriptor); - fireChangeListeners(descriptor); - }; - // noinspection unchecked - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) - return; - if (e.getProperty().equals(metaPropertyPath.toString())) { - updateComponent((FileDescriptor) e.getValue()); - fireChangeListeners(e.getValue()); - } - }; - // noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - initRequired(metaPropertyPath); - - if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { - Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); - FileDescriptor fileDescriptor = (FileDescriptor) newValue; - updateComponent(fileDescriptor); - fireChangeListeners(newValue); - } - - if (metaProperty.isReadOnly()) { - setEditable(false); - } - - handleFilteredAttributes(this, this.datasource, metaPropertyPath); - securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); - // noinspection unchecked - this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); - - initBeanValidator(); - } - - protected void updateInstance(Object value) { - updatingInstance = true; - try { - if (datasource != null && metaProperty != null && datasource.getItem() != null) { - datasource.getItem().setValueEx(metaPropertyPath.toString(), value); - } - } finally { - updatingInstance = false; - } - } - - protected void updateComponent(FileDescriptor fileDescriptor) { - if (fileDescriptor != null) { - impl.setFileName(fileDescriptor.getName()); - } else { - impl.setFileName(null); - } - } - - @Override - public boolean isShowFileName() { - return impl.isShowFileName(); - } - - @Override - public void setShowFileName(boolean showFileName) { - impl.setShowFileName(showFileName); - } - - @Override - public FileStoragePutMode getMode() { - return mode; - } - - @Override - public void setMode(FileStoragePutMode mode) { - this.mode = mode; - } - - /* - * Upload button - */ - @Override - public String getUploadButtonCaption() { - return impl.getUploadButtonCaption(); - } - - @Override - public void setUploadButtonCaption(String caption) { - impl.setUploadButtonCaption(caption); - } - - @Override - public void setUploadButtonIcon(String icon) { - impl.setUploadButtonIcon(icon); - } - - @Override - public String getUploadButtonIcon() { - return impl.getUploadButtonIcon(); - } - - @Override - public void setUploadButtonDescription(String description) { - impl.setUploadButtonDescription(description); - } - - @Override - public String getUploadButtonDescription() { - return impl.getUploadButtonDescription(); - } - - /* - * Clear button - */ - @Override - public void setShowClearButton(boolean showClearButton) { - impl.setShowClearButton(showClearButton); - } - - @Override - public boolean isShowClearButton() { - return impl.isShowClearButton(); - } - - @Override - public void setClearButtonCaption(String caption) { - impl.setClearButtonCaption(caption); - } - - @Override - public String getClearButtonCaption() { - return impl.getClearButtonCaption(); - } - - @Override - public void setClearButtonIcon(String icon) { - impl.setClearButtonIcon(icon); - } - - @Override - public String getClearButtonIcon() { - return impl.getClearButtonIcon(); - } - - @Override - public void setClearButtonDescription(String description) { - impl.setClearButtonDescription(description); - } - - @Override - public String getClearButtonDescription() { - return impl.getClearButtonDescription(); - } - - @Override - public void addBeforeValueClearListener(BeforeValueClearListener listener) { - if (beforeValueClearListeners == null) { - beforeValueClearListeners = new ArrayList<>(); - } - if (!beforeValueClearListeners.contains(listener)) { - beforeValueClearListeners.add(listener); - } - } - - @Override - public void removeBeforeValueClearListener(BeforeValueClearListener listener) { - if (beforeValueClearListeners != null) { - beforeValueClearListeners.remove(listener); - } - } - - @Override - public void addAfterValueClearListener(AfterValueClearListener listener) { - if (afterValueClearListeners == null) { - afterValueClearListeners = new ArrayList<>(); - } - if (!afterValueClearListeners.contains(listener)) { - afterValueClearListeners.add(listener); - } - } - - @Override - public void removeAfterValueClearListener(AfterValueClearListener listener) { - if (afterValueClearListeners != null) { - afterValueClearListeners.remove(listener); - } - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.app.FileStorageService; +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.gui.backgroundwork.BackgroundWorkProgressWindow; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.compatibility.FileUploadFieldListenerWrapper; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import com.haulmont.cuba.gui.executors.BackgroundTask; +import com.haulmont.cuba.gui.executors.TaskLifeCycle; +import com.haulmont.cuba.gui.export.ExportDisplay; +import com.haulmont.cuba.gui.export.FileDataProvider; +import com.haulmont.cuba.gui.upload.FileUploadingAPI; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import java.io.*; +import java.util.*; + +import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; +import static com.haulmont.cuba.gui.upload.FileUploadingAPI.FileInfo; + +public class DesktopFileUploadField extends DesktopAbstractUploadField implements FileUploadField { + + private final Logger log = LoggerFactory.getLogger(DesktopFileUploadField.class); + + protected FileUploadingAPI fileUploading; + protected Messages messages; + protected ExportDisplay exportDisplay; + + protected FileContentProvider contentProvider; + + protected volatile boolean isUploadingState = false; + + protected String fileName; + protected Button uploadButton; + protected FileStoragePutMode mode = FileStoragePutMode.MANUAL; + + protected Datasource datasource; + + protected boolean updatingInstance; + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemChangeListener securityItemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + protected UUID fileId; + protected UUID tempFileId; + + protected List fileUploadStartListeners; // lazily initialized list + protected List fileUploadFinishListeners; // lazily initialized list + protected List fileUploadSucceedListeners; // lazily initialized list + protected List fileUploadErrorListeners; // lazily initialized list + + protected List beforeValueClearListeners; // lazily initialized list + protected List afterValueClearListeners; // lazily initialized list + + protected FileDescriptor prevValue; + + public DesktopFileUploadField() { + fileUploading = AppBeans.get(FileUploadingAPI.NAME); + messages = AppBeans.get(Messages.NAME); + exportDisplay = AppBeans.get(ExportDisplay.NAME); + + ComponentsFactory componentsFactory = AppBeans.get(ComponentsFactory.NAME); + uploadButton = (Button) componentsFactory.createComponent(Button.NAME); + final JFileChooser fileChooser = new JFileChooser(); + uploadButton.setAction(new AbstractAction("") { + @Override + public void actionPerform(Component component) { + if (fileChooser.showOpenDialog(uploadButton.unwrap(JButton.class)) == JFileChooser.APPROVE_OPTION) { + uploadFile(fileChooser.getSelectedFile()); + } + } + }); + uploadButton.setCaption(messages.getMessage(getClass(), "export.selectFile")); + + initImpl(); + } + + protected void initImpl() { + impl = new CubaFileUploadWrapper(uploadButton); + impl.setFileNameButtonClickListener(() -> { + FileDescriptor value = getValue(); + if (value == null) + return; + + switch (mode) { + case MANUAL: + String name = getFileName(); + String fileName1 = StringUtils.isEmpty(name) ? value.getName() : name; + exportDisplay.show(DesktopFileUploadField.this::getFileContent, fileName1); + break; + case IMMEDIATE: + exportDisplay.show(value); + } + }); + impl.setClearButtonListener(this::clearButtonClicked); + } + + protected void clearButtonClicked() { + boolean preventClearAction = false; + if (beforeValueClearListeners != null) { + BeforeValueClearEvent beforeValueClearEvent = new BeforeValueClearEvent(this); + for (BeforeValueClearListener listener : new ArrayList<>(beforeValueClearListeners)) { + listener.beforeValueClearPerformed(beforeValueClearEvent); + } + preventClearAction = beforeValueClearEvent.isClearPrevented(); + } + + if (!preventClearAction) { + setValue(null); + fileName = null; + } + + if (afterValueClearListeners != null) { + AfterValueClearEvent afterValueClearEvent = new AfterValueClearEvent(this, !preventClearAction); + for (AfterValueClearListener listener : new ArrayList<>(afterValueClearListeners)) { + listener.afterValueClearPerformed(afterValueClearEvent); + } + } + } + + protected void uploadFile(File file) { + if (file.length() > getActualFileSizeLimit()) { + String warningMsg = messages.formatMainMessage("upload.fileTooBig.message", file.getName(), getFileSizeLimitString()); + getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); + } else if (hasInvalidExtension(file.getName())) { + String warningMsg = messages.formatMainMessage("upload.fileIncorrectExtension.message", file.getName()); + getFrame().showNotification(warningMsg, Frame.NotificationType.WARNING); + } else { + boolean success = true; + try { + isUploadingState = true; + + fileName = file.getName(); + fireFileUploadStart(file.getName(), file.length()); + + FileInfo fileInfo = fileUploading.createFile(); + tempFileId = fileInfo.getId(); + File tmpFile = fileInfo.getFile(); + + FileUtils.copyFile(file, tmpFile); + + fileId = tempFileId; + saveFile(getFileDescriptor()); + + isUploadingState = false; + } catch (Exception ex) { + success = false; + try { + fileUploading.deleteFile(tempFileId); + tempFileId = null; + } catch (FileStorageException e) { + throw new RuntimeException("Unable to delete file from temp storage", ex); + } + + fireFileUploadError(file.getName(), file.length(), ex); + } finally { + fireFileUploadFinish(file.getName(), file.length()); + } + + if (success) { + fireFileUploadSucceed(file.getName(), file.length()); + } + } + } + + protected void saveFile(FileDescriptor fileDescriptor) { + switch (mode) { + case MANUAL: + setValue(fileDescriptor); + break; + case IMMEDIATE: + BackgroundTask uploadProgress = + new BackgroundTask(2400, getFrame()) { + @Override + public Map getParams() { + return ParamsMap.of("fileId", fileId, "fileName", getFileName()); + } + + @Override + public FileDescriptor run(final TaskLifeCycle taskLifeCycle) throws Exception { + return fileUploading.putFileIntoStorage(taskLifeCycle); + } + + @Override + public void done(FileDescriptor result) { + FileDescriptor descriptor = commitFileDescriptor(result); + setValue(descriptor); + } + }; + + long fileSize = fileUploading.getFile(fileId).length(); + BackgroundWorkProgressWindow.show(uploadProgress, messages.getMainMessage("FileUploadField.uploadingFile"), + null, fileSize, true, true); + break; + } + } + + protected FileDescriptor commitFileDescriptor(FileDescriptor fileDescriptor) { + if (datasource != null) { + return datasource.getDataSupplier().commit(fileDescriptor); + } + + if (getFrame().getDsContext().getDataSupplier() != null) { + return getFrame().getDsContext().getDataSupplier().commit(fileDescriptor); + } + + return AppBeans.get(DataManager.class).commit(fileDescriptor); + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + impl.setWidth(width); + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + impl.setHeight(height); + } + + protected boolean hasInvalidExtension(String name) { + Set permittedExtensions = getPermittedExtensions(); + if (permittedExtensions != null && !permittedExtensions.isEmpty()) { + if (name.lastIndexOf(".") > 0) { + String fileExtension = name.substring(name.lastIndexOf("."), name.length()); + return !permittedExtensions.contains(fileExtension.toLowerCase()); + } else { + return true; + } + } + return false; + } + + @Override + public String getFileName() { + if (StringUtils.isEmpty(fileName)) + return null; + + String[] strings = fileName.split("[/\\\\]"); + return strings[strings.length - 1]; + } + + @Override + public FileDescriptor getFileDescriptor() { + if (fileId != null) { + return fileUploading.getFileDescriptor(fileId, fileName); + } else { + return null; + } + } + + @Override + public byte[] getBytes() { + byte[] bytes = null; + try { + if (fileId != null) { + File file = fileUploading.getFile(fileId); + FileInputStream fileInputStream = new FileInputStream(file); + ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); + IOUtils.copy(fileInputStream, byteOutput); + bytes = byteOutput.toByteArray(); + } + } catch (Exception e) { + throw new RuntimeException("Unable to read file content from temp storage", e); + } + + return bytes; + } + + @Override + public UUID getFileId() { + return fileId; + } + + @Override + public void addListener(Listener listener) { + FileUploadFieldListenerWrapper wrapper = new FileUploadFieldListenerWrapper(listener); + + addFileUploadStartListener(wrapper); + addFileUploadErrorListener(wrapper); + addFileUploadFinishListener(wrapper); + addFileUploadSucceedListener(wrapper); + } + @Override + public void removeListener(Listener listener) { + FileUploadFieldListenerWrapper wrapper = new FileUploadFieldListenerWrapper(listener); + + removeFileUploadStartListener(wrapper); + removeFileUploadErrorListener(wrapper); + removeFileUploadFinishListener(wrapper); + removeFileUploadSucceedListener(wrapper); + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + impl.setCaption(caption); + requestContainerUpdate(); + } + + @Override + public T getValue() { + return (T) prevValue; + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (!ObjectUtils.equals(prevValue, value)) { + updateInstance(value); + updateComponent((FileDescriptor) value); + fireChangeListeners(value); + } else { + updateComponent(prevValue); + } + + if (value == null || !PersistenceHelper.isNew(value)) { + fileId = null; + tempFileId = null; + } + } + + @Override + protected void setEditableToComponent(boolean editable) { + impl.setEditable(editable); + } + + @Override + public void setRequired(boolean required) { + super.setRequired(required); + impl.setRequired(required); + } + + @Override + public boolean isRequired() { + return impl.isRequired(); + } + + @Override + public void requestFocus() { + super.requestFocus(); + uploadButton.requestFocus(); + } + + @Override + public void setDescription(String description) { + impl.setDescription(description); + impl.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + requestContainerUpdate(); + } + + @Override + public String getDescription() { + return impl.getDescription(); + } + + protected void fireFileUploadStart(String fileName, long contentLength) { + if (fileUploadStartListeners != null && !fileUploadStartListeners.isEmpty()) { + FileUploadStartEvent e = new FileUploadStartEvent(fileName, contentLength); + for (FileUploadStartListener listener : new ArrayList<>(fileUploadStartListeners)) { + listener.fileUploadStart(e); + } + } + } + + protected void fireFileUploadFinish(String fileName, long contentLength) { + if (fileUploadFinishListeners != null && !fileUploadFinishListeners.isEmpty()) { + FileUploadFinishEvent e = new FileUploadFinishEvent(fileName, contentLength); + for (FileUploadFinishListener listener : new ArrayList<>(fileUploadFinishListeners)) { + listener.fileUploadFinish(e); + } + } + } + + protected void fireFileUploadError(String fileName, long contentLength, Exception cause) { + if (fileUploadErrorListeners != null && !fileUploadErrorListeners.isEmpty()) { + FileUploadErrorEvent e = new FileUploadErrorEvent(fileName, contentLength, cause); + for (FileUploadErrorListener listener : new ArrayList<>(fileUploadErrorListeners)) { + listener.fileUploadError(e); + } + } + } + + protected void fireFileUploadSucceed(String fileName, long contentLength) { + if (fileUploadSucceedListeners != null && !fileUploadSucceedListeners.isEmpty()) { + FileUploadSucceedEvent e = new FileUploadSucceedEvent(fileName, contentLength); + for (FileUploadSucceedListener listener : new ArrayList<>(fileUploadSucceedListeners)) { + listener.fileUploadSucceed(e); + } + } + } + + @Override + public void addFileUploadStartListener(FileUploadStartListener listener) { + if (fileUploadStartListeners == null) { + fileUploadStartListeners = new ArrayList<>(); + } + if (!fileUploadStartListeners.contains(listener)) { + fileUploadStartListeners.add(listener); + } + } + @Override + public void removeFileUploadStartListener(FileUploadStartListener listener) { + if (fileUploadStartListeners != null) { + fileUploadStartListeners.remove(listener); + } + } + + @Override + public void addFileUploadFinishListener(FileUploadFinishListener listener) { + if (fileUploadFinishListeners == null) { + fileUploadFinishListeners = new ArrayList<>(); + } + if (!fileUploadFinishListeners.contains(listener)) { + fileUploadFinishListeners.add(listener); + } + } + @Override + public void removeFileUploadFinishListener(FileUploadFinishListener listener) { + if (fileUploadFinishListeners != null) { + fileUploadFinishListeners.remove(listener); + } + } + + @Override + public void addFileUploadErrorListener(FileUploadErrorListener listener) { + if (fileUploadErrorListeners == null) { + fileUploadErrorListeners = new ArrayList<>(); + } + if (!fileUploadErrorListeners.isEmpty()) { + fileUploadErrorListeners.add(listener); + } + } + @Override + public void removeFileUploadErrorListener(FileUploadErrorListener listener) { + if (fileUploadErrorListeners != null) { + fileUploadErrorListeners.remove(listener); + } + } + + @Override + public void addFileUploadSucceedListener(FileUploadSucceedListener listener) { + if (fileUploadSucceedListeners == null) { + fileUploadSucceedListeners = new ArrayList<>(); + } + if (!fileUploadSucceedListeners.contains(listener)) { + fileUploadSucceedListeners.add(listener); + } + } + @Override + public void removeFileUploadSucceedListener(FileUploadSucceedListener listener) { + if (fileUploadSucceedListeners != null) { + fileUploadSucceedListeners.remove(listener); + } + } + + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = (FileDescriptor) newValue; + if (!ObjectUtils.equals(oldValue, newValue)) { + fireValueChanged(oldValue, newValue); + } + } + + @Override + public void setFileSizeLimit(long fileSizeLimit) { + this.fileSizeLimit = fileSizeLimit; + } + + @Override + public InputStream getFileContent() { + if (contentProvider != null) { + return contentProvider.provide(); + } + + FileDescriptor fileDescriptor = getValue(); + switch (mode) { + case MANUAL: + if (fileId == null) { + return new FileDataProvider(fileDescriptor).provide(); + } + + File file = fileUploading.getFile(fileId); + if (file != null) { + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + log.error("Unable to get content of {}", file, e); + } + return null; + } + + FileStorageService fileStorageService = AppBeans.get(FileStorageService.NAME); + + try { + if (fileStorageService.fileExists(fileDescriptor)) { + return new FileDataProvider(fileDescriptor).provide(); + } + } catch (FileStorageException e) { + log.error("Unable to get content of {}", fileDescriptor, e); + return null; + } + break; + case IMMEDIATE: + if (fileDescriptor != null) { + return new FileDataProvider(fileDescriptor).provide(); + } + } + return null; + } + + @Override + public void setContentProvider(FileContentProvider contentProvider) { + this.contentProvider = contentProvider; + } + + @Override + public FileContentProvider getContentProvider() { + return contentProvider; + } + + @Override + public String getAccept() { + // do nothing + return null; + } + + @Override + public void setAccept(String accept) { + // do nothing + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + @Override + public void setDatasource(Datasource datasource, String property) { + this.datasource = datasource; + + if (datasource == null) { + setValue(null); + return; + } + + MetaClass metaClass = datasource.getMetaClass(); + resolveMetaPropertyPath(metaClass, property); + + itemChangeListener = e -> { + if (updatingInstance) + return; + FileDescriptor descriptor = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); + updateComponent(descriptor); + fireChangeListeners(descriptor); + }; + // noinspection unchecked + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) + return; + if (e.getProperty().equals(metaPropertyPath.toString())) { + updateComponent((FileDescriptor) e.getValue()); + fireChangeListeners(e.getValue()); + } + }; + // noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + initRequired(metaPropertyPath); + + if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { + Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); + FileDescriptor fileDescriptor = (FileDescriptor) newValue; + updateComponent(fileDescriptor); + fireChangeListeners(newValue); + } + + if (metaProperty.isReadOnly()) { + setEditable(false); + } + + handleFilteredAttributes(this, this.datasource, metaPropertyPath); + securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); + // noinspection unchecked + this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); + + initBeanValidator(); + } + + protected void updateInstance(Object value) { + updatingInstance = true; + try { + if (datasource != null && metaProperty != null && datasource.getItem() != null) { + datasource.getItem().setValueEx(metaPropertyPath.toString(), value); + } + } finally { + updatingInstance = false; + } + } + + protected void updateComponent(FileDescriptor fileDescriptor) { + if (fileDescriptor != null) { + impl.setFileName(fileDescriptor.getName()); + } else { + impl.setFileName(null); + } + } + + @Override + public boolean isShowFileName() { + return impl.isShowFileName(); + } + + @Override + public void setShowFileName(boolean showFileName) { + impl.setShowFileName(showFileName); + } + + @Override + public FileStoragePutMode getMode() { + return mode; + } + + @Override + public void setMode(FileStoragePutMode mode) { + this.mode = mode; + } + + /* + * Upload button + */ + @Override + public String getUploadButtonCaption() { + return impl.getUploadButtonCaption(); + } + + @Override + public void setUploadButtonCaption(String caption) { + impl.setUploadButtonCaption(caption); + } + + @Override + public void setUploadButtonIcon(String icon) { + impl.setUploadButtonIcon(icon); + } + + @Override + public String getUploadButtonIcon() { + return impl.getUploadButtonIcon(); + } + + @Override + public void setUploadButtonDescription(String description) { + impl.setUploadButtonDescription(description); + } + + @Override + public String getUploadButtonDescription() { + return impl.getUploadButtonDescription(); + } + + /* + * Clear button + */ + @Override + public void setShowClearButton(boolean showClearButton) { + impl.setShowClearButton(showClearButton); + } + + @Override + public boolean isShowClearButton() { + return impl.isShowClearButton(); + } + + @Override + public void setClearButtonCaption(String caption) { + impl.setClearButtonCaption(caption); + } + + @Override + public String getClearButtonCaption() { + return impl.getClearButtonCaption(); + } + + @Override + public void setClearButtonIcon(String icon) { + impl.setClearButtonIcon(icon); + } + + @Override + public String getClearButtonIcon() { + return impl.getClearButtonIcon(); + } + + @Override + public void setClearButtonDescription(String description) { + impl.setClearButtonDescription(description); + } + + @Override + public String getClearButtonDescription() { + return impl.getClearButtonDescription(); + } + + @Override + public void addBeforeValueClearListener(BeforeValueClearListener listener) { + if (beforeValueClearListeners == null) { + beforeValueClearListeners = new ArrayList<>(); + } + if (!beforeValueClearListeners.contains(listener)) { + beforeValueClearListeners.add(listener); + } + } + + @Override + public void removeBeforeValueClearListener(BeforeValueClearListener listener) { + if (beforeValueClearListeners != null) { + beforeValueClearListeners.remove(listener); + } + } + + @Override + public void addAfterValueClearListener(AfterValueClearListener listener) { + if (afterValueClearListeners == null) { + afterValueClearListeners = new ArrayList<>(); + } + if (!afterValueClearListeners.contains(listener)) { + afterValueClearListeners.add(listener); + } + } + + @Override + public void removeAfterValueClearListener(AfterValueClearListener listener) { + if (afterValueClearListeners != null) { + afterValueClearListeners.remove(listener); + } + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilter.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilter.java index a5669a52c5..44d298b12b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilter.java @@ -1,389 +1,389 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Filter; -import com.haulmont.cuba.gui.components.FilterImplementation; -import com.haulmont.cuba.gui.components.MarginInfo; -import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper; -import com.haulmont.cuba.gui.components.filter.FilterDelegate; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.security.entity.FilterEntity; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; -import org.dom4j.Element; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * Generic filter implementation for the desktop-client. - * - */ -public class DesktopFilter extends DesktopAbstractComponent implements Filter, FilterImplementation { - - protected FilterDelegate delegate; - protected boolean settingsEnabled = true; - - protected List expandedStateChangeListeners; - - // just stub - protected boolean borderVisible = true; - - public DesktopFilter() { - delegate = AppBeans.get(FilterDelegate.class); - delegate.setFilter(this); - LC topLc = new LC(); - topLc.hideMode(3); - topLc.insetsAll("0"); - if (LayoutAdapter.isDebug()) { - topLc.debug(1000); - } - MigLayout topLayout = new MigLayout(topLc); - impl = new JPanel(topLayout); - - Container layout = delegate.getLayout(); - JComponent unwrap = DesktopComponentsHelper.getComposition(layout); - impl.add(unwrap, "width 100%"); - - setWidth("100%"); - - delegate.addExpandedStateChangeListener(e -> fireExpandStateChange(e.isExpanded())); - } - - @Override - public CollectionDatasource getDatasource() { - return delegate.getDatasource(); - } - - @Override - public void setDatasource(CollectionDatasource datasource) { - delegate.setDatasource(datasource); - } - - @Override - public void setFilterEntity(FilterEntity filterEntity) { - delegate.setFilterEntity(filterEntity); - } - - @Override - public boolean apply(boolean isNewWindow) { - return delegate.apply(isNewWindow); - } - - @Override - public void setMaxResults(int maxResults) { - delegate.setMaxResults(maxResults); - } - - @Override - public int getMaxResults() { - return delegate.getMaxResults(); - } - - @Override - public void loadFiltersAndApplyDefault() { - delegate.loadFiltersAndApplyDefault(); - } - - @Override - public void setUseMaxResults(boolean useMaxResults) { - delegate.setUseMaxResults(useMaxResults); - } - - @Override - public boolean getUseMaxResults() { - return delegate.getUseMaxResults(); - } - - @Override - public void setTextMaxResults(boolean textMaxResults) { - delegate.setTextMaxResults(textMaxResults); - } - - @Override - public boolean getTextMaxResults() { - return delegate.getTextMaxResults(); - } - - @Override - public void setApplyTo(Component component) { - delegate.setApplyTo(component); - } - - @Override - public Component getApplyTo() { - return delegate.getApplyTo(); - } - - @Override - public void setManualApplyRequired(Boolean manualApplyRequired) { - delegate.setManualApplyRequired(manualApplyRequired); - } - - @Override - public Boolean getManualApplyRequired() { - return delegate.getManualApplyRequired(); - } - - @Override - public void setEditable(boolean editable) { - delegate.setEditable(editable); - } - - @Override - public boolean isEditable() { - return delegate.isEditable(); - } - - @Override - public void setFolderActionsEnabled(boolean enabled) { - delegate.setFolderActionsEnabled(enabled); - } - - @Override - public boolean isFolderActionsEnabled() { - return delegate.isFolderActionsEnabled(); - } - - @Override - public void applySettings(Element element) { - if (isSettingsEnabled()) { - delegate.applySettings(element); - } - } - - @Override - public boolean saveSettings(Element element) { - return isSettingsEnabled() && delegate.saveSettings(element); - } - - @Override - public boolean isSettingsEnabled() { - return settingsEnabled; - } - - @Override - public void setSettingsEnabled(boolean settingsEnabled) { - this.settingsEnabled = settingsEnabled; - } - - // just stub - @Override - public void setMargin(MarginInfo marginInfo) { - } - - // just stub - @Override - public MarginInfo getMargin() { - return null; - } - - @Override - public String getCaption() { - return delegate.getCaption(); - } - - @Override - public void setCaption(String caption) { - delegate.setCaption(caption); - } - - @Override - public String getDescription() { - return null; - } - - @Override - public void setDescription(String description) { - //do nothing - } - - @Override - public void setParamValue(String paramName, Object value) { - delegate.setParamValue(paramName, value); - } - - @Override - public Object getParamValue(String paramName) { - return delegate.getParamValue(paramName); - } - - @Override - public void addFilterEntityChangeListener(FilterEntityChangeListener listener) { - delegate.addFilterEntityChangeListener(listener); - } - - @Override - public List getFilterEntityChangeListeners() { - return delegate.getFilterEntityChangeListeners(); - } - - @Override - public void setColumnsCount(int columnsCount) { - delegate.setColumnsCount(columnsCount); - } - - @Override - public int getColumnsCount() { - return delegate.getColumnsCount(); - } - - @Override - public void setEnabled(boolean enabled) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - enableComponents(impl, enabled); - } - - protected void enableComponents(java.awt.Container container, boolean enable) { - java.awt.Component[] components = container.getComponents(); - for (java.awt.Component component : components) { - component.setEnabled(enable); - if (component instanceof java.awt.Container) { - enableComponents((java.awt.Container)component, enable); - } - } - } - - @Nullable - @Override - public Component getComponent(String id) { - return delegate.getComponent(id); - } - - @Override - public boolean isExpanded() { - return delegate.isExpanded(); - } - - @Override - public void setExpanded(boolean expanded) { - delegate.setExpanded(expanded); - } - - @Override - public boolean isCollapsable() { - return delegate.isCollapsable(); - } - - @Override - public void setCollapsable(boolean collapsable) { - delegate.setCollapsable(collapsable); - } - - @Override - public void requestFocus() { - delegate.requestFocus(); - } - - @Override - public void switchFilterMode(FilterDelegate.FilterMode filterMode) { - delegate.switchFilterMode(filterMode); - } - - @Override - public void setModeSwitchVisible(boolean modeSwitchVisible) { - delegate.setModeSwitchVisible(modeSwitchVisible); - } - - @Override - public void addListener(ExpandListener listener) { - addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void removeListener(ExpandListener listener) { - removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void addListener(CollapseListener listener) { - addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void removeListener(CollapseListener listener) { - removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void addExpandedStateChangeListener(ExpandedStateChangeListener listener) { - if (expandedStateChangeListeners == null) { - expandedStateChangeListeners = new ArrayList<>(); - } - if (!expandedStateChangeListeners.contains(listener)) { - expandedStateChangeListeners.add(listener); - } - } - - @Override - public void removeExpandedStateChangeListener(ExpandedStateChangeListener listener) { - if (expandedStateChangeListeners != null) { - expandedStateChangeListeners.remove(listener); - } - } - - protected void fireExpandStateChange(boolean expanded) { - if (expandedStateChangeListeners != null && !expandedStateChangeListeners.isEmpty()) { - ExpandedStateChangeEvent event = new ExpandedStateChangeEvent(this, expanded); - - for (ExpandedStateChangeListener listener : new ArrayList<>(expandedStateChangeListeners)) { - listener.expandedStateChanged(event); - } - } - } - - @Override - public BeforeFilterAppliedHandler getBeforeFilterAppliedHandler() { - return delegate.getBeforeFilterAppliedHandler(); - } - - @Override - public void setBeforeFilterAppliedHandler(BeforeFilterAppliedHandler beforeFilterAppliedHandler) { - delegate.setBeforeFilterAppliedHandler(beforeFilterAppliedHandler); - } - - @Override - public AfterFilterAppliedHandler getAfterFilterAppliedHandler() { - return delegate.getAfterFilterAppliedHandler(); - } - - @Override - public void setAfterFilterAppliedHandler(AfterFilterAppliedHandler afterFilterAppliedHandler) { - delegate.setAfterFilterAppliedHandler(afterFilterAppliedHandler); - } - - // just stub - @Override - public void setBorderVisible(boolean visible) { - borderVisible = visible; - } - - // just stub - @Override - public boolean isBorderVisible() { - return borderVisible; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Filter; +import com.haulmont.cuba.gui.components.FilterImplementation; +import com.haulmont.cuba.gui.components.MarginInfo; +import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper; +import com.haulmont.cuba.gui.components.filter.FilterDelegate; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.security.entity.FilterEntity; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; +import org.dom4j.Element; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Generic filter implementation for the desktop-client. + * + */ +public class DesktopFilter extends DesktopAbstractComponent implements Filter, FilterImplementation { + + protected FilterDelegate delegate; + protected boolean settingsEnabled = true; + + protected List expandedStateChangeListeners; + + // just stub + protected boolean borderVisible = true; + + public DesktopFilter() { + delegate = AppBeans.get(FilterDelegate.class); + delegate.setFilter(this); + LC topLc = new LC(); + topLc.hideMode(3); + topLc.insetsAll("0"); + if (LayoutAdapter.isDebug()) { + topLc.debug(1000); + } + MigLayout topLayout = new MigLayout(topLc); + impl = new JPanel(topLayout); + + Container layout = delegate.getLayout(); + JComponent unwrap = DesktopComponentsHelper.getComposition(layout); + impl.add(unwrap, "width 100%"); + + setWidth("100%"); + + delegate.addExpandedStateChangeListener(e -> fireExpandStateChange(e.isExpanded())); + } + + @Override + public CollectionDatasource getDatasource() { + return delegate.getDatasource(); + } + + @Override + public void setDatasource(CollectionDatasource datasource) { + delegate.setDatasource(datasource); + } + + @Override + public void setFilterEntity(FilterEntity filterEntity) { + delegate.setFilterEntity(filterEntity); + } + + @Override + public boolean apply(boolean isNewWindow) { + return delegate.apply(isNewWindow); + } + + @Override + public void setMaxResults(int maxResults) { + delegate.setMaxResults(maxResults); + } + + @Override + public int getMaxResults() { + return delegate.getMaxResults(); + } + + @Override + public void loadFiltersAndApplyDefault() { + delegate.loadFiltersAndApplyDefault(); + } + + @Override + public void setUseMaxResults(boolean useMaxResults) { + delegate.setUseMaxResults(useMaxResults); + } + + @Override + public boolean getUseMaxResults() { + return delegate.getUseMaxResults(); + } + + @Override + public void setTextMaxResults(boolean textMaxResults) { + delegate.setTextMaxResults(textMaxResults); + } + + @Override + public boolean getTextMaxResults() { + return delegate.getTextMaxResults(); + } + + @Override + public void setApplyTo(Component component) { + delegate.setApplyTo(component); + } + + @Override + public Component getApplyTo() { + return delegate.getApplyTo(); + } + + @Override + public void setManualApplyRequired(Boolean manualApplyRequired) { + delegate.setManualApplyRequired(manualApplyRequired); + } + + @Override + public Boolean getManualApplyRequired() { + return delegate.getManualApplyRequired(); + } + + @Override + public void setEditable(boolean editable) { + delegate.setEditable(editable); + } + + @Override + public boolean isEditable() { + return delegate.isEditable(); + } + + @Override + public void setFolderActionsEnabled(boolean enabled) { + delegate.setFolderActionsEnabled(enabled); + } + + @Override + public boolean isFolderActionsEnabled() { + return delegate.isFolderActionsEnabled(); + } + + @Override + public void applySettings(Element element) { + if (isSettingsEnabled()) { + delegate.applySettings(element); + } + } + + @Override + public boolean saveSettings(Element element) { + return isSettingsEnabled() && delegate.saveSettings(element); + } + + @Override + public boolean isSettingsEnabled() { + return settingsEnabled; + } + + @Override + public void setSettingsEnabled(boolean settingsEnabled) { + this.settingsEnabled = settingsEnabled; + } + + // just stub + @Override + public void setMargin(MarginInfo marginInfo) { + } + + // just stub + @Override + public MarginInfo getMargin() { + return null; + } + + @Override + public String getCaption() { + return delegate.getCaption(); + } + + @Override + public void setCaption(String caption) { + delegate.setCaption(caption); + } + + @Override + public String getDescription() { + return null; + } + + @Override + public void setDescription(String description) { + //do nothing + } + + @Override + public void setParamValue(String paramName, Object value) { + delegate.setParamValue(paramName, value); + } + + @Override + public Object getParamValue(String paramName) { + return delegate.getParamValue(paramName); + } + + @Override + public void addFilterEntityChangeListener(FilterEntityChangeListener listener) { + delegate.addFilterEntityChangeListener(listener); + } + + @Override + public List getFilterEntityChangeListeners() { + return delegate.getFilterEntityChangeListeners(); + } + + @Override + public void setColumnsCount(int columnsCount) { + delegate.setColumnsCount(columnsCount); + } + + @Override + public int getColumnsCount() { + return delegate.getColumnsCount(); + } + + @Override + public void setEnabled(boolean enabled) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + enableComponents(impl, enabled); + } + + protected void enableComponents(java.awt.Container container, boolean enable) { + java.awt.Component[] components = container.getComponents(); + for (java.awt.Component component : components) { + component.setEnabled(enable); + if (component instanceof java.awt.Container) { + enableComponents((java.awt.Container)component, enable); + } + } + } + + @Nullable + @Override + public Component getComponent(String id) { + return delegate.getComponent(id); + } + + @Override + public boolean isExpanded() { + return delegate.isExpanded(); + } + + @Override + public void setExpanded(boolean expanded) { + delegate.setExpanded(expanded); + } + + @Override + public boolean isCollapsable() { + return delegate.isCollapsable(); + } + + @Override + public void setCollapsable(boolean collapsable) { + delegate.setCollapsable(collapsable); + } + + @Override + public void requestFocus() { + delegate.requestFocus(); + } + + @Override + public void switchFilterMode(FilterDelegate.FilterMode filterMode) { + delegate.switchFilterMode(filterMode); + } + + @Override + public void setModeSwitchVisible(boolean modeSwitchVisible) { + delegate.setModeSwitchVisible(modeSwitchVisible); + } + + @Override + public void addListener(ExpandListener listener) { + addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void removeListener(ExpandListener listener) { + removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void addListener(CollapseListener listener) { + addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void removeListener(CollapseListener listener) { + removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void addExpandedStateChangeListener(ExpandedStateChangeListener listener) { + if (expandedStateChangeListeners == null) { + expandedStateChangeListeners = new ArrayList<>(); + } + if (!expandedStateChangeListeners.contains(listener)) { + expandedStateChangeListeners.add(listener); + } + } + + @Override + public void removeExpandedStateChangeListener(ExpandedStateChangeListener listener) { + if (expandedStateChangeListeners != null) { + expandedStateChangeListeners.remove(listener); + } + } + + protected void fireExpandStateChange(boolean expanded) { + if (expandedStateChangeListeners != null && !expandedStateChangeListeners.isEmpty()) { + ExpandedStateChangeEvent event = new ExpandedStateChangeEvent(this, expanded); + + for (ExpandedStateChangeListener listener : new ArrayList<>(expandedStateChangeListeners)) { + listener.expandedStateChanged(event); + } + } + } + + @Override + public BeforeFilterAppliedHandler getBeforeFilterAppliedHandler() { + return delegate.getBeforeFilterAppliedHandler(); + } + + @Override + public void setBeforeFilterAppliedHandler(BeforeFilterAppliedHandler beforeFilterAppliedHandler) { + delegate.setBeforeFilterAppliedHandler(beforeFilterAppliedHandler); + } + + @Override + public AfterFilterAppliedHandler getAfterFilterAppliedHandler() { + return delegate.getAfterFilterAppliedHandler(); + } + + @Override + public void setAfterFilterAppliedHandler(AfterFilterAppliedHandler afterFilterAppliedHandler) { + delegate.setAfterFilterAppliedHandler(afterFilterAppliedHandler); + } + + // just stub + @Override + public void setBorderVisible(boolean visible) { + borderVisible = visible; + } + + // just stub + @Override + public boolean isBorderVisible() { + return borderVisible; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterDragAndDropSupport.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterDragAndDropSupport.java index 13c79aafbb..9f5bd68d88 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterDragAndDropSupport.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterDragAndDropSupport.java @@ -1,235 +1,235 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.datastruct.Node; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; -import com.haulmont.cuba.gui.components.Tree; -import com.haulmont.cuba.gui.components.filter.ConditionsTree; -import com.haulmont.cuba.gui.components.filter.condition.AbstractCondition; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.swing.*; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.io.IOException; -import java.util.Collections; -import java.util.Objects; - -/** - * Class provides support for Drag and Drop functionality in desktop implementation - * of generic filter editor - * - */ -@Component -public class DesktopFilterDragAndDropSupport { - - private Logger log = LoggerFactory.getLogger(DesktopFilterDragAndDropSupport.class); - - public void initDragAndDrop(Tree tree, ConditionsTree conditions) { - JTree dTree = (JTree) DesktopComponentsHelper.unwrap(tree); - dTree.setDragEnabled(true); - dTree.setDropMode(DropMode.ON_OR_INSERT); - dTree.setTransferHandler(new TreeTransferHandler(tree, conditions)); - } - - protected class TreeTransferHandler extends TransferHandler { - - private ConditionsTree conditions; - private Tree tree; - - public TreeTransferHandler(Tree tree, ConditionsTree conditions) { - this.tree = tree; - this.conditions = conditions; - } - - @Override - public boolean canImport(TransferSupport support) { - DropInfo dropInfo = getDropInfo(support); - AbstractCondition condition = dropInfo.getCondition(); - int dropIndex = dropInfo.getDropIndex(); - if (dropIndex == -1) { - return condition.isGroup(); - } else { - return true; - } - } - - @Override - public int getSourceActions(JComponent c) { - return MOVE; - } - - @Override - protected Transferable createTransferable(JComponent c) { - JTree tree = (JTree) c; - Object lastSelectedPathComponent = tree.getLastSelectedPathComponent(); - Entity entity = ((TreeModelAdapter.Node) lastSelectedPathComponent).getEntity(); - return new ConditionTransferable((AbstractCondition) entity); - } - - @Override - public boolean importData(TransferSupport support) { - DropInfo dropInfo = getDropInfo(support); - int dropIndex = dropInfo.getDropIndex(); - AbstractCondition targetCondition = dropInfo.getCondition(); - - AbstractCondition sourceCondition; - - Transferable transferable = support.getTransferable(); - try { - sourceCondition = (AbstractCondition) transferable.getTransferData(support.getDataFlavors()[0]); - } catch (Exception e) { - log.error(ExceptionUtils.getStackTrace(e)); - return false; - } - - Node sourceNode = conditions.getNode(sourceCondition); - Node targetNode = targetCondition == null ? null : conditions.getNode(targetCondition); - - boolean moveToTheSameParent = Objects.equals(sourceNode.getParent(), targetNode); - - if (dropIndex == -1) { //insert right into the node - if (sourceNode.getParent() == null) { - conditions.getRootNodes().remove(sourceNode); - } else { - sourceNode.getParent().getChildren().remove(sourceNode); - } - targetNode.addChild(sourceNode); - } else { //insert before or after other node - int sourceNodeIndex; - if (sourceNode.getParent() == null) { - sourceNodeIndex = conditions.getRootNodes().indexOf(sourceNode); - conditions.getRootNodes().remove(sourceNode); - } else { - sourceNodeIndex = sourceNode.getParent().getChildren().indexOf(sourceNode); - sourceNode.getParent().getChildren().remove(sourceNode); - } - - //decrease drop position index if dragging from top to bottom inside the same parent node - if (moveToTheSameParent && (sourceNodeIndex < dropIndex)) - dropIndex--; - - if (targetNode != null) { - targetNode.insertChildAt(dropIndex, sourceNode); - } else { - sourceNode.parent = null; - conditions.getRootNodes().add(dropIndex, sourceNode); - } - } - return true; - } - - @Override - protected void exportDone(JComponent source, Transferable data, int action) { - refreshConditionsDs(); - } - - protected void refreshConditionsDs() { - tree.getDatasource().refresh(Collections.singletonMap("conditions", conditions)); - tree.expandTree(); - } - - protected DropInfo getDropInfo(TransferSupport support) { - JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); - Object lastPathComponent = dropLocation.getPath().getLastPathComponent(); - if (lastPathComponent instanceof TreeModelAdapter.Node) { - TreeModelAdapter.Node targetTreeNode = (TreeModelAdapter.Node) lastPathComponent; - AbstractCondition condition = (AbstractCondition) targetTreeNode.getEntity(); - return new DropInfo(condition, dropLocation.getChildIndex()); - } else { - //if lastPathComponent is a String then a drop was on one of root nodes - return new DropInfo(null, dropLocation.getChildIndex()); - } - } - - /** - * Class holds an information about drop position in a tree. - */ - protected class DropInfo { - private AbstractCondition condition; - private int dropIndex; - - public DropInfo(AbstractCondition condition, int dropIndex) { - this.condition = condition; - this.dropIndex = dropIndex; - } - - /** - * @return a group condition if inserting node inside a group - * or null if inserting node to the top level of tree - */ - public AbstractCondition getCondition() { - return condition; - } - - /** - * @return drop position relatively to the parent node or -1 if inserting - * right into the node - */ - public int getDropIndex() { - return dropIndex; - } - } - } - - - /** - * Class provides a transferable {@link com.haulmont.cuba.gui.components.filter.condition.AbstractCondition} - * for Drag And Drop operation - */ - protected class ConditionTransferable implements Transferable { - - private AbstractCondition condition; - - public ConditionTransferable(AbstractCondition condition) { - this.condition = condition; - } - - @Override - public DataFlavor[] getTransferDataFlavors() { - String mimeType = DataFlavor.javaJVMLocalObjectMimeType + - ";class=\"" + - AbstractCondition.class.getName() + - "\""; - - DataFlavor[] dataFlavors = new DataFlavor[1]; - try { - dataFlavors[0] = new DataFlavor(mimeType); - } catch (Exception e) { - log.error(ExceptionUtils.getStackTrace(e)); - } - return dataFlavors; - } - - @Override - public boolean isDataFlavorSupported(DataFlavor flavor) { - return true; - } - - @Override - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - return condition; - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.datastruct.Node; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; +import com.haulmont.cuba.gui.components.Tree; +import com.haulmont.cuba.gui.components.filter.ConditionsTree; +import com.haulmont.cuba.gui.components.filter.condition.AbstractCondition; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.swing.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.Collections; +import java.util.Objects; + +/** + * Class provides support for Drag and Drop functionality in desktop implementation + * of generic filter editor + * + */ +@Component +public class DesktopFilterDragAndDropSupport { + + private Logger log = LoggerFactory.getLogger(DesktopFilterDragAndDropSupport.class); + + public void initDragAndDrop(Tree tree, ConditionsTree conditions) { + JTree dTree = (JTree) DesktopComponentsHelper.unwrap(tree); + dTree.setDragEnabled(true); + dTree.setDropMode(DropMode.ON_OR_INSERT); + dTree.setTransferHandler(new TreeTransferHandler(tree, conditions)); + } + + protected class TreeTransferHandler extends TransferHandler { + + private ConditionsTree conditions; + private Tree tree; + + public TreeTransferHandler(Tree tree, ConditionsTree conditions) { + this.tree = tree; + this.conditions = conditions; + } + + @Override + public boolean canImport(TransferSupport support) { + DropInfo dropInfo = getDropInfo(support); + AbstractCondition condition = dropInfo.getCondition(); + int dropIndex = dropInfo.getDropIndex(); + if (dropIndex == -1) { + return condition.isGroup(); + } else { + return true; + } + } + + @Override + public int getSourceActions(JComponent c) { + return MOVE; + } + + @Override + protected Transferable createTransferable(JComponent c) { + JTree tree = (JTree) c; + Object lastSelectedPathComponent = tree.getLastSelectedPathComponent(); + Entity entity = ((TreeModelAdapter.Node) lastSelectedPathComponent).getEntity(); + return new ConditionTransferable((AbstractCondition) entity); + } + + @Override + public boolean importData(TransferSupport support) { + DropInfo dropInfo = getDropInfo(support); + int dropIndex = dropInfo.getDropIndex(); + AbstractCondition targetCondition = dropInfo.getCondition(); + + AbstractCondition sourceCondition; + + Transferable transferable = support.getTransferable(); + try { + sourceCondition = (AbstractCondition) transferable.getTransferData(support.getDataFlavors()[0]); + } catch (Exception e) { + log.error(ExceptionUtils.getStackTrace(e)); + return false; + } + + Node sourceNode = conditions.getNode(sourceCondition); + Node targetNode = targetCondition == null ? null : conditions.getNode(targetCondition); + + boolean moveToTheSameParent = Objects.equals(sourceNode.getParent(), targetNode); + + if (dropIndex == -1) { //insert right into the node + if (sourceNode.getParent() == null) { + conditions.getRootNodes().remove(sourceNode); + } else { + sourceNode.getParent().getChildren().remove(sourceNode); + } + targetNode.addChild(sourceNode); + } else { //insert before or after other node + int sourceNodeIndex; + if (sourceNode.getParent() == null) { + sourceNodeIndex = conditions.getRootNodes().indexOf(sourceNode); + conditions.getRootNodes().remove(sourceNode); + } else { + sourceNodeIndex = sourceNode.getParent().getChildren().indexOf(sourceNode); + sourceNode.getParent().getChildren().remove(sourceNode); + } + + //decrease drop position index if dragging from top to bottom inside the same parent node + if (moveToTheSameParent && (sourceNodeIndex < dropIndex)) + dropIndex--; + + if (targetNode != null) { + targetNode.insertChildAt(dropIndex, sourceNode); + } else { + sourceNode.parent = null; + conditions.getRootNodes().add(dropIndex, sourceNode); + } + } + return true; + } + + @Override + protected void exportDone(JComponent source, Transferable data, int action) { + refreshConditionsDs(); + } + + protected void refreshConditionsDs() { + tree.getDatasource().refresh(Collections.singletonMap("conditions", conditions)); + tree.expandTree(); + } + + protected DropInfo getDropInfo(TransferSupport support) { + JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); + Object lastPathComponent = dropLocation.getPath().getLastPathComponent(); + if (lastPathComponent instanceof TreeModelAdapter.Node) { + TreeModelAdapter.Node targetTreeNode = (TreeModelAdapter.Node) lastPathComponent; + AbstractCondition condition = (AbstractCondition) targetTreeNode.getEntity(); + return new DropInfo(condition, dropLocation.getChildIndex()); + } else { + //if lastPathComponent is a String then a drop was on one of root nodes + return new DropInfo(null, dropLocation.getChildIndex()); + } + } + + /** + * Class holds an information about drop position in a tree. + */ + protected class DropInfo { + private AbstractCondition condition; + private int dropIndex; + + public DropInfo(AbstractCondition condition, int dropIndex) { + this.condition = condition; + this.dropIndex = dropIndex; + } + + /** + * @return a group condition if inserting node inside a group + * or null if inserting node to the top level of tree + */ + public AbstractCondition getCondition() { + return condition; + } + + /** + * @return drop position relatively to the parent node or -1 if inserting + * right into the node + */ + public int getDropIndex() { + return dropIndex; + } + } + } + + + /** + * Class provides a transferable {@link com.haulmont.cuba.gui.components.filter.condition.AbstractCondition} + * for Drag And Drop operation + */ + protected class ConditionTransferable implements Transferable { + + private AbstractCondition condition; + + public ConditionTransferable(AbstractCondition condition) { + this.condition = condition; + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + String mimeType = DataFlavor.javaJVMLocalObjectMimeType + + ";class=\"" + + AbstractCondition.class.getName() + + "\""; + + DataFlavor[] dataFlavors = new DataFlavor[1]; + try { + dataFlavors[0] = new DataFlavor(mimeType); + } catch (Exception e) { + log.error(ExceptionUtils.getStackTrace(e)); + } + return dataFlavors; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return true; + } + + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + return condition; + } + } +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterHelper.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterHelper.java index 168ec56ba3..d6727ded8d 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterHelper.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFilterHelper.java @@ -1,166 +1,166 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.AbstractSearchFolder; -import com.haulmont.cuba.core.entity.Folder; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.filter.ConditionsTree; -import com.haulmont.cuba.gui.components.filter.FilterHelper; -import com.haulmont.cuba.gui.presentations.Presentations; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; -import com.haulmont.cuba.security.entity.FilterEntity; -import org.apache.commons.lang.ObjectUtils; - -import javax.inject.Inject; -import javax.swing.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.Map; - -@org.springframework.stereotype.Component(FilterHelper.NAME) -public class DesktopFilterHelper implements FilterHelper { - @Inject - protected DesktopFilterDragAndDropSupport dragAndDropSupport; - - @Inject - protected ComponentsFactory componentsFactory; - - @Override - public void setLookupNullSelectionAllowed(LookupField lookupField, boolean value) { - lookupField.setRequired(!value); - } - - @Override - public void setLookupTextInputAllowed(LookupField lookupField, boolean value) { - //do nothing - } - - @Override - public AbstractSearchFolder saveFolder(AbstractSearchFolder folder) { - return null; - } - - @Override - public void openFolderEditWindow(boolean isAppFolder, AbstractSearchFolder folder, Presentations presentations, Runnable commitHandler) { - } - - @Override - public boolean isFolderActionsEnabled() { - return false; - } - - @Override - public void initConditionsDragAndDrop(Tree tree, ConditionsTree conditions) { - dragAndDropSupport.initDragAndDrop(tree, conditions); - } - - @Override - public Object getFoldersPane() { - return null; - } - - @Override - public void removeFolderFromFoldersPane(Folder folder) { - - } - - @Override - public boolean isTableActionsEnabled() { - return false; - } - - @Override - public void initTableFtsTooltips(Table table, Map tooltips) { - } - - @Override - public void removeTableFtsTooltips(Table table) { - - } - - @Override - public void setFieldReadOnlyFocusable(com.haulmont.cuba.gui.components.TextField textField, boolean readOnlyFocusable) { - //do nothing - } - - @Override - public void setComponentFocusable(Component component, boolean focusable) { - JComponent dComponent = DesktopComponentsHelper.unwrap(component); - dComponent.setFocusable(focusable); - } - - @Override - public void setLookupCaptions(LookupField lookupField, Map captions) { - ((DesktopLookupField) lookupField).setCaptionFormatter(new FilterEntityCaptionFormatter(captions)); - } - - @Override - public void addTextChangeListener(TextField textField, final TextChangeListener listener) { - final JTextField dTextField = (JTextField) DesktopComponentsHelper.unwrap(textField); - dTextField.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - listener.textChanged(dTextField.getText()); - } - }); - } - - @Override - public void addShortcutListener(TextField textField, final ShortcutListener listener) { - final JTextField dTextField = (JTextField) DesktopComponentsHelper.unwrap(textField); - final KeyStroke keyStroke = DesktopComponentsHelper.convertKeyCombination(listener.getKeyCombination()); - dTextField.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - if (ObjectUtils.equals(e.getKeyCode(), keyStroke.getKeyCode()) && - ObjectUtils.equals(e.getModifiers(), keyStroke.getModifiers())) { - listener.handleShortcutPressed(); - } - } - }); - } - - protected class FilterEntityCaptionFormatter implements DesktopAbstractOptionsField.CaptionFormatter { - - protected Map captions; - - public FilterEntityCaptionFormatter(Map captions) { - this.captions = captions; - } - - @Override - public String formatValue(FilterEntity value) { - return captions.get(value); - } - } - - @Override - public void setLookupFieldPageLength(LookupField lookupField, int pageLength) { - } - - @Override - public void setInternalDebugId(Component component, String id) { - // do nothing - } - - @Override - public Component.Container createSearchButtonGroupContainer() { - return componentsFactory.createComponent(HBoxLayout.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.AbstractSearchFolder; +import com.haulmont.cuba.core.entity.Folder; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.filter.ConditionsTree; +import com.haulmont.cuba.gui.components.filter.FilterHelper; +import com.haulmont.cuba.gui.presentations.Presentations; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; +import com.haulmont.cuba.security.entity.FilterEntity; +import org.apache.commons.lang.ObjectUtils; + +import javax.inject.Inject; +import javax.swing.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.Map; + +@org.springframework.stereotype.Component(FilterHelper.NAME) +public class DesktopFilterHelper implements FilterHelper { + @Inject + protected DesktopFilterDragAndDropSupport dragAndDropSupport; + + @Inject + protected ComponentsFactory componentsFactory; + + @Override + public void setLookupNullSelectionAllowed(LookupField lookupField, boolean value) { + lookupField.setRequired(!value); + } + + @Override + public void setLookupTextInputAllowed(LookupField lookupField, boolean value) { + //do nothing + } + + @Override + public AbstractSearchFolder saveFolder(AbstractSearchFolder folder) { + return null; + } + + @Override + public void openFolderEditWindow(boolean isAppFolder, AbstractSearchFolder folder, Presentations presentations, Runnable commitHandler) { + } + + @Override + public boolean isFolderActionsEnabled() { + return false; + } + + @Override + public void initConditionsDragAndDrop(Tree tree, ConditionsTree conditions) { + dragAndDropSupport.initDragAndDrop(tree, conditions); + } + + @Override + public Object getFoldersPane() { + return null; + } + + @Override + public void removeFolderFromFoldersPane(Folder folder) { + + } + + @Override + public boolean isTableActionsEnabled() { + return false; + } + + @Override + public void initTableFtsTooltips(Table table, Map tooltips) { + } + + @Override + public void removeTableFtsTooltips(Table table) { + + } + + @Override + public void setFieldReadOnlyFocusable(com.haulmont.cuba.gui.components.TextField textField, boolean readOnlyFocusable) { + //do nothing + } + + @Override + public void setComponentFocusable(Component component, boolean focusable) { + JComponent dComponent = DesktopComponentsHelper.unwrap(component); + dComponent.setFocusable(focusable); + } + + @Override + public void setLookupCaptions(LookupField lookupField, Map captions) { + ((DesktopLookupField) lookupField).setCaptionFormatter(new FilterEntityCaptionFormatter(captions)); + } + + @Override + public void addTextChangeListener(TextField textField, final TextChangeListener listener) { + final JTextField dTextField = (JTextField) DesktopComponentsHelper.unwrap(textField); + dTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + listener.textChanged(dTextField.getText()); + } + }); + } + + @Override + public void addShortcutListener(TextField textField, final ShortcutListener listener) { + final JTextField dTextField = (JTextField) DesktopComponentsHelper.unwrap(textField); + final KeyStroke keyStroke = DesktopComponentsHelper.convertKeyCombination(listener.getKeyCombination()); + dTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (ObjectUtils.equals(e.getKeyCode(), keyStroke.getKeyCode()) && + ObjectUtils.equals(e.getModifiers(), keyStroke.getModifiers())) { + listener.handleShortcutPressed(); + } + } + }); + } + + protected class FilterEntityCaptionFormatter implements DesktopAbstractOptionsField.CaptionFormatter { + + protected Map captions; + + public FilterEntityCaptionFormatter(Map captions) { + this.captions = captions; + } + + @Override + public String formatValue(FilterEntity value) { + return captions.get(value); + } + } + + @Override + public void setLookupFieldPageLength(LookupField lookupField, int pageLength) { + } + + @Override + public void setInternalDebugId(Component component, String id) { + // do nothing + } + + @Override + public Component.Container createSearchButtonGroupContainer() { + return componentsFactory.createComponent(HBoxLayout.class); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFrame.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFrame.java index 0010a31c8d..2947566700 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFrame.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopFrame.java @@ -1,585 +1,585 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DetachedFrame; -import com.haulmont.cuba.desktop.sys.DesktopWindowManager; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.DialogParams; -import com.haulmont.cuba.gui.FrameContext; -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.gui.config.WindowInfo; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.DsContext; -import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.lang.reflect.Constructor; -import java.util.*; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -public class DesktopFrame - extends DesktopVBox - implements DetachableFrame, WrappedFrame, Component.HasXmlDescriptor { - - private final Logger log = LoggerFactory.getLogger(DesktopFrame.class); - - private String messagePack; - private FrameContext context; - private DsContext dsContext; - private Frame wrapper; - private Map allComponents = new HashMap<>(); - - private boolean detached; - private DetachedFrame detachedFrame; - private int componentPosition = -1; - private HierarchyListener hierarchyListener; - - private List detachListeners = new ArrayList<>(); - - private WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - protected Messages messages = AppBeans.get(Messages.NAME); - - private DesktopFrameActionsHolder actionsHolder; - - protected boolean isAttachedToRoot = false; - - public DesktopFrame() { - actionsHolder = new DesktopFrameActionsHolder(this, impl); - - impl.addAncestorListener(new AncestorListener() { - @Override - public void ancestorAdded(AncestorEvent event) { - SwingUtilities.invokeLater(() -> { - if (!isAttachedToRoot) { - if (SwingUtilities.getRoot(event.getComponent()) != null) { - enableEventListeners(); - isAttachedToRoot = true; - } - } - }); - } - - @Override - public void ancestorRemoved(AncestorEvent event) { - SwingUtilities.invokeLater(() -> { - if (isAttachedToRoot) { - if (SwingUtilities.getRoot(event.getComponent()) == null) { - disableEventListeners(); - isAttachedToRoot = false; - } - } - }); - } - - @Override - public void ancestorMoved(AncestorEvent event) { - } - }); - } - - protected void disableEventListeners() { - Frame wrapper = getWrapper(); - if (wrapper != null) { - List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); - if (uiEventListeners != null) { - for (ApplicationListener listener : uiEventListeners) { - UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); - multicaster.removeApplicationListener(listener); - } - } - } - } - - protected void enableEventListeners() { - Frame wrapper = getWrapper(); - if (wrapper != null) { - List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); - if (uiEventListeners != null) { - for (ApplicationListener listener : uiEventListeners) { - UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); - multicaster.addApplicationListener(listener); - } - } - } - } - - @Override - public FrameContext getContext() { - return context == null ? getFrame().getContext() : context; - } - - @Override - public void setContext(FrameContext ctx) { - this.context = ctx; - } - - @Override - public DsContext getDsContext() { - return dsContext == null ? getFrame().getDsContext() : dsContext; - } - - @Override - public void setDsContext(DsContext dsContext) { - this.dsContext = dsContext; - } - - @Override - public String getMessagesPack() { - return messagePack; - } - - @Override - public void setMessagesPack(String name) { - messagePack = name; - } - - @Override - protected void attachToFrame(Component component) { - registerComponent(component); - } - - @Override - public void registerComponent(Component component) { - if (component.getId() != null) { - allComponents.put(component.getId(), component); - } - } - - @Override - public void unregisterComponent(Component component) { - if (component.getId() != null) { - allComponents.remove(component.getId()); - } - } - - @Nullable - @Override - public Component getRegisteredComponent(String id) { - return allComponents.get(id); - } - - @Override - public boolean isValid() { - Collection components = ComponentsHelper.getComponents(this); - for (Component component : components) { - if (component instanceof Validatable) { - Component.Validatable validatable = (Component.Validatable) component; - if (validatable.isValidateOnCommit() && !validatable.isValid()) - return false; - } - } - return true; - } - - @Override - public void validate() throws ValidationException { - Collection components = ComponentsHelper.getComponents(this); - for (Component component : components) { - if (component instanceof Validatable) { - Component.Validatable validatable = (Component.Validatable) component; - if (validatable.isValidateOnCommit()) { - validatable.validate(); - } - } - } - } - - @Override - public boolean validate(List fields) { - ValidationErrors errors = new ValidationErrors(); - - for (Validatable field : fields) { - try { - field.validate(); - } catch (ValidationException e) { - if (log.isTraceEnabled()) - log.trace("Validation failed", e); - else if (log.isDebugEnabled()) - log.debug("Validation failed: " + e); - - ComponentsHelper.fillErrorMessages(field, e, errors); - } - } - - return handleValidationErrors(errors); - } - - @Override - public boolean validateAll() { - ValidationErrors errors = new ValidationErrors(); - - Collection components = ComponentsHelper.getComponents(this); - for (Component component : components) { - if (component instanceof Validatable) { - Validatable validatable = (Validatable) component; - if (validatable.isValidateOnCommit()) { - try { - validatable.validate(); - } catch (ValidationException e) { - if (log.isTraceEnabled()) - log.trace("Validation failed", e); - else if (log.isDebugEnabled()) - log.debug("Validation failed: " + e); - - ComponentsHelper.fillErrorMessages(validatable, e, errors); - } - } - } - } - - return handleValidationErrors(errors); - } - - protected boolean handleValidationErrors(ValidationErrors errors) { - if (errors.isEmpty()) - return true; - - DesktopComponentsHelper.focusProblemComponent(errors); - - Window window = ComponentsHelper.getWindow(wrapper); - if (window instanceof AbstractFrame) { - SwingUtilities.invokeLater(() -> { - ((AbstractFrame) window).showValidationErrors(errors); - }); - } - - return false; - } - - private DesktopWindowManager getWindowManager() { - return DesktopComponentsHelper.getTopLevelFrame((Frame) this).getWindowManager(); - } - - @Deprecated - @Override - public DialogParams getDialogParams() { - return getWindowManager().getDialogParams(); - } - - @Override - public Window openWindow(String windowAlias, WindowManager.OpenType openType, Map params) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openWindow(windowInfo, openType, params); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType) { - WindowInfo editorScreen = windowConfig.getEditorScreen(item); - return getWindowManager().openEditor(editorScreen, item, openType); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params) { - WindowInfo editorScreen = windowConfig.getEditorScreen(item); - return getWindowManager().openEditor(editorScreen, item, openType, params); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { - WindowInfo editorScreen = windowConfig.getEditorScreen(item); - return getWindowManager().openEditor(editorScreen, item, openType, params, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openEditor(windowInfo, item, openType, params, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openEditor(windowInfo, item, openType, params); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Datasource parentDs) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openEditor(windowInfo, item, openType, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openEditor(windowInfo, item, openType); - } - - @Override - public Window openWindow(String windowAlias, WindowManager.OpenType openType) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openWindow(windowInfo, openType); - } - - @Override - public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType) { - WindowInfo lookupScreen = windowConfig.getLookupScreen(entityClass); - return getWindowManager().openLookup(lookupScreen, handler, openType); - } - - @Override - public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { - WindowInfo lookupScreen = windowConfig.getLookupScreen(entityClass); - return getWindowManager().openLookup(lookupScreen, handler, openType, params); - } - - @Override - public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openLookup(windowInfo, handler, openType, params); - } - - @Override - public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - return getWindowManager().openLookup(windowInfo, handler, openType); - } - - @Override - public Frame openFrame(Component parent, String windowAlias) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - Frame wrappedFrame = ((Frame.Wrapper) wrapper).getWrappedFrame(); - return getWindowManager().openFrame(wrappedFrame, parent, windowInfo); - } - - @Override - public Frame openFrame(Component parent, String windowAlias, Map params) { - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - Frame wrappedFrame = ((Frame.Wrapper) wrapper).getWrappedFrame(); - return getWindowManager().openFrame(wrappedFrame, parent, windowInfo, params); - } - - @Override - public void detachFrame(String caption) { - if (isDetached()) { - throw new RuntimeException("Frame already detached"); - } - final java.awt.Container parent = impl.getParent(); - - detachedFrame = new DetachedFrame(caption, parent); - - for (int i = 0; i < parent.getComponentCount(); i++) { - if (impl == parent.getComponent(i)) { - componentPosition = i; - break; - } - } - - hierarchyListener = new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) == HierarchyEvent.DISPLAYABILITY_CHANGED - && !parent.isDisplayable()) { - parent.removeHierarchyListener(this); - attachFrame(); - } - } - }; - - detachedFrame.setLocationRelativeTo(DesktopComponentsHelper.getTopLevelFrame(impl)); - detachedFrame.setSize(impl.getSize()); - detachedFrame.add(impl); - detachedFrame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - parent.removeHierarchyListener(hierarchyListener); - attachFrame(); - } - }); - parent.revalidate(); - parent.repaint(); - parent.addHierarchyListener(hierarchyListener); - detachedFrame.setVisible(true); - detached = true; - for (DetachListener listener : detachListeners) { - listener.frameDetached(this); - } - } - - @Override - public void attachFrame() { - if (!isDetached()) { - throw new RuntimeException("Frame is already attached"); - } - java.awt.Container parent = detachedFrame.getParentContainer(); - parent.add(impl, componentPosition); - detachedFrame.dispose(); - parent.removeHierarchyListener(hierarchyListener); - detachedFrame = null; - detached = false; - parent.revalidate(); - parent.repaint(); - for (DetachListener listener : detachListeners) { - listener.frameAttached(this); - } - } - - @Override - public void addDetachListener(DetachListener listener) { - if (!detachListeners.contains(listener)) { - detachListeners.add(listener); - } - } - - @Override - public void removeDetachListener(DetachListener listener) { - detachListeners.remove(listener); - } - - @Override - public boolean isDetached() { - return detached; - } - - @Override - public void showMessageDialog(String title, String message, MessageType messageType) { - getWindowManager().showMessageDialog(title, message, messageType); - } - - @Override - public void showOptionDialog(String title, String message, MessageType messageType, Action[] actions) { - getWindowManager().showOptionDialog(title, message, messageType, actions); - } - - @Override - public void showOptionDialog(String title, String message, MessageType messageType, java.util.List actions) { - getWindowManager().showOptionDialog(title, message, messageType, actions.toArray(new Action[actions.size()])); - } - - @Override - public void showNotification(String caption, String description, NotificationType type) { - getWindowManager().showNotification(caption, description, type); - } - - @Override - public void showWebPage(String url, @Nullable Map params) { - getWindowManager().showWebPage(url, params); - } - - @Override - public void showNotification(String caption) { - getWindowManager().showNotification(caption); - } - - @Override - public void showNotification(String caption, NotificationType type) { - getWindowManager().showNotification(caption, type); - } - - @Override - public Frame wrapBy(Class aClass) { - try { - // First try to find an old-style constructor with Frame parameter - Constructor constructor = null; - try { - constructor = aClass.getConstructor(Frame.class); - } catch (NoSuchMethodException e) { - // - } - if (constructor != null) { - wrapper = (Frame) constructor.newInstance(this); - } else { - // If not found, get the default constructor - constructor = aClass.getConstructor(); - wrapper = (Frame) constructor.newInstance(); - ((AbstractFrame) wrapper).setWrappedFrame(this); - } - return wrapper; - } catch (Throwable e) { - throw new RuntimeException("Unable to init frame controller", e); - } - } - - @Override - public Frame getWrapper() { - return wrapper; - } - - @Override - public Component getComponent(String id) { - return ComponentsHelper.getFrameComponent(this, id); - } - - @Override - public boolean expandsWidth() { - return true; - } - - @Override - public boolean expandsHeight() { - return false; - } - - @Override - public void addAction(final Action action) { - checkNotNullArgument(action, "action must be non null"); - - actionsHolder.addAction(action); - } - - @Override - public void addAction(Action action, int index) { - checkNotNullArgument(action, "action must be non null"); - - actionsHolder.addAction(action, index); - } - - @Override - public void removeAction(@Nullable Action action) { - actionsHolder.removeAction(action); - } - - @Override - public void removeAction(@Nullable String id) { - actionsHolder.removeAction(id); - } - - @Override - public void removeAllActions() { - actionsHolder.removeAllActions(); - } - - @Override - public Collection getActions() { - return actionsHolder.getActions(); - } - - @Override - @Nullable - public Action getAction(String id) { - return actionsHolder.getAction(id); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DetachedFrame; +import com.haulmont.cuba.desktop.sys.DesktopWindowManager; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.DialogParams; +import com.haulmont.cuba.gui.FrameContext; +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.gui.config.WindowInfo; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.DsContext; +import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.Constructor; +import java.util.*; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +public class DesktopFrame + extends DesktopVBox + implements DetachableFrame, WrappedFrame, Component.HasXmlDescriptor { + + private final Logger log = LoggerFactory.getLogger(DesktopFrame.class); + + private String messagePack; + private FrameContext context; + private DsContext dsContext; + private Frame wrapper; + private Map allComponents = new HashMap<>(); + + private boolean detached; + private DetachedFrame detachedFrame; + private int componentPosition = -1; + private HierarchyListener hierarchyListener; + + private List detachListeners = new ArrayList<>(); + + private WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + protected Messages messages = AppBeans.get(Messages.NAME); + + private DesktopFrameActionsHolder actionsHolder; + + protected boolean isAttachedToRoot = false; + + public DesktopFrame() { + actionsHolder = new DesktopFrameActionsHolder(this, impl); + + impl.addAncestorListener(new AncestorListener() { + @Override + public void ancestorAdded(AncestorEvent event) { + SwingUtilities.invokeLater(() -> { + if (!isAttachedToRoot) { + if (SwingUtilities.getRoot(event.getComponent()) != null) { + enableEventListeners(); + isAttachedToRoot = true; + } + } + }); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + SwingUtilities.invokeLater(() -> { + if (isAttachedToRoot) { + if (SwingUtilities.getRoot(event.getComponent()) == null) { + disableEventListeners(); + isAttachedToRoot = false; + } + } + }); + } + + @Override + public void ancestorMoved(AncestorEvent event) { + } + }); + } + + protected void disableEventListeners() { + Frame wrapper = getWrapper(); + if (wrapper != null) { + List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); + if (uiEventListeners != null) { + for (ApplicationListener listener : uiEventListeners) { + UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); + multicaster.removeApplicationListener(listener); + } + } + } + } + + protected void enableEventListeners() { + Frame wrapper = getWrapper(); + if (wrapper != null) { + List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); + if (uiEventListeners != null) { + for (ApplicationListener listener : uiEventListeners) { + UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); + multicaster.addApplicationListener(listener); + } + } + } + } + + @Override + public FrameContext getContext() { + return context == null ? getFrame().getContext() : context; + } + + @Override + public void setContext(FrameContext ctx) { + this.context = ctx; + } + + @Override + public DsContext getDsContext() { + return dsContext == null ? getFrame().getDsContext() : dsContext; + } + + @Override + public void setDsContext(DsContext dsContext) { + this.dsContext = dsContext; + } + + @Override + public String getMessagesPack() { + return messagePack; + } + + @Override + public void setMessagesPack(String name) { + messagePack = name; + } + + @Override + protected void attachToFrame(Component component) { + registerComponent(component); + } + + @Override + public void registerComponent(Component component) { + if (component.getId() != null) { + allComponents.put(component.getId(), component); + } + } + + @Override + public void unregisterComponent(Component component) { + if (component.getId() != null) { + allComponents.remove(component.getId()); + } + } + + @Nullable + @Override + public Component getRegisteredComponent(String id) { + return allComponents.get(id); + } + + @Override + public boolean isValid() { + Collection components = ComponentsHelper.getComponents(this); + for (Component component : components) { + if (component instanceof Validatable) { + Component.Validatable validatable = (Component.Validatable) component; + if (validatable.isValidateOnCommit() && !validatable.isValid()) + return false; + } + } + return true; + } + + @Override + public void validate() throws ValidationException { + Collection components = ComponentsHelper.getComponents(this); + for (Component component : components) { + if (component instanceof Validatable) { + Component.Validatable validatable = (Component.Validatable) component; + if (validatable.isValidateOnCommit()) { + validatable.validate(); + } + } + } + } + + @Override + public boolean validate(List fields) { + ValidationErrors errors = new ValidationErrors(); + + for (Validatable field : fields) { + try { + field.validate(); + } catch (ValidationException e) { + if (log.isTraceEnabled()) + log.trace("Validation failed", e); + else if (log.isDebugEnabled()) + log.debug("Validation failed: " + e); + + ComponentsHelper.fillErrorMessages(field, e, errors); + } + } + + return handleValidationErrors(errors); + } + + @Override + public boolean validateAll() { + ValidationErrors errors = new ValidationErrors(); + + Collection components = ComponentsHelper.getComponents(this); + for (Component component : components) { + if (component instanceof Validatable) { + Validatable validatable = (Validatable) component; + if (validatable.isValidateOnCommit()) { + try { + validatable.validate(); + } catch (ValidationException e) { + if (log.isTraceEnabled()) + log.trace("Validation failed", e); + else if (log.isDebugEnabled()) + log.debug("Validation failed: " + e); + + ComponentsHelper.fillErrorMessages(validatable, e, errors); + } + } + } + } + + return handleValidationErrors(errors); + } + + protected boolean handleValidationErrors(ValidationErrors errors) { + if (errors.isEmpty()) + return true; + + DesktopComponentsHelper.focusProblemComponent(errors); + + Window window = ComponentsHelper.getWindow(wrapper); + if (window instanceof AbstractFrame) { + SwingUtilities.invokeLater(() -> { + ((AbstractFrame) window).showValidationErrors(errors); + }); + } + + return false; + } + + private DesktopWindowManager getWindowManager() { + return DesktopComponentsHelper.getTopLevelFrame((Frame) this).getWindowManager(); + } + + @Deprecated + @Override + public DialogParams getDialogParams() { + return getWindowManager().getDialogParams(); + } + + @Override + public Window openWindow(String windowAlias, WindowManager.OpenType openType, Map params) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openWindow(windowInfo, openType, params); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType) { + WindowInfo editorScreen = windowConfig.getEditorScreen(item); + return getWindowManager().openEditor(editorScreen, item, openType); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params) { + WindowInfo editorScreen = windowConfig.getEditorScreen(item); + return getWindowManager().openEditor(editorScreen, item, openType, params); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { + WindowInfo editorScreen = windowConfig.getEditorScreen(item); + return getWindowManager().openEditor(editorScreen, item, openType, params, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openEditor(windowInfo, item, openType, params, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openEditor(windowInfo, item, openType, params); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Datasource parentDs) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openEditor(windowInfo, item, openType, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openEditor(windowInfo, item, openType); + } + + @Override + public Window openWindow(String windowAlias, WindowManager.OpenType openType) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openWindow(windowInfo, openType); + } + + @Override + public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType) { + WindowInfo lookupScreen = windowConfig.getLookupScreen(entityClass); + return getWindowManager().openLookup(lookupScreen, handler, openType); + } + + @Override + public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { + WindowInfo lookupScreen = windowConfig.getLookupScreen(entityClass); + return getWindowManager().openLookup(lookupScreen, handler, openType, params); + } + + @Override + public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openLookup(windowInfo, handler, openType, params); + } + + @Override + public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + return getWindowManager().openLookup(windowInfo, handler, openType); + } + + @Override + public Frame openFrame(Component parent, String windowAlias) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + Frame wrappedFrame = ((Frame.Wrapper) wrapper).getWrappedFrame(); + return getWindowManager().openFrame(wrappedFrame, parent, windowInfo); + } + + @Override + public Frame openFrame(Component parent, String windowAlias, Map params) { + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + Frame wrappedFrame = ((Frame.Wrapper) wrapper).getWrappedFrame(); + return getWindowManager().openFrame(wrappedFrame, parent, windowInfo, params); + } + + @Override + public void detachFrame(String caption) { + if (isDetached()) { + throw new RuntimeException("Frame already detached"); + } + final java.awt.Container parent = impl.getParent(); + + detachedFrame = new DetachedFrame(caption, parent); + + for (int i = 0; i < parent.getComponentCount(); i++) { + if (impl == parent.getComponent(i)) { + componentPosition = i; + break; + } + } + + hierarchyListener = new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) == HierarchyEvent.DISPLAYABILITY_CHANGED + && !parent.isDisplayable()) { + parent.removeHierarchyListener(this); + attachFrame(); + } + } + }; + + detachedFrame.setLocationRelativeTo(DesktopComponentsHelper.getTopLevelFrame(impl)); + detachedFrame.setSize(impl.getSize()); + detachedFrame.add(impl); + detachedFrame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + parent.removeHierarchyListener(hierarchyListener); + attachFrame(); + } + }); + parent.revalidate(); + parent.repaint(); + parent.addHierarchyListener(hierarchyListener); + detachedFrame.setVisible(true); + detached = true; + for (DetachListener listener : detachListeners) { + listener.frameDetached(this); + } + } + + @Override + public void attachFrame() { + if (!isDetached()) { + throw new RuntimeException("Frame is already attached"); + } + java.awt.Container parent = detachedFrame.getParentContainer(); + parent.add(impl, componentPosition); + detachedFrame.dispose(); + parent.removeHierarchyListener(hierarchyListener); + detachedFrame = null; + detached = false; + parent.revalidate(); + parent.repaint(); + for (DetachListener listener : detachListeners) { + listener.frameAttached(this); + } + } + + @Override + public void addDetachListener(DetachListener listener) { + if (!detachListeners.contains(listener)) { + detachListeners.add(listener); + } + } + + @Override + public void removeDetachListener(DetachListener listener) { + detachListeners.remove(listener); + } + + @Override + public boolean isDetached() { + return detached; + } + + @Override + public void showMessageDialog(String title, String message, MessageType messageType) { + getWindowManager().showMessageDialog(title, message, messageType); + } + + @Override + public void showOptionDialog(String title, String message, MessageType messageType, Action[] actions) { + getWindowManager().showOptionDialog(title, message, messageType, actions); + } + + @Override + public void showOptionDialog(String title, String message, MessageType messageType, java.util.List actions) { + getWindowManager().showOptionDialog(title, message, messageType, actions.toArray(new Action[actions.size()])); + } + + @Override + public void showNotification(String caption, String description, NotificationType type) { + getWindowManager().showNotification(caption, description, type); + } + + @Override + public void showWebPage(String url, @Nullable Map params) { + getWindowManager().showWebPage(url, params); + } + + @Override + public void showNotification(String caption) { + getWindowManager().showNotification(caption); + } + + @Override + public void showNotification(String caption, NotificationType type) { + getWindowManager().showNotification(caption, type); + } + + @Override + public Frame wrapBy(Class aClass) { + try { + // First try to find an old-style constructor with Frame parameter + Constructor constructor = null; + try { + constructor = aClass.getConstructor(Frame.class); + } catch (NoSuchMethodException e) { + // + } + if (constructor != null) { + wrapper = (Frame) constructor.newInstance(this); + } else { + // If not found, get the default constructor + constructor = aClass.getConstructor(); + wrapper = (Frame) constructor.newInstance(); + ((AbstractFrame) wrapper).setWrappedFrame(this); + } + return wrapper; + } catch (Throwable e) { + throw new RuntimeException("Unable to init frame controller", e); + } + } + + @Override + public Frame getWrapper() { + return wrapper; + } + + @Override + public Component getComponent(String id) { + return ComponentsHelper.getFrameComponent(this, id); + } + + @Override + public boolean expandsWidth() { + return true; + } + + @Override + public boolean expandsHeight() { + return false; + } + + @Override + public void addAction(final Action action) { + checkNotNullArgument(action, "action must be non null"); + + actionsHolder.addAction(action); + } + + @Override + public void addAction(Action action, int index) { + checkNotNullArgument(action, "action must be non null"); + + actionsHolder.addAction(action, index); + } + + @Override + public void removeAction(@Nullable Action action) { + actionsHolder.removeAction(action); + } + + @Override + public void removeAction(@Nullable String id) { + actionsHolder.removeAction(id); + } + + @Override + public void removeAllActions() { + actionsHolder.removeAllActions(); + } + + @Override + public Collection getActions() { + return actionsHolder.getActions(); + } + + @Override + @Nullable + public Action getAction(String id) { + return actionsHolder.getAction(id); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGridLayout.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGridLayout.java index b9063bc7c4..6c927f1100 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGridLayout.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGridLayout.java @@ -1,420 +1,420 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.GridLayoutAdapter; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.GridLayout; -import com.haulmont.cuba.gui.components.MarginInfo; -import net.miginfocom.layout.CC; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.util.*; - -public class DesktopGridLayout extends DesktopAbstractComponent implements GridLayout, DesktopContainer { - - protected GridLayoutAdapter layoutAdapter; - - protected Collection ownComponents = new LinkedHashSet<>(); - protected Map componentByIds = new HashMap<>(); - protected Map captions = new HashMap<>(); - protected Map> wrappers = new HashMap<>(); - - protected boolean scheduledRepaint = false; - - public DesktopGridLayout() { - impl = new JPanel(); - assignClassDebugProperty(impl); - layoutAdapter = GridLayoutAdapter.create(impl); - } - - @Override - public float getColumnExpandRatio(int col) { - return layoutAdapter.getColumnExpandRatio(col); - } - - @Override - public void setColumnExpandRatio(int col, float ratio) { - layoutAdapter.setColumnExpandRatio(col, ratio); - } - - @Override - public float getRowExpandRatio(int row) { - return layoutAdapter.getRowExpandRatio(row); - } - - @Override - public void setRowExpandRatio(int row, float ratio) { - layoutAdapter.setRowExpandRatio(row, ratio); - } - - @Override - public void add(Component component, int col, int row) { - add(component, col, row, col, row); - } - - @Override - public void add(Component component, int col, int row, int col2, int row2) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - final JComponent composition = DesktopComponentsHelper.getComposition(component); - - // add caption first - ComponentCaption caption = null; - boolean haveDescription = false; - if (DesktopContainerHelper.hasExternalCaption(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - impl.add(caption, layoutAdapter.getCaptionConstraints(component, col, row, col2, row2)); - } else if (DesktopContainerHelper.hasExternalDescription(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - haveDescription = true; - } - //if component have description without caption, we need to wrap - // component to view Description button horizontally after component - if (haveDescription) { - JPanel wrapper = new JPanel(); - BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); - adapter.setExpandLayout(true); - adapter.setSpacing(false); - adapter.setMargin(false); - wrapper.add(composition); - wrapper.add(caption, new CC().alignY("top")); - impl.add(wrapper, layoutAdapter.getConstraints(component, col, row, col2, row2)); - wrappers.put(component, new Pair<>(wrapper, adapter)); - } else { - impl.add(composition, layoutAdapter.getConstraints(component, col, row, col2, row2)); - } - - if (component.getId() != null) { - componentByIds.put(component.getId(), component); - } - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - frame.registerComponent(component); - } - } - - ownComponents.add(component); - - DesktopContainerHelper.assignContainer(component, this); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - component.setParent(this); - - requestRepaint(); - } - - @Override - public void setFrame(Frame frame) { - super.setFrame(frame); - - if (frame != null) { - for (Component childComponent : ownComponents) { - if (childComponent instanceof BelongToFrame - && ((BelongToFrame) childComponent).getFrame() == null) { - ((BelongToFrame) childComponent).setFrame(frame); - } - } - } - } - - @Override - public int getRows() { - return layoutAdapter.getRows(); - } - - @Override - public void setRows(int rows) { - layoutAdapter.setRows(rows); - } - - @Override - public int getColumns() { - return layoutAdapter.getColumns(); - } - - @Override - public void setColumns(int columns) { - layoutAdapter.setColumns(columns); - } - - @Nullable - @Override - public Component getComponent(int columnIndex, int rowIndex) { - return null; - } - - @Nullable - @Override - public Area getComponentArea(Component component) { - return null; - } - - @Override - public void add(Component component) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - // captions not added here - final JComponent composition = DesktopComponentsHelper.getComposition(component); - impl.add(composition, layoutAdapter.getConstraints(component)); - - if (component.getId() != null) { - componentByIds.put(component.getId(), component); - } - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - frame.registerComponent(component); - } - } - - ownComponents.add(component); - - DesktopContainerHelper.assignContainer(component, this); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - component.setParent(this); - - requestRepaint(); - } - - protected void requestRepaint() { - if (!scheduledRepaint) { - SwingUtilities.invokeLater(() -> { - impl.revalidate(); - impl.repaint(); - - scheduledRepaint = false; - }); - - scheduledRepaint = true; - } - } - - @Override - public void remove(Component component) { - if (wrappers.containsKey(component)) { - impl.remove(wrappers.get(component).getFirst()); - wrappers.remove(component); - } else { - impl.remove(DesktopComponentsHelper.getComposition(component)); - } - if (captions.containsKey(component)) { - impl.remove(captions.get(component)); - captions.remove(component); - - } - if (component.getId() != null) { - componentByIds.remove(component.getId()); - } - ownComponents.remove(component); - - DesktopContainerHelper.assignContainer(component, null); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - component.setParent(null); - - requestRepaint(); - } - - @Override - public void removeAll() { - wrappers.clear(); - impl.removeAll(); - componentByIds.clear(); - captions.clear(); - - List components = new ArrayList<>(ownComponents); - ownComponents.clear(); - - for (Component component : components) { - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - - DesktopContainerHelper.assignContainer(component, null); - } - - requestRepaint(); - } - - @Override - public Component getOwnComponent(String id) { - return componentByIds.get(id); - } - - @Nullable - @Override - public Component getComponent(String id) { - return ComponentsHelper.getComponent(this, id); - } - - @Override - public Collection getOwnComponents() { - return Collections.unmodifiableCollection(ownComponents); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public void setMargin(MarginInfo marginInfo) { - layoutAdapter.setMargin(marginInfo); - } - - @Override - public MarginInfo getMargin() { - return layoutAdapter.getMargin(); - } - - @Override - public void setSpacing(boolean enabled) { - layoutAdapter.setSpacing(enabled); - } - - @Override - public boolean getSpacing() { - return layoutAdapter.getSpacing(); - } - - @Override - public void updateComponent(Component child) { - boolean componentReAdded = false; - - if (DesktopContainerHelper.mayHaveExternalCaption(child)) { - if (captions.containsKey(child) - && !DesktopContainerHelper.hasExternalCaption(child) - && !DesktopContainerHelper.hasExternalDescription(child)) { - reAddChild(child); - componentReAdded = true; - } else if (!captions.containsKey(child) - && (DesktopContainerHelper.hasExternalCaption(child) - || DesktopContainerHelper.hasExternalDescription(child))) { - reAddChild(child); - componentReAdded = true; - } else if (captions.containsKey(child)) { - ComponentCaption caption = captions.get(child); - caption.update(); - if (!wrappers.containsKey(child)) { - CC c = (CC) layoutAdapter.getConstraints(child); - layoutAdapter.updateConstraints(caption, layoutAdapter.getCaptionConstraints(child, - c.getCellX(), c.getCellY(), c.getCellX(), c.getCellY())); - } - } - } - - if (!componentReAdded) { - JComponent composition; - if (wrappers.containsKey(child)) { - composition = wrappers.get(child).getFirst(); - } else { - composition = DesktopComponentsHelper.getComposition(child); - } - layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); - } - - requestRepaint(); - - requestContainerUpdate(); - } - - protected void reAddChild(Component child) { - CC childCC = (CC) layoutAdapter.getConstraints(child); - int col1 = childCC.getCellX(); - int row1 = childCC.getCellY(); - int spanX = childCC.getSpanX(); - int spanY = childCC.getSpanY(); - - // readd component - int col2 = spanX - 1 + col1; - int row2 = spanY - 1 + row1; - - remove(child); - add(child, col1, row1, col2, row2); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - for (Component component : ownComponents) { - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); - } - } - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - @Override - public void addLayoutClickListener(LayoutClickListener listener) { - } - - @Override - public void removeLayoutClickListener(LayoutClickListener listener) { - } - - @Override - public void addShortcutAction(ShortcutAction action) { - // do nothing - } - - @Override - public void removeShortcutAction(ShortcutAction action) { - // do nothing - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.GridLayoutAdapter; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.GridLayout; +import com.haulmont.cuba.gui.components.MarginInfo; +import net.miginfocom.layout.CC; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.util.*; + +public class DesktopGridLayout extends DesktopAbstractComponent implements GridLayout, DesktopContainer { + + protected GridLayoutAdapter layoutAdapter; + + protected Collection ownComponents = new LinkedHashSet<>(); + protected Map componentByIds = new HashMap<>(); + protected Map captions = new HashMap<>(); + protected Map> wrappers = new HashMap<>(); + + protected boolean scheduledRepaint = false; + + public DesktopGridLayout() { + impl = new JPanel(); + assignClassDebugProperty(impl); + layoutAdapter = GridLayoutAdapter.create(impl); + } + + @Override + public float getColumnExpandRatio(int col) { + return layoutAdapter.getColumnExpandRatio(col); + } + + @Override + public void setColumnExpandRatio(int col, float ratio) { + layoutAdapter.setColumnExpandRatio(col, ratio); + } + + @Override + public float getRowExpandRatio(int row) { + return layoutAdapter.getRowExpandRatio(row); + } + + @Override + public void setRowExpandRatio(int row, float ratio) { + layoutAdapter.setRowExpandRatio(row, ratio); + } + + @Override + public void add(Component component, int col, int row) { + add(component, col, row, col, row); + } + + @Override + public void add(Component component, int col, int row, int col2, int row2) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + final JComponent composition = DesktopComponentsHelper.getComposition(component); + + // add caption first + ComponentCaption caption = null; + boolean haveDescription = false; + if (DesktopContainerHelper.hasExternalCaption(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + impl.add(caption, layoutAdapter.getCaptionConstraints(component, col, row, col2, row2)); + } else if (DesktopContainerHelper.hasExternalDescription(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + haveDescription = true; + } + //if component have description without caption, we need to wrap + // component to view Description button horizontally after component + if (haveDescription) { + JPanel wrapper = new JPanel(); + BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); + adapter.setExpandLayout(true); + adapter.setSpacing(false); + adapter.setMargin(false); + wrapper.add(composition); + wrapper.add(caption, new CC().alignY("top")); + impl.add(wrapper, layoutAdapter.getConstraints(component, col, row, col2, row2)); + wrappers.put(component, new Pair<>(wrapper, adapter)); + } else { + impl.add(composition, layoutAdapter.getConstraints(component, col, row, col2, row2)); + } + + if (component.getId() != null) { + componentByIds.put(component.getId(), component); + } + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + frame.registerComponent(component); + } + } + + ownComponents.add(component); + + DesktopContainerHelper.assignContainer(component, this); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + component.setParent(this); + + requestRepaint(); + } + + @Override + public void setFrame(Frame frame) { + super.setFrame(frame); + + if (frame != null) { + for (Component childComponent : ownComponents) { + if (childComponent instanceof BelongToFrame + && ((BelongToFrame) childComponent).getFrame() == null) { + ((BelongToFrame) childComponent).setFrame(frame); + } + } + } + } + + @Override + public int getRows() { + return layoutAdapter.getRows(); + } + + @Override + public void setRows(int rows) { + layoutAdapter.setRows(rows); + } + + @Override + public int getColumns() { + return layoutAdapter.getColumns(); + } + + @Override + public void setColumns(int columns) { + layoutAdapter.setColumns(columns); + } + + @Nullable + @Override + public Component getComponent(int columnIndex, int rowIndex) { + return null; + } + + @Nullable + @Override + public Area getComponentArea(Component component) { + return null; + } + + @Override + public void add(Component component) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + // captions not added here + final JComponent composition = DesktopComponentsHelper.getComposition(component); + impl.add(composition, layoutAdapter.getConstraints(component)); + + if (component.getId() != null) { + componentByIds.put(component.getId(), component); + } + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + frame.registerComponent(component); + } + } + + ownComponents.add(component); + + DesktopContainerHelper.assignContainer(component, this); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + component.setParent(this); + + requestRepaint(); + } + + protected void requestRepaint() { + if (!scheduledRepaint) { + SwingUtilities.invokeLater(() -> { + impl.revalidate(); + impl.repaint(); + + scheduledRepaint = false; + }); + + scheduledRepaint = true; + } + } + + @Override + public void remove(Component component) { + if (wrappers.containsKey(component)) { + impl.remove(wrappers.get(component).getFirst()); + wrappers.remove(component); + } else { + impl.remove(DesktopComponentsHelper.getComposition(component)); + } + if (captions.containsKey(component)) { + impl.remove(captions.get(component)); + captions.remove(component); + + } + if (component.getId() != null) { + componentByIds.remove(component.getId()); + } + ownComponents.remove(component); + + DesktopContainerHelper.assignContainer(component, null); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + component.setParent(null); + + requestRepaint(); + } + + @Override + public void removeAll() { + wrappers.clear(); + impl.removeAll(); + componentByIds.clear(); + captions.clear(); + + List components = new ArrayList<>(ownComponents); + ownComponents.clear(); + + for (Component component : components) { + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + + DesktopContainerHelper.assignContainer(component, null); + } + + requestRepaint(); + } + + @Override + public Component getOwnComponent(String id) { + return componentByIds.get(id); + } + + @Nullable + @Override + public Component getComponent(String id) { + return ComponentsHelper.getComponent(this, id); + } + + @Override + public Collection getOwnComponents() { + return Collections.unmodifiableCollection(ownComponents); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public void setMargin(MarginInfo marginInfo) { + layoutAdapter.setMargin(marginInfo); + } + + @Override + public MarginInfo getMargin() { + return layoutAdapter.getMargin(); + } + + @Override + public void setSpacing(boolean enabled) { + layoutAdapter.setSpacing(enabled); + } + + @Override + public boolean getSpacing() { + return layoutAdapter.getSpacing(); + } + + @Override + public void updateComponent(Component child) { + boolean componentReAdded = false; + + if (DesktopContainerHelper.mayHaveExternalCaption(child)) { + if (captions.containsKey(child) + && !DesktopContainerHelper.hasExternalCaption(child) + && !DesktopContainerHelper.hasExternalDescription(child)) { + reAddChild(child); + componentReAdded = true; + } else if (!captions.containsKey(child) + && (DesktopContainerHelper.hasExternalCaption(child) + || DesktopContainerHelper.hasExternalDescription(child))) { + reAddChild(child); + componentReAdded = true; + } else if (captions.containsKey(child)) { + ComponentCaption caption = captions.get(child); + caption.update(); + if (!wrappers.containsKey(child)) { + CC c = (CC) layoutAdapter.getConstraints(child); + layoutAdapter.updateConstraints(caption, layoutAdapter.getCaptionConstraints(child, + c.getCellX(), c.getCellY(), c.getCellX(), c.getCellY())); + } + } + } + + if (!componentReAdded) { + JComponent composition; + if (wrappers.containsKey(child)) { + composition = wrappers.get(child).getFirst(); + } else { + composition = DesktopComponentsHelper.getComposition(child); + } + layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); + } + + requestRepaint(); + + requestContainerUpdate(); + } + + protected void reAddChild(Component child) { + CC childCC = (CC) layoutAdapter.getConstraints(child); + int col1 = childCC.getCellX(); + int row1 = childCC.getCellY(); + int spanX = childCC.getSpanX(); + int spanY = childCC.getSpanY(); + + // readd component + int col2 = spanX - 1 + col1; + int row2 = spanY - 1 + row1; + + remove(child); + add(child, col1, row1, col2, row2); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + for (Component component : ownComponents) { + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); + } + } + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + @Override + public void addLayoutClickListener(LayoutClickListener listener) { + } + + @Override + public void removeLayoutClickListener(LayoutClickListener listener) { + } + + @Override + public void addShortcutAction(ShortcutAction action) { + // do nothing + } + + @Override + public void removeShortcutAction(ShortcutAction action) { + // do nothing + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupBox.java index f329d35fa9..f8d772b9a9 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupBox.java @@ -1,260 +1,260 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; -import com.haulmont.cuba.gui.components.GroupBoxLayout; -import com.haulmont.cuba.gui.components.MarginInfo; -import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper; -import org.apache.commons.lang.BooleanUtils; -import org.dom4j.Element; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class DesktopGroupBox extends DesktopAbstractBox implements GroupBoxLayout, AutoExpanding { - - protected Orientation orientation = Orientation.VERTICAL; - - protected CollapsiblePanel collapsiblePanel; - - protected List expandedStateChangeListeners; - - protected boolean settingsEnabled = true; - protected boolean showAsPanel; - protected MarginInfo outerMarginInfo; - - public DesktopGroupBox() { - collapsiblePanel = new CollapsiblePanel(super.getComposition()); - collapsiblePanel.addCollapseListener(new CollapsiblePanel.CollapseListener() { - @Override - public void collapsed() { - fireExpandStateChange(false); - } - - @Override - public void expanded() { - fireExpandStateChange(true); - } - }); - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - - setWidth("100%"); - } - - @Override - public boolean isExpanded() { - return collapsiblePanel.isExpanded(); - } - - @Override - public ExpandDirection getExpandDirection() { - return orientation == Orientation.HORIZONTAL ? ExpandDirection.HORIZONTAL : ExpandDirection.VERTICAL; - } - - @Override - public void setExpanded(boolean expanded) { - collapsiblePanel.setExpanded(expanded); - } - - @Override - public boolean isCollapsable() { - return collapsiblePanel.isCollapsable(); - } - - @Override - public void setCollapsable(boolean collapsible) { - collapsiblePanel.setCollapsible(collapsible); - } - - @Override - public void addListener(ExpandListener listener) { - addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void removeListener(ExpandListener listener) { - removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void addListener(CollapseListener listener) { - addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void removeListener(CollapseListener listener) { - removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); - } - - @Override - public void addExpandedStateChangeListener(ExpandedStateChangeListener listener) { - if (expandedStateChangeListeners == null) { - expandedStateChangeListeners = new ArrayList<>(); - } - if (!expandedStateChangeListeners.contains(listener)) { - expandedStateChangeListeners.add(listener); - } - } - - @Override - public void removeExpandedStateChangeListener(ExpandedStateChangeListener listener) { - if (expandedStateChangeListeners != null) { - expandedStateChangeListeners.remove(listener); - } - } - - protected void fireExpandStateChange(boolean expanded) { - if (expandedStateChangeListeners != null && !expandedStateChangeListeners.isEmpty()) { - ExpandedStateChangeEvent event = new ExpandedStateChangeEvent(this, expanded); - - for (ExpandedStateChangeListener listener : new ArrayList<>(expandedStateChangeListeners)) { - listener.expandedStateChanged(event); - } - } - } - - @Override - public String getCaption() { - return collapsiblePanel.getCaption(); - } - - @Override - public void setCaption(String caption) { - collapsiblePanel.setCaption(caption); - } - - @Override - public String getDescription() { - return null; - } - - @Override - public void setDescription(String description) { - } - - @Override - public boolean isBorderVisible() { - return true; - } - - @Override - public void setBorderVisible(boolean borderVisible) { - throw new UnsupportedOperationException(); - } - - @Override - public JComponent getComposition() { - return collapsiblePanel; - } - - @Override - public void applySettings(Element element) { - if (isSettingsEnabled()) { - Element groupBoxElement = element.element("groupBox"); - if (groupBoxElement != null) { - String expanded = groupBoxElement.attributeValue("expanded"); - if (expanded != null) { - setExpanded(Boolean.parseBoolean(expanded)); - } - } - } - } - - @Override - public boolean saveSettings(Element element) { - if (!isSettingsEnabled()) { - return false; - } - - Element groupBoxElement = element.element("groupBox"); - if (groupBoxElement != null) { - element.remove(groupBoxElement); - } - groupBoxElement = element.addElement("groupBox"); - groupBoxElement.addAttribute("expanded", BooleanUtils.toStringTrueFalse(isExpanded())); - return true; - } - - @Override - public boolean isSettingsEnabled() { - return settingsEnabled; - } - - @Override - public void setSettingsEnabled(boolean settingsEnabled) { - this.settingsEnabled = settingsEnabled; - } - - @Override - public Orientation getOrientation() { - return orientation; - } - - @Override - public void setOrientation(Orientation orientation) { - Objects.requireNonNull(orientation); - if (orientation == Orientation.VERTICAL) { - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - } else { - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); - } - this.orientation = orientation; - - requestContainerUpdate(); - - collapsiblePanel.revalidate(); - collapsiblePanel.repaint(); - } - - @Override - public void setShowAsPanel(boolean showAsPanel) { - this.showAsPanel = showAsPanel; - } - - @Override - public boolean isShowAsPanel() { - return showAsPanel; - } - - @Override - public boolean expandsWidth() { - return orientation == Orientation.VERTICAL; - } - - @Override - public boolean expandsHeight() { - return orientation == Orientation.HORIZONTAL; - } - - @Override - public void setOuterMargin(MarginInfo marginInfo) { - outerMarginInfo = marginInfo; - } - - @Override - public MarginInfo getOuterMargin() { - if (outerMarginInfo == null) { - outerMarginInfo = new MarginInfo(false); - } - return outerMarginInfo; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; +import com.haulmont.cuba.gui.components.GroupBoxLayout; +import com.haulmont.cuba.gui.components.MarginInfo; +import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper; +import org.apache.commons.lang.BooleanUtils; +import org.dom4j.Element; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class DesktopGroupBox extends DesktopAbstractBox implements GroupBoxLayout, AutoExpanding { + + protected Orientation orientation = Orientation.VERTICAL; + + protected CollapsiblePanel collapsiblePanel; + + protected List expandedStateChangeListeners; + + protected boolean settingsEnabled = true; + protected boolean showAsPanel; + protected MarginInfo outerMarginInfo; + + public DesktopGroupBox() { + collapsiblePanel = new CollapsiblePanel(super.getComposition()); + collapsiblePanel.addCollapseListener(new CollapsiblePanel.CollapseListener() { + @Override + public void collapsed() { + fireExpandStateChange(false); + } + + @Override + public void expanded() { + fireExpandStateChange(true); + } + }); + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + + setWidth("100%"); + } + + @Override + public boolean isExpanded() { + return collapsiblePanel.isExpanded(); + } + + @Override + public ExpandDirection getExpandDirection() { + return orientation == Orientation.HORIZONTAL ? ExpandDirection.HORIZONTAL : ExpandDirection.VERTICAL; + } + + @Override + public void setExpanded(boolean expanded) { + collapsiblePanel.setExpanded(expanded); + } + + @Override + public boolean isCollapsable() { + return collapsiblePanel.isCollapsable(); + } + + @Override + public void setCollapsable(boolean collapsible) { + collapsiblePanel.setCollapsible(collapsible); + } + + @Override + public void addListener(ExpandListener listener) { + addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void removeListener(ExpandListener listener) { + removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void addListener(CollapseListener listener) { + addExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void removeListener(CollapseListener listener) { + removeExpandedStateChangeListener(new ComponentExpandCollapseListenerWrapper(listener)); + } + + @Override + public void addExpandedStateChangeListener(ExpandedStateChangeListener listener) { + if (expandedStateChangeListeners == null) { + expandedStateChangeListeners = new ArrayList<>(); + } + if (!expandedStateChangeListeners.contains(listener)) { + expandedStateChangeListeners.add(listener); + } + } + + @Override + public void removeExpandedStateChangeListener(ExpandedStateChangeListener listener) { + if (expandedStateChangeListeners != null) { + expandedStateChangeListeners.remove(listener); + } + } + + protected void fireExpandStateChange(boolean expanded) { + if (expandedStateChangeListeners != null && !expandedStateChangeListeners.isEmpty()) { + ExpandedStateChangeEvent event = new ExpandedStateChangeEvent(this, expanded); + + for (ExpandedStateChangeListener listener : new ArrayList<>(expandedStateChangeListeners)) { + listener.expandedStateChanged(event); + } + } + } + + @Override + public String getCaption() { + return collapsiblePanel.getCaption(); + } + + @Override + public void setCaption(String caption) { + collapsiblePanel.setCaption(caption); + } + + @Override + public String getDescription() { + return null; + } + + @Override + public void setDescription(String description) { + } + + @Override + public boolean isBorderVisible() { + return true; + } + + @Override + public void setBorderVisible(boolean borderVisible) { + throw new UnsupportedOperationException(); + } + + @Override + public JComponent getComposition() { + return collapsiblePanel; + } + + @Override + public void applySettings(Element element) { + if (isSettingsEnabled()) { + Element groupBoxElement = element.element("groupBox"); + if (groupBoxElement != null) { + String expanded = groupBoxElement.attributeValue("expanded"); + if (expanded != null) { + setExpanded(Boolean.parseBoolean(expanded)); + } + } + } + } + + @Override + public boolean saveSettings(Element element) { + if (!isSettingsEnabled()) { + return false; + } + + Element groupBoxElement = element.element("groupBox"); + if (groupBoxElement != null) { + element.remove(groupBoxElement); + } + groupBoxElement = element.addElement("groupBox"); + groupBoxElement.addAttribute("expanded", BooleanUtils.toStringTrueFalse(isExpanded())); + return true; + } + + @Override + public boolean isSettingsEnabled() { + return settingsEnabled; + } + + @Override + public void setSettingsEnabled(boolean settingsEnabled) { + this.settingsEnabled = settingsEnabled; + } + + @Override + public Orientation getOrientation() { + return orientation; + } + + @Override + public void setOrientation(Orientation orientation) { + Objects.requireNonNull(orientation); + if (orientation == Orientation.VERTICAL) { + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + } else { + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); + } + this.orientation = orientation; + + requestContainerUpdate(); + + collapsiblePanel.revalidate(); + collapsiblePanel.repaint(); + } + + @Override + public void setShowAsPanel(boolean showAsPanel) { + this.showAsPanel = showAsPanel; + } + + @Override + public boolean isShowAsPanel() { + return showAsPanel; + } + + @Override + public boolean expandsWidth() { + return orientation == Orientation.VERTICAL; + } + + @Override + public boolean expandsHeight() { + return orientation == Orientation.HORIZONTAL; + } + + @Override + public void setOuterMargin(MarginInfo marginInfo) { + outerMarginInfo = marginInfo; + } + + @Override + public MarginInfo getOuterMargin() { + if (outerMarginInfo == null) { + outerMarginInfo = new MarginInfo(false); + } + return outerMarginInfo; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupTable.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupTable.java index 84fd6a0885..cb11cc4fc2 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupTable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopGroupTable.java @@ -1,101 +1,101 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.gui.components.GroupTable; -import com.haulmont.cuba.gui.data.GroupDatasource; -import com.haulmont.cuba.gui.data.GroupInfo; - -public class DesktopGroupTable - extends DesktopTable - implements GroupTable { - - protected boolean showItemsCountForGroup = true; - - @Override - public GroupDatasource getDatasource() { - return (GroupDatasource) super.getDatasource(); - } - - @Override - public void groupBy(Object[] properties) { - } - - @Override - public boolean getColumnGroupAllowed(String columnId) { - return false; - } - - @Override - public void setColumnGroupAllowed(String columnId, boolean allowed) { - } - - @Override - public boolean getColumnGroupAllowed(Column column) { - return false; - } - - @Override - public void setColumnGroupAllowed(Column column, boolean allowed) { - } - - @Override - public void expandAll() { - } - - @Override - public void expand(GroupInfo groupId) { - } - - @Override - public void expandPath(Entity item) { - } - - @Override - public void collapseAll() { - } - - @Override - public void collapse(GroupInfo groupId) { - } - - @Override - public boolean isExpanded(GroupInfo groupId) { - return true; - } - - @Override - public boolean isFixedGrouping() { - return false; - } - - @Override - public void setFixedGrouping(boolean groupingByUserEnabled) { - } - - @Override - public boolean isShowItemsCountForGroup() { - return showItemsCountForGroup; - } - - @Override - public void setShowItemsCountForGroup(boolean showItemsCountForGroup) { - this.showItemsCountForGroup = showItemsCountForGroup; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.gui.components.GroupTable; +import com.haulmont.cuba.gui.data.GroupDatasource; +import com.haulmont.cuba.gui.data.GroupInfo; + +public class DesktopGroupTable + extends DesktopTable + implements GroupTable { + + protected boolean showItemsCountForGroup = true; + + @Override + public GroupDatasource getDatasource() { + return (GroupDatasource) super.getDatasource(); + } + + @Override + public void groupBy(Object[] properties) { + } + + @Override + public boolean getColumnGroupAllowed(String columnId) { + return false; + } + + @Override + public void setColumnGroupAllowed(String columnId, boolean allowed) { + } + + @Override + public boolean getColumnGroupAllowed(Column column) { + return false; + } + + @Override + public void setColumnGroupAllowed(Column column, boolean allowed) { + } + + @Override + public void expandAll() { + } + + @Override + public void expand(GroupInfo groupId) { + } + + @Override + public void expandPath(Entity item) { + } + + @Override + public void collapseAll() { + } + + @Override + public void collapse(GroupInfo groupId) { + } + + @Override + public boolean isExpanded(GroupInfo groupId) { + return true; + } + + @Override + public boolean isFixedGrouping() { + return false; + } + + @Override + public void setFixedGrouping(boolean groupingByUserEnabled) { + } + + @Override + public boolean isShowItemsCountForGroup() { + return showItemsCountForGroup; + } + + @Override + public void setShowItemsCountForGroup(boolean showItemsCountForGroup) { + this.showItemsCountForGroup = showItemsCountForGroup; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopHBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopHBox.java index bd766bfd1e..4881dd43f8 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopHBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopHBox.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.gui.components.HBoxLayout; - -public class DesktopHBox extends DesktopAbstractBox implements AutoExpanding, HBoxLayout { - - public DesktopHBox() { - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); - setHeight("-1px"); // fix layout inside a scrollbox if the height is not set - } - - @Override - public boolean expandsWidth() { - return false; - } - - @Override - public boolean expandsHeight() { - return true; - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - layoutAdapter.setExpandLayout(!widthSize.isOwnSize()); // expand layout if width not -1 - } - - @Override - public ExpandDirection getExpandDirection() { - return ExpandDirection.HORIZONTAL; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.gui.components.HBoxLayout; + +public class DesktopHBox extends DesktopAbstractBox implements AutoExpanding, HBoxLayout { + + public DesktopHBox() { + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.X); + setHeight("-1px"); // fix layout inside a scrollbox if the height is not set + } + + @Override + public boolean expandsWidth() { + return false; + } + + @Override + public boolean expandsHeight() { + return true; + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + layoutAdapter.setExpandLayout(!widthSize.isOwnSize()); // expand layout if width not -1 + } + + @Override + public ExpandDirection getExpandDirection() { + return ExpandDirection.HORIZONTAL; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLabel.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLabel.java index 421d97b1bc..ae731955f1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLabel.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLabel.java @@ -1,307 +1,307 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.Formatter; -import com.haulmont.cuba.gui.components.Label; -import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.ValueListener; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringEscapeUtils; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -public class DesktopLabel extends DesktopAbstractComponent implements Label { - - protected Datasource datasource; - protected MetaProperty metaProperty; - protected MetaPropertyPath metaPropertyPath; - - protected List valueChangeListeners = new ArrayList<>(); - - protected DefaultValueFormatter valueFormatter; - - protected Object prevValue; - - protected boolean updatingInstance = false; - - protected boolean htmlEnabled = false; - - protected String labelText = ""; - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - public DesktopLabel() { - impl = new JLabel(); - impl.setFocusable(false); - setAlignment(Alignment.MIDDLE_LEFT); - - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - Locale locale = sessionSource.getLocale(); - valueFormatter = new DefaultValueFormatter(locale); - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - @Override - public void setDatasource(Datasource datasource, String property) { - this.datasource = datasource; - - if (datasource == null) { - setValue(null); - return; - } - - resolveMetaPropertyPath(datasource.getMetaClass(), property); - - valueFormatter.setMetaProperty(metaProperty); - - itemChangeListener = e -> { - if (updatingInstance) { - return; - } - - Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); - updateComponent(value); - fireChangeListeners(value); - }; - //noinspection unchecked - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) { - return; - } - - if (e.getProperty().equals(metaPropertyPath.toString())) { - updateComponent(e.getValue()); - fireChangeListeners(e.getValue()); - } - }; - //noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { - Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); - updateComponent(newValue); - fireChangeListeners(newValue); - } - } - - @Override - public boolean isEditable() { - return false; - } - - @Override - public void setEditable(boolean editable) { - } - - @Override - public Formatter getFormatter() { - return valueFormatter.getFormatter(); - } - - @Override - public void setFormatter(Formatter formatter) { - valueFormatter.setFormatter(formatter); - updateComponent(prevValue); - } - - @Override - public T getValue() { - return (T) prevValue; - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (!ObjectUtils.equals(prevValue, value)) { - updateInstance(value); - updateComponent(value); - fireChangeListeners(value); - } - } - - protected void updateInstance(Object value) { - if (updatingInstance) { - return; - } - - if (ObjectUtils.equals(prevValue, value)) { - return; - } - - updatingInstance = true; - try { - if ((datasource != null) && (metaPropertyPath != null)) { - if (datasource.getItem() != null) { - InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); - } - } - } finally { - updatingInstance = false; - } - } - - protected void updateComponent(Object value) { - String text = valueFormatter.formatValue(value); - this.labelText = text; - updateLabel(text); - } - - private void updateLabel(String text) { - if (!htmlEnabled) { - text = StringEscapeUtils.escapeHtml(text); - if (getWidth() > 0 && getHeight() <= 0) { - text = ComponentsHelper.preprocessHtmlMessage("" + text + ""); - } else { - text = ComponentsHelper.preprocessHtmlMessage("" + text + ""); - } - } else { - text = "" + text + ""; - } - impl.setText(text); - } - - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = newValue; - if (!ObjectUtils.equals(oldValue, newValue)) { - fireValueChanged(oldValue, newValue); - } - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - - updateLabel(this.labelText); - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - - updateLabel(this.labelText); - } - - @Override - public void addListener(ValueListener listener) { - addValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - @Override - public void removeListener(ValueListener listener) { - removeValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - @Override - public void addValueChangeListener(ValueChangeListener listener) { - if (!valueChangeListeners.contains(listener)) { - valueChangeListeners.add(listener); - } - } - - @Override - public void removeValueChangeListener(ValueChangeListener listener) { - valueChangeListeners.remove(listener); - } - - protected void fireValueChanged(Object prevValue, Object value) { - for (ValueChangeListener listener : new ArrayList<>(valueChangeListeners)) { - listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); - } - } - - @Override - public boolean isHtmlEnabled() { - return htmlEnabled; - } - - @Override - public void setHtmlEnabled(boolean htmlEnabled) { - this.htmlEnabled = htmlEnabled; - } - - @Override - public String getRawValue() { - return this.labelText; - } - - protected void resolveMetaPropertyPath(MetaClass metaClass, String property) { - metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) - .resolveMetaPropertyPath(metaClass, property); - Preconditions.checkNotNullArgument(metaPropertyPath, "Could not resolve property path '%s' in '%s'", property, metaClass); - this.metaProperty = metaPropertyPath.getMetaProperty(); - } - - @Override - public String getCaption() { - return null; - } - - @Override - public void setCaption(String caption) { - // do nothing - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.Formatter; +import com.haulmont.cuba.gui.components.Label; +import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.ValueListener; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringEscapeUtils; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class DesktopLabel extends DesktopAbstractComponent implements Label { + + protected Datasource datasource; + protected MetaProperty metaProperty; + protected MetaPropertyPath metaPropertyPath; + + protected List valueChangeListeners = new ArrayList<>(); + + protected DefaultValueFormatter valueFormatter; + + protected Object prevValue; + + protected boolean updatingInstance = false; + + protected boolean htmlEnabled = false; + + protected String labelText = ""; + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + public DesktopLabel() { + impl = new JLabel(); + impl.setFocusable(false); + setAlignment(Alignment.MIDDLE_LEFT); + + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + Locale locale = sessionSource.getLocale(); + valueFormatter = new DefaultValueFormatter(locale); + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + @Override + public void setDatasource(Datasource datasource, String property) { + this.datasource = datasource; + + if (datasource == null) { + setValue(null); + return; + } + + resolveMetaPropertyPath(datasource.getMetaClass(), property); + + valueFormatter.setMetaProperty(metaProperty); + + itemChangeListener = e -> { + if (updatingInstance) { + return; + } + + Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); + updateComponent(value); + fireChangeListeners(value); + }; + //noinspection unchecked + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) { + return; + } + + if (e.getProperty().equals(metaPropertyPath.toString())) { + updateComponent(e.getValue()); + fireChangeListeners(e.getValue()); + } + }; + //noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { + Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); + updateComponent(newValue); + fireChangeListeners(newValue); + } + } + + @Override + public boolean isEditable() { + return false; + } + + @Override + public void setEditable(boolean editable) { + } + + @Override + public Formatter getFormatter() { + return valueFormatter.getFormatter(); + } + + @Override + public void setFormatter(Formatter formatter) { + valueFormatter.setFormatter(formatter); + updateComponent(prevValue); + } + + @Override + public T getValue() { + return (T) prevValue; + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (!ObjectUtils.equals(prevValue, value)) { + updateInstance(value); + updateComponent(value); + fireChangeListeners(value); + } + } + + protected void updateInstance(Object value) { + if (updatingInstance) { + return; + } + + if (ObjectUtils.equals(prevValue, value)) { + return; + } + + updatingInstance = true; + try { + if ((datasource != null) && (metaPropertyPath != null)) { + if (datasource.getItem() != null) { + InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); + } + } + } finally { + updatingInstance = false; + } + } + + protected void updateComponent(Object value) { + String text = valueFormatter.formatValue(value); + this.labelText = text; + updateLabel(text); + } + + private void updateLabel(String text) { + if (!htmlEnabled) { + text = StringEscapeUtils.escapeHtml(text); + if (getWidth() > 0 && getHeight() <= 0) { + text = ComponentsHelper.preprocessHtmlMessage("" + text + ""); + } else { + text = ComponentsHelper.preprocessHtmlMessage("" + text + ""); + } + } else { + text = "" + text + ""; + } + impl.setText(text); + } + + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = newValue; + if (!ObjectUtils.equals(oldValue, newValue)) { + fireValueChanged(oldValue, newValue); + } + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + + updateLabel(this.labelText); + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + + updateLabel(this.labelText); + } + + @Override + public void addListener(ValueListener listener) { + addValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + @Override + public void removeListener(ValueListener listener) { + removeValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + if (!valueChangeListeners.contains(listener)) { + valueChangeListeners.add(listener); + } + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + valueChangeListeners.remove(listener); + } + + protected void fireValueChanged(Object prevValue, Object value) { + for (ValueChangeListener listener : new ArrayList<>(valueChangeListeners)) { + listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); + } + } + + @Override + public boolean isHtmlEnabled() { + return htmlEnabled; + } + + @Override + public void setHtmlEnabled(boolean htmlEnabled) { + this.htmlEnabled = htmlEnabled; + } + + @Override + public String getRawValue() { + return this.labelText; + } + + protected void resolveMetaPropertyPath(MetaClass metaClass, String property) { + metaPropertyPath = AppBeans.get(MetadataTools.NAME, MetadataTools.class) + .resolveMetaPropertyPath(metaClass, property); + Preconditions.checkNotNullArgument(metaPropertyPath, "Could not resolve property path '%s' in '%s'", property, metaClass); + this.metaProperty = metaPropertyPath.getMetaProperty(); + } + + @Override + public String getCaption() { + return null; + } + + @Override + public void setCaption(String caption) { + // do nothing + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLinkButton.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLinkButton.java index eb120753ac..500621d07b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLinkButton.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLinkButton.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.LinkButton; -import org.jdesktop.swingx.JXHyperlink; - -import javax.swing.*; - -public class DesktopLinkButton extends DesktopButton implements LinkButton { - @Override - protected JButton createImplementation() { - final JXHyperlink link = new JXHyperlink(); - return link; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.LinkButton; +import org.jdesktop.swingx.JXHyperlink; + +import javax.swing.*; + +public class DesktopLinkButton extends DesktopButton implements LinkButton { + @Override + protected JButton createImplementation() { + final JXHyperlink link = new JXHyperlink(); + return link; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupField.java index 9b08ae08cf..ba87c73986 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupField.java @@ -1,801 +1,801 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import ca.odell.glazedlists.BasicEventList; -import ca.odell.glazedlists.matchers.TextMatcherEditor; -import ca.odell.glazedlists.swing.AutoCompleteSupport; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.vcl.ExtendedComboBox; -import com.haulmont.cuba.desktop.sys.vcl.UserSelectionHandler; -import com.haulmont.cuba.gui.components.CaptionMode; -import com.haulmont.cuba.gui.components.LookupField; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import java.util.List; - -public class DesktopLookupField extends DesktopAbstractOptionsField implements LookupField, UserSelectionHandler { - - protected static final FilterMode DEFAULT_FILTER_MODE = FilterMode.CONTAINS; - - protected BasicEventList items = new BasicEventList<>(); - protected AutoCompleteSupport autoComplete; - protected String caption; - protected NewOptionHandler newOptionHandler; - - protected boolean optionsInitialized; - protected boolean resetValueState = false; - - protected boolean newOptionAllowed; - protected boolean settingValue; - - protected boolean disableActionListener = false; - - protected Object nullOption; - - protected ExtendedComboBox comboBox; - protected JTextField textField; - - protected JPanel composition; - - protected DefaultValueFormatter valueFormatter; - protected String inputPrompt; - protected boolean textInputAllowed = true; - - protected boolean nullOptionVisible = true; - - protected List userSelectionListeners = null; // lazy initialized list - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - // just stub - protected OptionIconProvider optionIconProvider; - - public DesktopLookupField() { - composition = new JPanel(); - composition.setLayout(new BorderLayout()); - composition.setFocusable(false); - - comboBox = new ExtendedComboBox() { - @Override - public void flushValue() { - super.flushValue(); - - flushSelectedValue(); - } - }; - comboBox.setEditable(true); - comboBox.setPrototypeDisplayValue("AAAAAAAAAAAA"); - autoComplete = AutoCompleteSupport.install(comboBox, items); - - for (int i = 0; i < comboBox.getComponentCount(); i++) { - java.awt.Component component = comboBox.getComponent(i); - component.addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - initOptions(); - - // update text representation based on entity properties - updateTextRepresentation(); - } - - @Override - public void focusLost(FocusEvent e) { - // Reset invalid value - checkSelectedValue(); - } - }); - } - // set value only on PopupMenu closing to avoid firing listeners on keyboard navigation - comboBox.addPopupMenuListener( - new PopupMenuListener() { - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - comboBox.updatePopupWidth(); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - if (!autoComplete.isEditableState()) { - // Only if really item changed - Object selectedItem = comboBox.getSelectedItem(); - if (selectedItem instanceof ValueWrapper) { - Object selectedValue = ((ValueWrapper) selectedItem).getValue(); - setValue(selectedValue); - } else if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { - restorePreviousItemText(); - newOptionHandler.addNewOption((String) selectedItem); - } else if ((selectedItem != null) && !newOptionAllowed) { - updateComponent(prevValue); - } - - updateMissingValueState(); - - fireUserSelectionListeners(); - } - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - } - } - ); - comboBox.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (settingValue || disableActionListener) - return; - Object selectedItem = comboBox.getSelectedItem(); - if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { - restorePreviousItemText(); - newOptionHandler.addNewOption((String) selectedItem); - } - - updateMissingValueState(); - } - } - ); - - setFilterMode(DEFAULT_FILTER_MODE); - - textField = new JTextField(); - textField.setEditable(false); - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - valueFormatter = new DefaultValueFormatter(sessionSource.getLocale()); - - composition.add(comboBox, BorderLayout.CENTER); - impl = comboBox; - - DesktopComponentsHelper.adjustSize(comboBox); - DesktopComponentsHelper.adjustSize(textField); - - textField.setMinimumSize(new Dimension(comboBox.getMinimumSize().width, textField.getPreferredSize().height)); - - initClearShortcut(); - } - - protected void fireUserSelectionListeners() { - if (userSelectionListeners != null) { - for (UserSelectionListener listener : userSelectionListeners) { - listener.userSelectionApplied(this); - } - } - } - - protected void initClearShortcut() { - JComponent editor = (JComponent) comboBox.getEditor().getEditorComponent(); - KeyStroke clearKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.SHIFT_DOWN_MASK, false); - editor.getInputMap(JComponent.WHEN_FOCUSED).put(clearKeyStroke, "clearShortcut"); - editor.getActionMap().put("clearShortcut", new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (!isRequired() && isEditable() && isEnabled()) { - setValue(null); - - fireUserSelectionListeners(); - } - } - }); - } - - protected void restorePreviousItemText() { - disableActionListener = true; - try { - Object value = null; - if (prevValue != null) { - for (Object item : items) { - ValueWrapper wrapper = (ValueWrapper) item; - if (wrapper.getValue() == prevValue) { - value = wrapper; - break; - } - } - } - - if (value == null && nullOption != null) - value = new NullOption(); - - comboBox.getEditor().setItem(value); - } finally { - disableActionListener = false; - } - } - - protected void updateTextRepresentation() { - disableActionListener = true; - try { - Object value = comboBox.getSelectedItem(); - comboBox.getEditor().setItem(value); - } finally { - disableActionListener = false; - } - } - - @SuppressWarnings("unchecked") - protected void updateOptionsDsItem() { - if (optionsDatasource != null) { - updatingInstance = true; - if (optionsDatasource.getState() == Datasource.State.VALID) { - if (!ObjectUtils.equals(getValue(), optionsDatasource.getItem())) - optionsDatasource.setItem((Entity) getValue()); - } - updatingInstance = false; - } - } - - protected void checkSelectedValue() { - if (!resetValueState) { - resetValueState = true; - Object selectedItem = comboBox.getSelectedItem(); - - if (!(selectedItem instanceof ValueWrapper)) { - if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { - updateComponent(prevValue); - } else if (selectedItem == null || !newOptionAllowed) { - if (isRequired()) { - updateComponent(prevValue); - } else { - updateComponent(nullOption); - } - } - } - - resetValueState = false; - } - } - - protected void flushSelectedValue() { - if (!resetValueState) { - resetValueState = true; - Object selectedItem = comboBox.getEditor().getItem(); - - if (!(selectedItem instanceof ValueWrapper)) { - if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { - restorePreviousItemText(); - newOptionHandler.addNewOption((String) selectedItem); - } else if (selectedItem == null || !newOptionAllowed) { - if (isRequired()) { - updateComponent(prevValue); - } else { - updateComponent(nullOption); - } - } - } - - resetValueState = false; - } - } - - protected void initOptions() { - if (optionsInitialized) - return; - - items.clear(); - - if (!isRequired() && nullOption == null && nullOptionVisible) { - items.add(new ObjectWrapper(null)); - } - - if (optionsDatasource != null) { - if (!(optionsDatasource.getState() == Datasource.State.VALID)) { - optionsDatasource.refresh(); - } - for (Object id : optionsDatasource.getItemIds()) { - items.add(new EntityWrapper(optionsDatasource.getItem(id))); - } - - collectionChangeListener = e -> { - items.clear(); - for (Entity item : optionsDatasource.getItems()) { - items.add(new EntityWrapper(item)); - } - }; - optionsDatasource.addCollectionChangeListener(new WeakCollectionChangeListener(optionsDatasource, collectionChangeListener)); - } else if (optionsMap != null) { - for (String key : optionsMap.keySet()) { - items.add(new MapKeyWrapper(key)); - } - } else if (optionsList != null) { - for (Object obj : optionsList) { - items.add(new ObjectWrapper(obj)); - } - } else if (optionsEnum != null) { - List options = Arrays.asList(optionsEnum.getEnumConstants()); - for (Object obj : options) { - items.add(new ObjectWrapper(obj)); - } - } else if (datasource != null && metaProperty != null && metaProperty.getRange().isEnum()) { - @SuppressWarnings("unchecked") - Enumeration enumeration = metaProperty.getRange().asEnumeration(); - for (Enum en : enumeration.getValues()) { - items.add(new ObjectWrapper(en)); - } - } - - optionsInitialized = true; - } - - @Override - public JComponent getComposition() { - return composition; - } - - @Override - public Object getNullOption() { - return nullOption; - } - - @Override - public void setNullOption(Object nullOption) { - this.nullOption = nullOption; - autoComplete.setFirstItem(new NullOption()); - if (getValue() == null) { - setValue(null); - } - optionsInitialized = false; - } - - @Override - public FilterMode getFilterMode() { - return autoComplete.getFilterMode() == TextMatcherEditor.CONTAINS - ? FilterMode.CONTAINS : FilterMode.STARTS_WITH; - } - - @Override - public void setFilterMode(FilterMode mode) { - autoComplete.setFilterMode(FilterMode.CONTAINS.equals(mode) - ? TextMatcherEditor.CONTAINS : TextMatcherEditor.STARTS_WITH); - } - - @Override - public boolean isNewOptionAllowed() { - return newOptionAllowed; - } - - @Override - public void setNewOptionAllowed(boolean newOptionAllowed) { - this.newOptionAllowed = newOptionAllowed; - } - - @Override - public boolean isTextInputAllowed() { - return textInputAllowed; - } - - @Override - public void setTextInputAllowed(boolean textInputAllowed) { - this.textInputAllowed = textInputAllowed; - } - - @Override - public NewOptionHandler getNewOptionHandler() { - return newOptionHandler; - } - - @Override - public void setNewOptionHandler(NewOptionHandler newOptionHandler) { - this.newOptionHandler = newOptionHandler; - } - - @Override - public int getPageLength() { - return 0; - } - - @Override - public void setPageLength(int pageLength) { - // do nothing - } - - @Override - public void setNullOptionVisible(boolean nullOptionVisible) { - this.nullOptionVisible = nullOptionVisible; - } - - @Override - public boolean isNullOptionVisible() { - return nullOptionVisible; - } - - public void setOptionIconProvider(OptionIconProvider optionIconProvider) { - this.optionIconProvider = optionIconProvider; - } - - @Override - public void setOptionIconProvider(Class optionClass, OptionIconProvider optionIconProvider) { - this.optionIconProvider = optionIconProvider; - } - - public OptionIconProvider getOptionIconProvider() { - return optionIconProvider; - } - - @Override - public String getInputPrompt() { - return inputPrompt; - } - - @Override - public void setInputPrompt(String inputPrompt) { - this.inputPrompt = inputPrompt; - } - - @Override - public boolean isMultiSelect() { - return false; - } - - @Override - public void setMultiSelect(boolean multiselect) { - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - requestContainerUpdate(); - } - - @Override - public void setOptionsList(List optionsList) { - super.setOptionsList(optionsList); - if (optionsInitialized) { - optionsInitialized = false; - - initOptions(); - } - } - - @Override - public void setOptionsMap(Map map) { - super.setOptionsMap(map); - if (optionsInitialized) { - optionsInitialized = false; - - initOptions(); - } - } - - @Override - public void setOptionsEnum(Class optionsEnum) { - super.setOptionsEnum(optionsEnum); - if (optionsInitialized) { - optionsInitialized = false; - - initOptions(); - } - } - - @Override - public String getDescription() { - return ((JComponent) comboBox.getEditor().getEditorComponent()).getToolTipText(); - } - - @Override - public void setDescription(String description) { - if (!ObjectUtils.equals(this.getDescription(), description)) { - JComponent editorComponent = (JComponent) comboBox.getEditor().getEditorComponent(); - - editorComponent.setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(editorComponent); - - requestContainerUpdate(); - } - } - - @Override - public void updateMissingValueState() { - Component editorComponent = comboBox.getEditor().getEditorComponent(); - boolean value = required && isEditableWithParent() && isEnabledWithParent() && editorComponent instanceof JTextComponent - && StringUtils.isEmpty(((JTextComponent) editorComponent).getText()); - decorateMissingValue(comboBox, value); - } - - @Override - protected void setEditableToComponent(boolean editable) { - if (!editable) { - composition.remove(comboBox); - composition.add(textField, BorderLayout.CENTER); - impl = textField; - - updateTextField(); - } else { - composition.remove(textField); - composition.add(comboBox, BorderLayout.CENTER); - - impl = comboBox; - } - - updateMissingValueState(); - requestContainerUpdate(); - - composition.revalidate(); - composition.repaint(); - } - - protected JComponent getInputComponent() { - if (impl == comboBox) { - return (JComponent) comboBox.getEditor().getEditorComponent(); - } else { - return impl; - } - } - - protected void updateTextField() { - if (metaProperty != null) { - Object value = getValue(); - if (value == null && nullOption != null) { - textField.setText(nullOption.toString()); - } else { - valueFormatter.setMetaProperty(metaProperty); - textField.setText(valueFormatter.formatValue(value)); - } - } else { - if (comboBox.getSelectedItem() != null) { - textField.setText(comboBox.getSelectedItem().toString()); - } else if (nullOption != null) { - textField.setText(nullOption.toString()); - } else { - textField.setText(""); - } - } - } - - @Override - protected Object getSelectedItem() { - return comboBox.getSelectedItem(); - } - - @Override - protected void setSelectedItem(Object item) { - comboBox.setSelectedItem(item); - if (!editable) { - updateTextField(); - } - updateMissingValueState(); - } - - protected Object getValueFromOptions(Object value) { - if (optionsDatasource != null && value instanceof Entity) { - if (Datasource.State.INVALID == optionsDatasource.getState()) { - optionsDatasource.refresh(); - } - Object itemId = ((Entity) value).getId(); - if (optionsDatasource.containsItem(itemId)) { - value = optionsDatasource.getItem(itemId); - } - } - - return value; - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - settingValue = true; - try { - if (value == nullOption) { - value = null; - } - - super.setValue(getValueFromOptions(value)); - } finally { - settingValue = false; - } - - comboBox.hidePopup(); - } - - @SuppressWarnings("unchecked") - @Override - public T getValue() { - final Object value = super.getValue(); - return (T) getValueFromOptions(value); - } - - @Override - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = newValue; - if (!ObjectUtils.equals(oldValue, newValue)) { - updateOptionsDsItem(); - fireValueChanged(oldValue, newValue); - } - } - - @Override - protected void updateComponent(Object value) { - if (value == null && nullOption != null) - value = new NullOption(); - super.updateComponent(value); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - - comboBox.setEnabled(resultEnabled); - textField.setEnabled(resultEnabled); - - comboBox.setFocusable(resultEnabled); - textField.setFocusable(resultEnabled); - - updateMissingValueState(); - } - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { - return getClass().getSimpleName() + "_" + datasource.getId() + "_" + metaPropertyPath.toString(); - } - if (optionsDatasource != null && StringUtils.isNotEmpty(optionsDatasource.getId())) { - return getClass().getSimpleName() + "_" + optionsDatasource.getId(); - } - - return getClass().getSimpleName(); - } - - @Override - public void setCaptionProperty(String captionProperty) { - this.captionProperty = captionProperty; - - if (captionProperty != null) { - setCaptionMode(CaptionMode.PROPERTY); - } else { - setCaptionMode(CaptionMode.ITEM); - } - } - - @Override - public void addUserSelectionListener(UserSelectionListener listener) { - Preconditions.checkNotNullArgument(listener); - - if (userSelectionListeners == null) { - userSelectionListeners = new LinkedList<>(); - } - if (!userSelectionListeners.contains(listener)) { - userSelectionListeners.add(listener); - } - } - - @Override - public void removeUserSelectionListener(UserSelectionListener listener) { - if (userSelectionListeners != null) { - userSelectionListeners.remove(listener); - } - } - - @Override - protected String getDisplayString(Entity entity) { - // This code was copied from superclass - if (entity == null) - return ""; - - String captionValue; - if (captionMode.equals(CaptionMode.PROPERTY) && !StringUtils.isBlank(captionProperty)) { - captionValue = entity.getValueEx(captionProperty); - } else { - captionValue = entity.getInstanceName(); - } - - if (captionValue == null) - captionValue = ""; - - return captionValue; - } - - @Override - public void setLookupSelectHandler(Runnable selectHandler) { - // do nothing - } - - @Override - public Collection getLookupSelectedItems() { - return Collections.singleton(getValue()); - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } - - protected class NullOption extends EntityWrapper { - public NullOption() { - //noinspection IncorrectCreateEntity - super(new BaseUuidEntity() { - @Override - public String getInstanceName() { - // NullOption class is used for any type of nullOption value - if (nullOption instanceof Instance) { - return InstanceUtils.getInstanceName((Instance) nullOption); - } else if (nullOption instanceof Enum) { - return messages.getMessage((Enum) nullOption); - } - - if (nullOption == null) { - return ""; - } else { - return nullOption.toString(); - } - } - - // Used for captionProperty of null entity - @SuppressWarnings("unchecked") - @Override - public T getValue(String s) { - return (T) getInstanceName(); - } - }); - } - - @Override - public Entity getValue() { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import ca.odell.glazedlists.BasicEventList; +import ca.odell.glazedlists.matchers.TextMatcherEditor; +import ca.odell.glazedlists.swing.AutoCompleteSupport; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.vcl.ExtendedComboBox; +import com.haulmont.cuba.desktop.sys.vcl.UserSelectionHandler; +import com.haulmont.cuba.gui.components.CaptionMode; +import com.haulmont.cuba.gui.components.LookupField; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +public class DesktopLookupField extends DesktopAbstractOptionsField implements LookupField, UserSelectionHandler { + + protected static final FilterMode DEFAULT_FILTER_MODE = FilterMode.CONTAINS; + + protected BasicEventList items = new BasicEventList<>(); + protected AutoCompleteSupport autoComplete; + protected String caption; + protected NewOptionHandler newOptionHandler; + + protected boolean optionsInitialized; + protected boolean resetValueState = false; + + protected boolean newOptionAllowed; + protected boolean settingValue; + + protected boolean disableActionListener = false; + + protected Object nullOption; + + protected ExtendedComboBox comboBox; + protected JTextField textField; + + protected JPanel composition; + + protected DefaultValueFormatter valueFormatter; + protected String inputPrompt; + protected boolean textInputAllowed = true; + + protected boolean nullOptionVisible = true; + + protected List userSelectionListeners = null; // lazy initialized list + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + // just stub + protected OptionIconProvider optionIconProvider; + + public DesktopLookupField() { + composition = new JPanel(); + composition.setLayout(new BorderLayout()); + composition.setFocusable(false); + + comboBox = new ExtendedComboBox() { + @Override + public void flushValue() { + super.flushValue(); + + flushSelectedValue(); + } + }; + comboBox.setEditable(true); + comboBox.setPrototypeDisplayValue("AAAAAAAAAAAA"); + autoComplete = AutoCompleteSupport.install(comboBox, items); + + for (int i = 0; i < comboBox.getComponentCount(); i++) { + java.awt.Component component = comboBox.getComponent(i); + component.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + initOptions(); + + // update text representation based on entity properties + updateTextRepresentation(); + } + + @Override + public void focusLost(FocusEvent e) { + // Reset invalid value + checkSelectedValue(); + } + }); + } + // set value only on PopupMenu closing to avoid firing listeners on keyboard navigation + comboBox.addPopupMenuListener( + new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + comboBox.updatePopupWidth(); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + if (!autoComplete.isEditableState()) { + // Only if really item changed + Object selectedItem = comboBox.getSelectedItem(); + if (selectedItem instanceof ValueWrapper) { + Object selectedValue = ((ValueWrapper) selectedItem).getValue(); + setValue(selectedValue); + } else if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { + restorePreviousItemText(); + newOptionHandler.addNewOption((String) selectedItem); + } else if ((selectedItem != null) && !newOptionAllowed) { + updateComponent(prevValue); + } + + updateMissingValueState(); + + fireUserSelectionListeners(); + } + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + } + ); + comboBox.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (settingValue || disableActionListener) + return; + Object selectedItem = comboBox.getSelectedItem(); + if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { + restorePreviousItemText(); + newOptionHandler.addNewOption((String) selectedItem); + } + + updateMissingValueState(); + } + } + ); + + setFilterMode(DEFAULT_FILTER_MODE); + + textField = new JTextField(); + textField.setEditable(false); + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + valueFormatter = new DefaultValueFormatter(sessionSource.getLocale()); + + composition.add(comboBox, BorderLayout.CENTER); + impl = comboBox; + + DesktopComponentsHelper.adjustSize(comboBox); + DesktopComponentsHelper.adjustSize(textField); + + textField.setMinimumSize(new Dimension(comboBox.getMinimumSize().width, textField.getPreferredSize().height)); + + initClearShortcut(); + } + + protected void fireUserSelectionListeners() { + if (userSelectionListeners != null) { + for (UserSelectionListener listener : userSelectionListeners) { + listener.userSelectionApplied(this); + } + } + } + + protected void initClearShortcut() { + JComponent editor = (JComponent) comboBox.getEditor().getEditorComponent(); + KeyStroke clearKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.SHIFT_DOWN_MASK, false); + editor.getInputMap(JComponent.WHEN_FOCUSED).put(clearKeyStroke, "clearShortcut"); + editor.getActionMap().put("clearShortcut", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (!isRequired() && isEditable() && isEnabled()) { + setValue(null); + + fireUserSelectionListeners(); + } + } + }); + } + + protected void restorePreviousItemText() { + disableActionListener = true; + try { + Object value = null; + if (prevValue != null) { + for (Object item : items) { + ValueWrapper wrapper = (ValueWrapper) item; + if (wrapper.getValue() == prevValue) { + value = wrapper; + break; + } + } + } + + if (value == null && nullOption != null) + value = new NullOption(); + + comboBox.getEditor().setItem(value); + } finally { + disableActionListener = false; + } + } + + protected void updateTextRepresentation() { + disableActionListener = true; + try { + Object value = comboBox.getSelectedItem(); + comboBox.getEditor().setItem(value); + } finally { + disableActionListener = false; + } + } + + @SuppressWarnings("unchecked") + protected void updateOptionsDsItem() { + if (optionsDatasource != null) { + updatingInstance = true; + if (optionsDatasource.getState() == Datasource.State.VALID) { + if (!ObjectUtils.equals(getValue(), optionsDatasource.getItem())) + optionsDatasource.setItem((Entity) getValue()); + } + updatingInstance = false; + } + } + + protected void checkSelectedValue() { + if (!resetValueState) { + resetValueState = true; + Object selectedItem = comboBox.getSelectedItem(); + + if (!(selectedItem instanceof ValueWrapper)) { + if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { + updateComponent(prevValue); + } else if (selectedItem == null || !newOptionAllowed) { + if (isRequired()) { + updateComponent(prevValue); + } else { + updateComponent(nullOption); + } + } + } + + resetValueState = false; + } + } + + protected void flushSelectedValue() { + if (!resetValueState) { + resetValueState = true; + Object selectedItem = comboBox.getEditor().getItem(); + + if (!(selectedItem instanceof ValueWrapper)) { + if (selectedItem instanceof String && newOptionAllowed && newOptionHandler != null) { + restorePreviousItemText(); + newOptionHandler.addNewOption((String) selectedItem); + } else if (selectedItem == null || !newOptionAllowed) { + if (isRequired()) { + updateComponent(prevValue); + } else { + updateComponent(nullOption); + } + } + } + + resetValueState = false; + } + } + + protected void initOptions() { + if (optionsInitialized) + return; + + items.clear(); + + if (!isRequired() && nullOption == null && nullOptionVisible) { + items.add(new ObjectWrapper(null)); + } + + if (optionsDatasource != null) { + if (!(optionsDatasource.getState() == Datasource.State.VALID)) { + optionsDatasource.refresh(); + } + for (Object id : optionsDatasource.getItemIds()) { + items.add(new EntityWrapper(optionsDatasource.getItem(id))); + } + + collectionChangeListener = e -> { + items.clear(); + for (Entity item : optionsDatasource.getItems()) { + items.add(new EntityWrapper(item)); + } + }; + optionsDatasource.addCollectionChangeListener(new WeakCollectionChangeListener(optionsDatasource, collectionChangeListener)); + } else if (optionsMap != null) { + for (String key : optionsMap.keySet()) { + items.add(new MapKeyWrapper(key)); + } + } else if (optionsList != null) { + for (Object obj : optionsList) { + items.add(new ObjectWrapper(obj)); + } + } else if (optionsEnum != null) { + List options = Arrays.asList(optionsEnum.getEnumConstants()); + for (Object obj : options) { + items.add(new ObjectWrapper(obj)); + } + } else if (datasource != null && metaProperty != null && metaProperty.getRange().isEnum()) { + @SuppressWarnings("unchecked") + Enumeration enumeration = metaProperty.getRange().asEnumeration(); + for (Enum en : enumeration.getValues()) { + items.add(new ObjectWrapper(en)); + } + } + + optionsInitialized = true; + } + + @Override + public JComponent getComposition() { + return composition; + } + + @Override + public Object getNullOption() { + return nullOption; + } + + @Override + public void setNullOption(Object nullOption) { + this.nullOption = nullOption; + autoComplete.setFirstItem(new NullOption()); + if (getValue() == null) { + setValue(null); + } + optionsInitialized = false; + } + + @Override + public FilterMode getFilterMode() { + return autoComplete.getFilterMode() == TextMatcherEditor.CONTAINS + ? FilterMode.CONTAINS : FilterMode.STARTS_WITH; + } + + @Override + public void setFilterMode(FilterMode mode) { + autoComplete.setFilterMode(FilterMode.CONTAINS.equals(mode) + ? TextMatcherEditor.CONTAINS : TextMatcherEditor.STARTS_WITH); + } + + @Override + public boolean isNewOptionAllowed() { + return newOptionAllowed; + } + + @Override + public void setNewOptionAllowed(boolean newOptionAllowed) { + this.newOptionAllowed = newOptionAllowed; + } + + @Override + public boolean isTextInputAllowed() { + return textInputAllowed; + } + + @Override + public void setTextInputAllowed(boolean textInputAllowed) { + this.textInputAllowed = textInputAllowed; + } + + @Override + public NewOptionHandler getNewOptionHandler() { + return newOptionHandler; + } + + @Override + public void setNewOptionHandler(NewOptionHandler newOptionHandler) { + this.newOptionHandler = newOptionHandler; + } + + @Override + public int getPageLength() { + return 0; + } + + @Override + public void setPageLength(int pageLength) { + // do nothing + } + + @Override + public void setNullOptionVisible(boolean nullOptionVisible) { + this.nullOptionVisible = nullOptionVisible; + } + + @Override + public boolean isNullOptionVisible() { + return nullOptionVisible; + } + + public void setOptionIconProvider(OptionIconProvider optionIconProvider) { + this.optionIconProvider = optionIconProvider; + } + + @Override + public void setOptionIconProvider(Class optionClass, OptionIconProvider optionIconProvider) { + this.optionIconProvider = optionIconProvider; + } + + public OptionIconProvider getOptionIconProvider() { + return optionIconProvider; + } + + @Override + public String getInputPrompt() { + return inputPrompt; + } + + @Override + public void setInputPrompt(String inputPrompt) { + this.inputPrompt = inputPrompt; + } + + @Override + public boolean isMultiSelect() { + return false; + } + + @Override + public void setMultiSelect(boolean multiselect) { + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + requestContainerUpdate(); + } + + @Override + public void setOptionsList(List optionsList) { + super.setOptionsList(optionsList); + if (optionsInitialized) { + optionsInitialized = false; + + initOptions(); + } + } + + @Override + public void setOptionsMap(Map map) { + super.setOptionsMap(map); + if (optionsInitialized) { + optionsInitialized = false; + + initOptions(); + } + } + + @Override + public void setOptionsEnum(Class optionsEnum) { + super.setOptionsEnum(optionsEnum); + if (optionsInitialized) { + optionsInitialized = false; + + initOptions(); + } + } + + @Override + public String getDescription() { + return ((JComponent) comboBox.getEditor().getEditorComponent()).getToolTipText(); + } + + @Override + public void setDescription(String description) { + if (!ObjectUtils.equals(this.getDescription(), description)) { + JComponent editorComponent = (JComponent) comboBox.getEditor().getEditorComponent(); + + editorComponent.setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(editorComponent); + + requestContainerUpdate(); + } + } + + @Override + public void updateMissingValueState() { + Component editorComponent = comboBox.getEditor().getEditorComponent(); + boolean value = required && isEditableWithParent() && isEnabledWithParent() && editorComponent instanceof JTextComponent + && StringUtils.isEmpty(((JTextComponent) editorComponent).getText()); + decorateMissingValue(comboBox, value); + } + + @Override + protected void setEditableToComponent(boolean editable) { + if (!editable) { + composition.remove(comboBox); + composition.add(textField, BorderLayout.CENTER); + impl = textField; + + updateTextField(); + } else { + composition.remove(textField); + composition.add(comboBox, BorderLayout.CENTER); + + impl = comboBox; + } + + updateMissingValueState(); + requestContainerUpdate(); + + composition.revalidate(); + composition.repaint(); + } + + protected JComponent getInputComponent() { + if (impl == comboBox) { + return (JComponent) comboBox.getEditor().getEditorComponent(); + } else { + return impl; + } + } + + protected void updateTextField() { + if (metaProperty != null) { + Object value = getValue(); + if (value == null && nullOption != null) { + textField.setText(nullOption.toString()); + } else { + valueFormatter.setMetaProperty(metaProperty); + textField.setText(valueFormatter.formatValue(value)); + } + } else { + if (comboBox.getSelectedItem() != null) { + textField.setText(comboBox.getSelectedItem().toString()); + } else if (nullOption != null) { + textField.setText(nullOption.toString()); + } else { + textField.setText(""); + } + } + } + + @Override + protected Object getSelectedItem() { + return comboBox.getSelectedItem(); + } + + @Override + protected void setSelectedItem(Object item) { + comboBox.setSelectedItem(item); + if (!editable) { + updateTextField(); + } + updateMissingValueState(); + } + + protected Object getValueFromOptions(Object value) { + if (optionsDatasource != null && value instanceof Entity) { + if (Datasource.State.INVALID == optionsDatasource.getState()) { + optionsDatasource.refresh(); + } + Object itemId = ((Entity) value).getId(); + if (optionsDatasource.containsItem(itemId)) { + value = optionsDatasource.getItem(itemId); + } + } + + return value; + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + settingValue = true; + try { + if (value == nullOption) { + value = null; + } + + super.setValue(getValueFromOptions(value)); + } finally { + settingValue = false; + } + + comboBox.hidePopup(); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() { + final Object value = super.getValue(); + return (T) getValueFromOptions(value); + } + + @Override + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = newValue; + if (!ObjectUtils.equals(oldValue, newValue)) { + updateOptionsDsItem(); + fireValueChanged(oldValue, newValue); + } + } + + @Override + protected void updateComponent(Object value) { + if (value == null && nullOption != null) + value = new NullOption(); + super.updateComponent(value); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + + comboBox.setEnabled(resultEnabled); + textField.setEnabled(resultEnabled); + + comboBox.setFocusable(resultEnabled); + textField.setFocusable(resultEnabled); + + updateMissingValueState(); + } + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { + return getClass().getSimpleName() + "_" + datasource.getId() + "_" + metaPropertyPath.toString(); + } + if (optionsDatasource != null && StringUtils.isNotEmpty(optionsDatasource.getId())) { + return getClass().getSimpleName() + "_" + optionsDatasource.getId(); + } + + return getClass().getSimpleName(); + } + + @Override + public void setCaptionProperty(String captionProperty) { + this.captionProperty = captionProperty; + + if (captionProperty != null) { + setCaptionMode(CaptionMode.PROPERTY); + } else { + setCaptionMode(CaptionMode.ITEM); + } + } + + @Override + public void addUserSelectionListener(UserSelectionListener listener) { + Preconditions.checkNotNullArgument(listener); + + if (userSelectionListeners == null) { + userSelectionListeners = new LinkedList<>(); + } + if (!userSelectionListeners.contains(listener)) { + userSelectionListeners.add(listener); + } + } + + @Override + public void removeUserSelectionListener(UserSelectionListener listener) { + if (userSelectionListeners != null) { + userSelectionListeners.remove(listener); + } + } + + @Override + protected String getDisplayString(Entity entity) { + // This code was copied from superclass + if (entity == null) + return ""; + + String captionValue; + if (captionMode.equals(CaptionMode.PROPERTY) && !StringUtils.isBlank(captionProperty)) { + captionValue = entity.getValueEx(captionProperty); + } else { + captionValue = entity.getInstanceName(); + } + + if (captionValue == null) + captionValue = ""; + + return captionValue; + } + + @Override + public void setLookupSelectHandler(Runnable selectHandler) { + // do nothing + } + + @Override + public Collection getLookupSelectedItems() { + return Collections.singleton(getValue()); + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } + + protected class NullOption extends EntityWrapper { + public NullOption() { + //noinspection IncorrectCreateEntity + super(new BaseUuidEntity() { + @Override + public String getInstanceName() { + // NullOption class is used for any type of nullOption value + if (nullOption instanceof Instance) { + return InstanceUtils.getInstanceName((Instance) nullOption); + } else if (nullOption instanceof Enum) { + return messages.getMessage((Enum) nullOption); + } + + if (nullOption == null) { + return ""; + } else { + return nullOption.toString(); + } + } + + // Used for captionProperty of null entity + @SuppressWarnings("unchecked") + @Override + public T getValue(String s) { + return (T) getInstanceName(); + } + }); + } + + @Override + public Entity getValue() { + return null; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupPickerField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupPickerField.java index fe574c842d..ff33a91514 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupPickerField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopLookupPickerField.java @@ -1,188 +1,188 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.LookupPickerField; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.util.Collection; - -public class DesktopLookupPickerField extends DesktopLookupField implements LookupPickerField { - - protected DesktopPickerField pickerField; - protected boolean isRefreshOptionsOnLookupClose = false; - - public DesktopLookupPickerField() { - pickerField = new DesktopPickerField(new Picker()); - } - - @Override - public JComponent getComposition() { - return pickerField.getComposition(); - } - - @Override - public MetaClass getMetaClass() { - return pickerField.getMetaClass(); - } - - @Override - public void setMetaClass(MetaClass metaClass) { - pickerField.setMetaClass(metaClass); - } - - @Override - public LookupAction addLookupAction() { - LookupAction action = LookupAction.create(this); - addAction(action); - return action; - } - - @Override - public ClearAction addClearAction() { - ClearAction action = ClearAction.create(this); - addAction(action); - return action; - } - - @Override - public OpenAction addOpenAction() { - OpenAction action = OpenAction.create(this); - addAction(action); - return action; - } - - @Override - public void addFieldListener(FieldListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setFieldEditable(boolean editable) { - throw new UnsupportedOperationException(); - } - - @Override - public void addAction(Action action) { - pickerField.addAction(action); - } - - @Override - public void addAction(Action action, int index) { - pickerField.addAction(action, index); - } - - @Override - public void removeAction(@Nullable Action action) { - pickerField.removeAction(action); - } - - @Override - public void removeAction(@Nullable String id) { - pickerField.removeAction(id); - } - - @Override - public void removeAllActions() { - pickerField.removeAllActions(); - } - - @Override - public Collection getActions() { - return pickerField.getActions(); - } - - @Override - @Nullable - public Action getAction(String id) { - return pickerField.getAction(id); - } - - @Override - public void setFrame(Frame frame) { - super.setFrame(frame); - pickerField.setFrame(frame); - } - - @Override - public void setDatasource(Datasource datasource, String property) { - pickerField.checkDatasourceProperty(datasource, property); - super.setDatasource(datasource, property); - pickerField.setDatasource(datasource, property); - } - - @Override - public void setOptionsDatasource(CollectionDatasource datasource) { - super.setOptionsDatasource(datasource); - if (pickerField.getMetaClass() == null && datasource != null) { - pickerField.setMetaClass(datasource.getMetaClass()); - } - } - - @Override - protected void setEditableToComponent(boolean editable) { - super.setEditableToComponent(editable); - - pickerField.setEditable(editable); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - pickerField.setParentEnabled(isEnabledWithParent()); - } - - @Override - public boolean isRefreshOptionsOnLookupClose() { - return isRefreshOptionsOnLookupClose; - } - - @Override - public void setRefreshOptionsOnLookupClose(boolean refresh) { - isRefreshOptionsOnLookupClose = refresh; - } - - private class Picker extends com.haulmont.cuba.desktop.sys.vcl.Picker { - @Override - protected void initEditor() { - // put LookupField into PickerField composition - editor = DesktopLookupPickerField.super.getComposition(); - } - - @Override - public JComponent getInputField() { - return getInputComponent(); - } - - @Override - public Object getValue() { - return null; - } - - @Override - public void setValue(Object value) { - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.LookupPickerField; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.util.Collection; + +public class DesktopLookupPickerField extends DesktopLookupField implements LookupPickerField { + + protected DesktopPickerField pickerField; + protected boolean isRefreshOptionsOnLookupClose = false; + + public DesktopLookupPickerField() { + pickerField = new DesktopPickerField(new Picker()); + } + + @Override + public JComponent getComposition() { + return pickerField.getComposition(); + } + + @Override + public MetaClass getMetaClass() { + return pickerField.getMetaClass(); + } + + @Override + public void setMetaClass(MetaClass metaClass) { + pickerField.setMetaClass(metaClass); + } + + @Override + public LookupAction addLookupAction() { + LookupAction action = LookupAction.create(this); + addAction(action); + return action; + } + + @Override + public ClearAction addClearAction() { + ClearAction action = ClearAction.create(this); + addAction(action); + return action; + } + + @Override + public OpenAction addOpenAction() { + OpenAction action = OpenAction.create(this); + addAction(action); + return action; + } + + @Override + public void addFieldListener(FieldListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void setFieldEditable(boolean editable) { + throw new UnsupportedOperationException(); + } + + @Override + public void addAction(Action action) { + pickerField.addAction(action); + } + + @Override + public void addAction(Action action, int index) { + pickerField.addAction(action, index); + } + + @Override + public void removeAction(@Nullable Action action) { + pickerField.removeAction(action); + } + + @Override + public void removeAction(@Nullable String id) { + pickerField.removeAction(id); + } + + @Override + public void removeAllActions() { + pickerField.removeAllActions(); + } + + @Override + public Collection getActions() { + return pickerField.getActions(); + } + + @Override + @Nullable + public Action getAction(String id) { + return pickerField.getAction(id); + } + + @Override + public void setFrame(Frame frame) { + super.setFrame(frame); + pickerField.setFrame(frame); + } + + @Override + public void setDatasource(Datasource datasource, String property) { + pickerField.checkDatasourceProperty(datasource, property); + super.setDatasource(datasource, property); + pickerField.setDatasource(datasource, property); + } + + @Override + public void setOptionsDatasource(CollectionDatasource datasource) { + super.setOptionsDatasource(datasource); + if (pickerField.getMetaClass() == null && datasource != null) { + pickerField.setMetaClass(datasource.getMetaClass()); + } + } + + @Override + protected void setEditableToComponent(boolean editable) { + super.setEditableToComponent(editable); + + pickerField.setEditable(editable); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + pickerField.setParentEnabled(isEnabledWithParent()); + } + + @Override + public boolean isRefreshOptionsOnLookupClose() { + return isRefreshOptionsOnLookupClose; + } + + @Override + public void setRefreshOptionsOnLookupClose(boolean refresh) { + isRefreshOptionsOnLookupClose = refresh; + } + + private class Picker extends com.haulmont.cuba.desktop.sys.vcl.Picker { + @Override + protected void initEditor() { + // put LookupField into PickerField composition + editor = DesktopLookupPickerField.super.getComposition(); + } + + @Override + public JComponent getInputField() { + return getInputComponent(); + } + + @Override + public Object getValue() { + return null; + } + + @Override + public void setValue(Object value) { + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopOptionsGroup.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopOptionsGroup.java index 8b4380acab..5f8fc71376 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopOptionsGroup.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopOptionsGroup.java @@ -1,408 +1,408 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.gui.components.CaptionMode; -import com.haulmont.cuba.gui.components.OptionsGroup; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.*; - -public class DesktopOptionsGroup extends DesktopAbstractOptionsField implements OptionsGroup { - - private boolean multiselect; - private boolean optionsInitialized; - private Map items = new LinkedHashMap<>(); - private ButtonGroup buttonGroup; - - private Orientation orientation = Orientation.VERTICAL; - private MigLayout layout; - - private boolean enabled = true; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - public DesktopOptionsGroup() { - layout = new MigLayout(); - impl = new JPanel(layout); - updateLayout(); - } - - private void updateLayout() { - layout.setLayoutConstraints(orientation == Orientation.VERTICAL ? "flowy" : "flowx"); - } - - @Override - public boolean isMultiSelect() { - return multiselect; - } - - @Override - public void setMultiSelect(boolean multiselect) { - if (this.multiselect != multiselect - && (optionsDatasource != null || optionsList != null || optionsMap != null)) - throw new IllegalStateException("Set multiselect before initializing options"); - - this.multiselect = multiselect; - } - - @Override - public void setOptionsDatasource(CollectionDatasource datasource) { - if (optionsInitialized) - return; - - super.setOptionsDatasource(datasource); - if (optionsDatasource != null) { - if (!optionsDatasource.getState().equals(Datasource.State.VALID)) { - optionsDatasource.refresh(); - } - for (Entity item : optionsDatasource.getItems()) { - addItem(new EntityWrapper(item)); - } - - collectionChangeListener = e -> { - Object value = getValue(); - - removeAllItems(); - for (Object id : e.getDs().getItemIds()) { - addItem(new EntityWrapper(e.getDs().getItem(id))); - } - - updateComponent(value); - fireChangeListeners(getValue()); - - impl.revalidate(); - impl.repaint(); - }; - optionsDatasource.addCollectionChangeListener(new WeakCollectionChangeListener(optionsDatasource, collectionChangeListener)); - - if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { - Entity newValue = datasource.getItem(); - updateComponent(newValue); - fireChangeListeners(newValue); - } - optionsInitialized = true; - } - - assignAutoDebugId(); - } - - @Override - public void setDatasource(Datasource datasource, String property) { - super.setDatasource(datasource, property); - - assignAutoDebugId(); - } - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { - return getClass().getSimpleName() + datasource.getId() + "_" + metaPropertyPath.toString(); - } - if (optionsDatasource != null && StringUtils.isNotEmpty(optionsDatasource.getId())) { - return getClass().getSimpleName() + optionsDatasource.getId(); - } - - return getClass().getSimpleName(); - } - - @Override - public void setOptionsList(List optionsList) { - if (optionsInitialized) - return; - - super.setOptionsList(optionsList); - if (optionsList != null) { - for (Object obj : optionsList) { - addItem(new ObjectWrapper(obj)); - } - - if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { - Entity newValue = datasource.getItem(); - updateComponent(newValue); - fireChangeListeners(newValue); - } - optionsInitialized = true; - } - } - - @Override - public void setOptionsMap(Map map) { - if (optionsInitialized) - return; - - super.setOptionsMap(map); - if (optionsMap != null) { - for (String key : optionsMap.keySet()) { - addItem(new MapKeyWrapper(key)); - } - - if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { - Entity newValue = datasource.getItem(); - updateComponent(newValue); - fireChangeListeners(newValue); - } - optionsInitialized = true; - } - } - - @Override - public void setOptionsEnum(Class optionsEnum) { - if (optionsInitialized) - return; - - super.setOptionsEnum(optionsEnum); - if (optionsEnum != null) { - List options = Arrays.asList(optionsEnum.getEnumConstants()); - for (Object obj : options) { - addItem(new ObjectWrapper(obj)); - } - - if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { - Entity newValue = datasource.getItem(); - updateComponent(newValue); - fireChangeListeners(newValue); - } - optionsInitialized = true; - } - } - - private void addItem(final ValueWrapper item) { - JToggleButton button; - if (multiselect) { - button = new JCheckBox(item.toString()); - } else { - if (buttonGroup == null) - buttonGroup = new ButtonGroup(); - button = new JRadioButton(item.toString()); - buttonGroup.add(button); - } - button.setEnabled(enabled && editable); - button.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (!multiselect) { - Object newValue = item.getValue(); - if (!ObjectUtils.equals(newValue, prevValue)) { - updateInstance(newValue); - fireChangeListeners(newValue); - } - updateMissingValueState(); - } else { - Set newValue = new LinkedHashSet<>(); - for (Map.Entry item : items.entrySet()) { - if (item.getValue().isSelected()) { - newValue.add(item.getKey().getValue()); - } - } - if ((prevValue != null - && !CollectionUtils.isEqualCollection(newValue, (Collection) prevValue)) - || (prevValue == null)) { - updateInstance(newValue); - fireChangeListeners(newValue); - } - updateMissingValueState(); - } - } - } - ); - - impl.add(button); - items.put(item, button); - } - - @Override - protected void updateInstance(Object newValue) { - if (newValue instanceof Collection && multiselect && metaPropertyPath != null) { - Class propertyType = metaPropertyPath.getMetaProperty().getJavaType(); - if (Set.class.isAssignableFrom(propertyType)) { - newValue = new LinkedHashSet<>((Collection) newValue); - } else if (List.class.isAssignableFrom(propertyType)) { - newValue = new ArrayList<>((Collection) newValue); - } - } - - super.updateInstance(newValue); - } - - @Override - public void updateMissingValueState() { - boolean state = required && getSelectedItem() == null; - decorateMissingValue(impl, state); - } - - private void refreshCaptions() { - for (Map.Entry entry : items.entrySet()) { - entry.getValue().setText(entry.getKey().toString()); - } - } - - @Override - public void setCaptionMode(CaptionMode captionMode) { - super.setCaptionMode(captionMode); - - refreshCaptions(); - } - - @Override - public void setCaptionProperty(String captionProperty) { - super.setCaptionProperty(captionProperty); - - refreshCaptions(); - } - - private void removeAllItems() { - impl.removeAll(); - items.clear(); - buttonGroup = null; - } - - @Override - protected void updateComponent(Object value) { - if (multiselect && value instanceof Collection) { - for (Object v : ((Collection) value)) { - for (Map.Entry entry : items.entrySet()) { - if (ObjectUtils.equals(entry.getKey().getValue(), v)) - entry.getValue().setSelected(true); - else - entry.getValue().setSelected(false); - } - } - updateMissingValueState(); - } else { - super.updateComponent(value); - } - } - - @SuppressWarnings("unchecked") - @Override - public T getValue() { - if (multiselect) { - Set set = new LinkedHashSet<>(); - for (Map.Entry entry : items.entrySet()) { - if (entry.getValue().isSelected()) { - set.add(entry.getKey().getValue()); - } - } - return (T) set; - } else { - return (T) wrapAsCollection(super.getValue()); - } - } - - @SuppressWarnings("unchecked") - protected T wrapAsCollection(Object o) { - if (isMultiSelect()) { - if (o != null) { - return (T) Collections.singleton(o); - } else { - return (T) Collections.emptySet(); - } - } else { - return (T) o; - } - } - - @Override - public String getDescription() { - return null; - } - - @Override - public void setDescription(String description) { - } - - @Override - protected Object getSelectedItem() { - for (Map.Entry entry : items.entrySet()) { - if (entry.getValue().isSelected()) - return entry.getKey(); - } - return null; - } - - @Override - protected void setSelectedItem(Object item) { - for (Map.Entry entry : items.entrySet()) { - Object wrapperValue = entry.getKey().getValue(); - if (item != null && wrapperValue.equals(((ValueWrapper) item).getValue())) - entry.getValue().setSelected(true); - else - entry.getValue().setSelected(false); - } - updateMissingValueState(); - } - - @Override - protected void setEditableToComponent(boolean editable) { - for (JToggleButton button : items.values()) { - button.setEnabled(enabled && editable); - } - } - - @Override - public Orientation getOrientation() { - return orientation; - } - - @Override - public void setOrientation(Orientation orientation) { - if (orientation == null) { - throw new IllegalArgumentException("Orientation must not be null"); - } - this.orientation = orientation; - updateLayout(); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - for (JToggleButton button : items.values()) { - button.setEnabled(enabled && editable && parentEnabled); - } - } - - @Override - public void setLookupSelectHandler(Runnable selectHandler) { - // do nothing - } - - @Override - public Collection getLookupSelectedItems() { - Object value = getValue(); - return (value instanceof Collection) - ? (Collection) value - : Collections.singleton(value); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.gui.components.CaptionMode; +import com.haulmont.cuba.gui.components.OptionsGroup; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.*; + +public class DesktopOptionsGroup extends DesktopAbstractOptionsField implements OptionsGroup { + + private boolean multiselect; + private boolean optionsInitialized; + private Map items = new LinkedHashMap<>(); + private ButtonGroup buttonGroup; + + private Orientation orientation = Orientation.VERTICAL; + private MigLayout layout; + + private boolean enabled = true; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + public DesktopOptionsGroup() { + layout = new MigLayout(); + impl = new JPanel(layout); + updateLayout(); + } + + private void updateLayout() { + layout.setLayoutConstraints(orientation == Orientation.VERTICAL ? "flowy" : "flowx"); + } + + @Override + public boolean isMultiSelect() { + return multiselect; + } + + @Override + public void setMultiSelect(boolean multiselect) { + if (this.multiselect != multiselect + && (optionsDatasource != null || optionsList != null || optionsMap != null)) + throw new IllegalStateException("Set multiselect before initializing options"); + + this.multiselect = multiselect; + } + + @Override + public void setOptionsDatasource(CollectionDatasource datasource) { + if (optionsInitialized) + return; + + super.setOptionsDatasource(datasource); + if (optionsDatasource != null) { + if (!optionsDatasource.getState().equals(Datasource.State.VALID)) { + optionsDatasource.refresh(); + } + for (Entity item : optionsDatasource.getItems()) { + addItem(new EntityWrapper(item)); + } + + collectionChangeListener = e -> { + Object value = getValue(); + + removeAllItems(); + for (Object id : e.getDs().getItemIds()) { + addItem(new EntityWrapper(e.getDs().getItem(id))); + } + + updateComponent(value); + fireChangeListeners(getValue()); + + impl.revalidate(); + impl.repaint(); + }; + optionsDatasource.addCollectionChangeListener(new WeakCollectionChangeListener(optionsDatasource, collectionChangeListener)); + + if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { + Entity newValue = datasource.getItem(); + updateComponent(newValue); + fireChangeListeners(newValue); + } + optionsInitialized = true; + } + + assignAutoDebugId(); + } + + @Override + public void setDatasource(Datasource datasource, String property) { + super.setDatasource(datasource, property); + + assignAutoDebugId(); + } + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + if (datasource != null && StringUtils.isNotEmpty(datasource.getId()) && metaPropertyPath != null) { + return getClass().getSimpleName() + datasource.getId() + "_" + metaPropertyPath.toString(); + } + if (optionsDatasource != null && StringUtils.isNotEmpty(optionsDatasource.getId())) { + return getClass().getSimpleName() + optionsDatasource.getId(); + } + + return getClass().getSimpleName(); + } + + @Override + public void setOptionsList(List optionsList) { + if (optionsInitialized) + return; + + super.setOptionsList(optionsList); + if (optionsList != null) { + for (Object obj : optionsList) { + addItem(new ObjectWrapper(obj)); + } + + if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { + Entity newValue = datasource.getItem(); + updateComponent(newValue); + fireChangeListeners(newValue); + } + optionsInitialized = true; + } + } + + @Override + public void setOptionsMap(Map map) { + if (optionsInitialized) + return; + + super.setOptionsMap(map); + if (optionsMap != null) { + for (String key : optionsMap.keySet()) { + addItem(new MapKeyWrapper(key)); + } + + if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { + Entity newValue = datasource.getItem(); + updateComponent(newValue); + fireChangeListeners(newValue); + } + optionsInitialized = true; + } + } + + @Override + public void setOptionsEnum(Class optionsEnum) { + if (optionsInitialized) + return; + + super.setOptionsEnum(optionsEnum); + if (optionsEnum != null) { + List options = Arrays.asList(optionsEnum.getEnumConstants()); + for (Object obj : options) { + addItem(new ObjectWrapper(obj)); + } + + if ((datasource!= null) && (datasource.getState() == Datasource.State.VALID)) { + Entity newValue = datasource.getItem(); + updateComponent(newValue); + fireChangeListeners(newValue); + } + optionsInitialized = true; + } + } + + private void addItem(final ValueWrapper item) { + JToggleButton button; + if (multiselect) { + button = new JCheckBox(item.toString()); + } else { + if (buttonGroup == null) + buttonGroup = new ButtonGroup(); + button = new JRadioButton(item.toString()); + buttonGroup.add(button); + } + button.setEnabled(enabled && editable); + button.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!multiselect) { + Object newValue = item.getValue(); + if (!ObjectUtils.equals(newValue, prevValue)) { + updateInstance(newValue); + fireChangeListeners(newValue); + } + updateMissingValueState(); + } else { + Set newValue = new LinkedHashSet<>(); + for (Map.Entry item : items.entrySet()) { + if (item.getValue().isSelected()) { + newValue.add(item.getKey().getValue()); + } + } + if ((prevValue != null + && !CollectionUtils.isEqualCollection(newValue, (Collection) prevValue)) + || (prevValue == null)) { + updateInstance(newValue); + fireChangeListeners(newValue); + } + updateMissingValueState(); + } + } + } + ); + + impl.add(button); + items.put(item, button); + } + + @Override + protected void updateInstance(Object newValue) { + if (newValue instanceof Collection && multiselect && metaPropertyPath != null) { + Class propertyType = metaPropertyPath.getMetaProperty().getJavaType(); + if (Set.class.isAssignableFrom(propertyType)) { + newValue = new LinkedHashSet<>((Collection) newValue); + } else if (List.class.isAssignableFrom(propertyType)) { + newValue = new ArrayList<>((Collection) newValue); + } + } + + super.updateInstance(newValue); + } + + @Override + public void updateMissingValueState() { + boolean state = required && getSelectedItem() == null; + decorateMissingValue(impl, state); + } + + private void refreshCaptions() { + for (Map.Entry entry : items.entrySet()) { + entry.getValue().setText(entry.getKey().toString()); + } + } + + @Override + public void setCaptionMode(CaptionMode captionMode) { + super.setCaptionMode(captionMode); + + refreshCaptions(); + } + + @Override + public void setCaptionProperty(String captionProperty) { + super.setCaptionProperty(captionProperty); + + refreshCaptions(); + } + + private void removeAllItems() { + impl.removeAll(); + items.clear(); + buttonGroup = null; + } + + @Override + protected void updateComponent(Object value) { + if (multiselect && value instanceof Collection) { + for (Object v : ((Collection) value)) { + for (Map.Entry entry : items.entrySet()) { + if (ObjectUtils.equals(entry.getKey().getValue(), v)) + entry.getValue().setSelected(true); + else + entry.getValue().setSelected(false); + } + } + updateMissingValueState(); + } else { + super.updateComponent(value); + } + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() { + if (multiselect) { + Set set = new LinkedHashSet<>(); + for (Map.Entry entry : items.entrySet()) { + if (entry.getValue().isSelected()) { + set.add(entry.getKey().getValue()); + } + } + return (T) set; + } else { + return (T) wrapAsCollection(super.getValue()); + } + } + + @SuppressWarnings("unchecked") + protected T wrapAsCollection(Object o) { + if (isMultiSelect()) { + if (o != null) { + return (T) Collections.singleton(o); + } else { + return (T) Collections.emptySet(); + } + } else { + return (T) o; + } + } + + @Override + public String getDescription() { + return null; + } + + @Override + public void setDescription(String description) { + } + + @Override + protected Object getSelectedItem() { + for (Map.Entry entry : items.entrySet()) { + if (entry.getValue().isSelected()) + return entry.getKey(); + } + return null; + } + + @Override + protected void setSelectedItem(Object item) { + for (Map.Entry entry : items.entrySet()) { + Object wrapperValue = entry.getKey().getValue(); + if (item != null && wrapperValue.equals(((ValueWrapper) item).getValue())) + entry.getValue().setSelected(true); + else + entry.getValue().setSelected(false); + } + updateMissingValueState(); + } + + @Override + protected void setEditableToComponent(boolean editable) { + for (JToggleButton button : items.values()) { + button.setEnabled(enabled && editable); + } + } + + @Override + public Orientation getOrientation() { + return orientation; + } + + @Override + public void setOrientation(Orientation orientation) { + if (orientation == null) { + throw new IllegalArgumentException("Orientation must not be null"); + } + this.orientation = orientation; + updateLayout(); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + for (JToggleButton button : items.values()) { + button.setEnabled(enabled && editable && parentEnabled); + } + } + + @Override + public void setLookupSelectHandler(Runnable selectHandler) { + // do nothing + } + + @Override + public Collection getLookupSelectedItems() { + Object value = getValue(); + return (value instanceof Collection) + ? (Collection) value + : Collections.singleton(value); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPickerField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPickerField.java index 5786239392..1e9c0be665 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPickerField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPickerField.java @@ -1,611 +1,611 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.vcl.Picker; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.swing.AbstractAction; -import javax.swing.*; -import javax.swing.text.JTextComponent; -import java.awt.event.*; -import java.util.*; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; -import static com.haulmont.cuba.gui.ComponentsHelper.findActionById; -import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; - -public class DesktopPickerField extends DesktopAbstractField - implements PickerField, Component.SecuredActionsHolder { - - protected CaptionMode captionMode = CaptionMode.ITEM; - protected String captionProperty; - - protected Datasource datasource; - protected MetaClass metaClass; - - protected Object prevValue; - protected String prevTextValue; - - protected java.util.List actionsOrder = new LinkedList<>(); - protected java.util.Set buttons = new HashSet<>(); - - protected int modifiersMask; - protected Map> keyStrokesMap = new HashMap<>(); - - protected boolean updatingInstance; - - protected Metadata metadata = AppBeans.get(Metadata.NAME); - - protected MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - - protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); - - protected Datasource.ItemChangeListener itemChangeListener; - protected Datasource.ItemChangeListener securityItemChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - public DesktopPickerField() { - impl = new Picker(); - initModifiersMask(); - } - - public DesktopPickerField(Picker picker) { - impl = picker; - initModifiersMask(); - } - - @Override - public CaptionMode getCaptionMode() { - return captionMode; - } - - @Override - public void setCaptionMode(CaptionMode captionMode) { - this.captionMode = captionMode; - } - - @Override - public String getCaptionProperty() { - return captionProperty; - } - - @Override - public void setCaptionProperty(String captionProperty) { - this.captionProperty = captionProperty; - } - - @Override - public MetaClass getMetaClass() { - Datasource ds = getDatasource(); - if (ds != null) { - return metaProperty.getRange().asClass(); - } else { - return metaClass; - } - } - - @Override - public void setMetaClass(MetaClass metaClass) { - Datasource ds = getDatasource(); - if (ds != null) - throw new IllegalStateException("Datasource is not null"); - this.metaClass = metaClass; - } - - @Override - public LookupAction addLookupAction() { - LookupAction action = LookupAction.create(this); - addAction(action); - return action; - } - - @Override - public ClearAction addClearAction() { - ClearAction action = ClearAction.create(this); - addAction(action); - return action; - } - - @Override - public OpenAction addOpenAction() { - OpenAction action = OpenAction.create(this); - addAction(action); - return action; - } - - @Override - public void addFieldListener(final FieldListener listener) { - final JTextField field = (JTextField) impl.getEditor(); - field.addFocusListener(new FocusAdapter() { - - @Override - public void focusLost(FocusEvent e) { - fireFieldListener(listener, field.getText()); - } - }); - - field.addKeyListener(new KeyAdapter() { - protected static final int ENTER_CODE = 10; - - @Override - public void keyPressed(KeyEvent e) { - if (ENTER_CODE == e.getKeyCode()) { - fireFieldListener(listener, field.getText()); - } - } - }); - } - - protected void fireFieldListener(FieldListener listener, String fieldText) { - if (!(ObjectUtils.equals(prevTextValue, fieldText))) { - prevTextValue = fieldText; - listener.actionPerformed(fieldText, getValue()); - } - } - - protected void initModifiersMask() { - Configuration configuration = AppBeans.get(Configuration.NAME); - ClientConfig config = configuration.getConfig(ClientConfig.class); - String[] strModifiers = StringUtils.split(config.getPickerShortcutModifiers().toUpperCase(), "-"); - - for (String strModifier : strModifiers) { - KeyCombination.Modifier modifier = KeyCombination.Modifier.valueOf(strModifier); - modifiersMask = modifiersMask | DesktopComponentsHelper.convertModifier(modifier); - } - } - - @Override - public void setFieldEditable(boolean editable) { - if (isEditable()) - ((JTextField) impl.getEditor()).setEditable(editable); - } - - @Override - public T getValue() { - if ((datasource != null) && (metaPropertyPath != null) - && (datasource.getState() == Datasource.State.VALID) - && (datasource.getItem() != null)) { - return datasource.getItem().getValueEx(metaPropertyPath.toString()); - } else { - //noinspection unchecked - return (T) prevValue; - } - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (datasource == null && metaClass == null) { - throw new IllegalStateException("Datasource or metaclass must be set for field"); - } - - if (value != null) { - Class fieldClass = getMetaClass().getJavaClass(); - Class valueClass = value.getClass(); - //noinspection unchecked - if (!fieldClass.isAssignableFrom(valueClass)) { - throw new IllegalArgumentException( - String.format("Could not set value with class %s to field with class %s", - fieldClass.getCanonicalName(), - valueClass.getCanonicalName()) - ); - } - } - - if (!InstanceUtils.propertyValueEquals(prevValue, value)) { - updateInstance(value); - updateComponent(value); - fireChangeListeners(value); - } else { - updateComponent(prevValue); - } - } - - private void updateInstance(Object value) { - if (updatingInstance) - return; - - if (InstanceUtils.propertyValueEquals(prevValue, value)) - return; - - updatingInstance = true; - try { - if (datasource != null && metaProperty != null && datasource.getState() == Datasource.State.VALID && - datasource.getItem() != null) - InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); - } finally { - updatingInstance = false; - } - } - - @Override - public Datasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return metaProperty; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return metaPropertyPath; - } - - public void checkDatasourceProperty(Datasource datasource, String property){ - checkNotNullArgument(datasource); - checkNotNullArgument(property); - - MetaPropertyPath metaPropertyPath = getResolvedMetaPropertyPath(datasource.getMetaClass(), property); - if (!metaPropertyPath.getRange().isClass()) { - throw new DevelopmentException(String.format("property '%s.%s' should have Entity type", datasource.getMetaClass().getName(), property)); - } - } - - @Override - public void setDatasource(Datasource datasource, String property) { - checkDatasourceProperty(datasource, property); - this.datasource = datasource; - - // null datasource is not supported for this class - /*if (datasource == null) { - setValue(null); - return; - }*/ - - resolveMetaPropertyPath(datasource.getMetaClass(), property); - - itemChangeListener = e -> { - if (updatingInstance) { - return; - } - - Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); - updateComponent(value); - fireChangeListeners(value); - }; - //noinspection unchecked - datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); - - itemPropertyChangeListener = e -> { - if (updatingInstance) { - return; - } - - if (e.getProperty().equals(metaProperty.getName())) { - updateComponent(e.getValue()); - fireChangeListeners(e.getValue()); - } - }; - //noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { - Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); - updateComponent(newValue); - fireChangeListeners(newValue); - } - - initRequired(metaPropertyPath); - - if (metaProperty.isReadOnly()) { - setEditable(false); - } - - handleFilteredAttributes(this, this.datasource, metaPropertyPath); - securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); - // noinspection unchecked - this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); - - initBeanValidator(); - } - - protected void fireChangeListeners(Object newValue) { - if (!InstanceUtils.propertyValueEquals(prevValue, newValue)) { - Object oldValue = prevValue; - - prevValue = newValue; - - fireValueChanged(oldValue, newValue); - } - } - - protected void updateComponent(Object value) { - String text; - - if (value == null) { - text = ""; - } else { - if (value instanceof Instance) { - if (captionMode.equals(CaptionMode.ITEM)) { - text = ((Instance) value).getInstanceName(); - } else { - Object propertyValue = ((Instance)value).getValue(captionProperty); - MetaClass valueClass = metadata.getClassNN(value.getClass()); - MetaProperty property = valueClass.getProperty(captionProperty); - - text = metadataTools.format(propertyValue, property); - } - } else { - text = value.toString(); - } - } - - impl.setValue(text); - prevTextValue = text; - updateMissingValueState(); - } - - @Override - protected void setCaptionToComponent(String caption) { - super.setCaptionToComponent(caption); - - requestContainerUpdate(); - } - - @Override - public String getDescription() { - return impl.getEditor().getToolTipText(); - } - - @Override - public void setDescription(String description) { - if (!ObjectUtils.equals(this.getDescription(), description)) { - impl.getEditor().setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl.getEditor()); - - requestContainerUpdate(); - } - } - - @Override - protected void setEditableToComponent(boolean editable) { - for (Action action : actionsOrder) { - if (action instanceof StandardAction) { - ((StandardAction) action).setEditable(isEditable()); - } - } - if (!editable && impl.getEditor() instanceof JTextComponent) { - JTextComponent editor = (JTextComponent) impl.getEditor(); - editor.setEditable(false); - } - updateMissingValueState(); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - for (DesktopButton button : buttons) { - button.setParentEnabled(resultEnabled); - } - - if (impl.getEditor() instanceof JTextComponent) { - JTextComponent editor = (JTextComponent) impl.getEditor(); - editor.setFocusable(resultEnabled); - } - } - - @Override - public void addAction(Action action) { - int index = findActionById(actionsOrder, action.getId()); - if (index < 0) { - index = actionsOrder.size(); - } - - addAction(action, index); - } - - @Override - public void addAction(Action action, int index) { - checkNotNullArgument(action, "action must be non null"); - - int oldIndex = findActionById(actionsOrder, action.getId()); - if (oldIndex >= 0) { - removeAction(actionsOrder.get(oldIndex)); - if (index > oldIndex) { - index--; - } - } - - actionsOrder.add(index, action); - - DesktopButton dButton = new DesktopButton(); - dButton.setParentEnabled(isEnabledWithParent()); - dButton.setShouldBeFocused(false); - dButton.setAction(action); - dButton.getImpl().setFocusable(false); - dButton.getImpl().setText(""); - - impl.addButton(dButton.getImpl(), index); - buttons.add(dButton); - - // apply Editable after action owner is set - if (action instanceof StandardAction) { - ((StandardAction) action).setEditable(isEditable()); - } - - updateOrderedShortcuts(); - - ActionMap actionMap = getImpl().getInputField().getActionMap(); - actionMap.put(action.getId(), new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - action.actionPerform(dButton); - } - }); - - if (action.getShortcutCombination() != null) { - InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); - - KeyStroke shortcutKeyStroke = DesktopComponentsHelper.convertKeyCombination(action.getShortcutCombination()); - inputMap.put(shortcutKeyStroke, action.getId()); - } - - actionsPermissions.apply(action); - } - - @Override - public void removeAction(@Nullable Action action) { - if (action != null) { - if (actionsOrder.remove(action)) { - if (action.getOwner() != null && action.getOwner() instanceof DesktopButton) { - JButton button = ((DesktopButton) action.getOwner()).getImpl(); - impl.removeButton(button); - } - - InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); - ActionMap actionMap = getImpl().getInputField().getActionMap(); - List keyStrokes = keyStrokesMap.get(action); - if (keyStrokes != null) { - for (KeyStroke keyStroke : keyStrokes) { - inputMap.remove(keyStroke); - } - actionMap.remove(action.getId()); - } - - updateOrderedShortcuts(); - } - } - } - - protected void updateOrderedShortcuts() { - InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); - for (int i = 0; i < 9; i++) { - KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_1 + i, modifiersMask, false); - inputMap.remove(keyStroke); - } - - int index = 0; - for (Action action : actionsOrder) { - KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_1 + index, modifiersMask, false); - List keyStrokes = new LinkedList<>(); - keyStrokes.add(keyStroke); - keyStrokesMap.put(action, keyStrokes); - - inputMap.put(keyStroke, action.getId()); - - index++; - } - } - - @Override - public void removeAction(@Nullable String id) { - Action action = getAction(id); - if (action != null) { - removeAction(action); - } - } - - @Override - public void removeAllActions() { - for (Action action : new ArrayList<>(actionsOrder)) { - removeAction(action); - } - } - - @Override - public Collection getActions() { - return Collections.unmodifiableCollection(actionsOrder); - } - - @Override - @Nullable - public Action getAction(String id) { - for (Action action : getActions()) { - if (ObjectUtils.equals(action.getId(), id)) { - return action; - } - } - return null; - } - - @Override - public void updateMissingValueState() { - if (!(impl.getEditor() instanceof JTextComponent)) { - return; - } - JTextComponent editor = (JTextComponent) impl.getEditor(); - boolean value = required && isEditableWithParent() && StringUtils.isBlank(editor.getText()); - - decorateMissingValue(impl.getEditor(), value); - } - - @Override - public ActionsPermissions getActionsPermissions() { - return actionsPermissions; - } - - @Override - public void setLookupSelectHandler(Runnable selectHandler) { - // do nothing - } - - @Override - public Collection getLookupSelectedItems() { - return Collections.singleton(getValue()); - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.vcl.Picker; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.swing.AbstractAction; +import javax.swing.*; +import javax.swing.text.JTextComponent; +import java.awt.event.*; +import java.util.*; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; +import static com.haulmont.cuba.gui.ComponentsHelper.findActionById; +import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes; + +public class DesktopPickerField extends DesktopAbstractField + implements PickerField, Component.SecuredActionsHolder { + + protected CaptionMode captionMode = CaptionMode.ITEM; + protected String captionProperty; + + protected Datasource datasource; + protected MetaClass metaClass; + + protected Object prevValue; + protected String prevTextValue; + + protected java.util.List actionsOrder = new LinkedList<>(); + protected java.util.Set buttons = new HashSet<>(); + + protected int modifiersMask; + protected Map> keyStrokesMap = new HashMap<>(); + + protected boolean updatingInstance; + + protected Metadata metadata = AppBeans.get(Metadata.NAME); + + protected MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + + protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); + + protected Datasource.ItemChangeListener itemChangeListener; + protected Datasource.ItemChangeListener securityItemChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + public DesktopPickerField() { + impl = new Picker(); + initModifiersMask(); + } + + public DesktopPickerField(Picker picker) { + impl = picker; + initModifiersMask(); + } + + @Override + public CaptionMode getCaptionMode() { + return captionMode; + } + + @Override + public void setCaptionMode(CaptionMode captionMode) { + this.captionMode = captionMode; + } + + @Override + public String getCaptionProperty() { + return captionProperty; + } + + @Override + public void setCaptionProperty(String captionProperty) { + this.captionProperty = captionProperty; + } + + @Override + public MetaClass getMetaClass() { + Datasource ds = getDatasource(); + if (ds != null) { + return metaProperty.getRange().asClass(); + } else { + return metaClass; + } + } + + @Override + public void setMetaClass(MetaClass metaClass) { + Datasource ds = getDatasource(); + if (ds != null) + throw new IllegalStateException("Datasource is not null"); + this.metaClass = metaClass; + } + + @Override + public LookupAction addLookupAction() { + LookupAction action = LookupAction.create(this); + addAction(action); + return action; + } + + @Override + public ClearAction addClearAction() { + ClearAction action = ClearAction.create(this); + addAction(action); + return action; + } + + @Override + public OpenAction addOpenAction() { + OpenAction action = OpenAction.create(this); + addAction(action); + return action; + } + + @Override + public void addFieldListener(final FieldListener listener) { + final JTextField field = (JTextField) impl.getEditor(); + field.addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + fireFieldListener(listener, field.getText()); + } + }); + + field.addKeyListener(new KeyAdapter() { + protected static final int ENTER_CODE = 10; + + @Override + public void keyPressed(KeyEvent e) { + if (ENTER_CODE == e.getKeyCode()) { + fireFieldListener(listener, field.getText()); + } + } + }); + } + + protected void fireFieldListener(FieldListener listener, String fieldText) { + if (!(ObjectUtils.equals(prevTextValue, fieldText))) { + prevTextValue = fieldText; + listener.actionPerformed(fieldText, getValue()); + } + } + + protected void initModifiersMask() { + Configuration configuration = AppBeans.get(Configuration.NAME); + ClientConfig config = configuration.getConfig(ClientConfig.class); + String[] strModifiers = StringUtils.split(config.getPickerShortcutModifiers().toUpperCase(), "-"); + + for (String strModifier : strModifiers) { + KeyCombination.Modifier modifier = KeyCombination.Modifier.valueOf(strModifier); + modifiersMask = modifiersMask | DesktopComponentsHelper.convertModifier(modifier); + } + } + + @Override + public void setFieldEditable(boolean editable) { + if (isEditable()) + ((JTextField) impl.getEditor()).setEditable(editable); + } + + @Override + public T getValue() { + if ((datasource != null) && (metaPropertyPath != null) + && (datasource.getState() == Datasource.State.VALID) + && (datasource.getItem() != null)) { + return datasource.getItem().getValueEx(metaPropertyPath.toString()); + } else { + //noinspection unchecked + return (T) prevValue; + } + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (datasource == null && metaClass == null) { + throw new IllegalStateException("Datasource or metaclass must be set for field"); + } + + if (value != null) { + Class fieldClass = getMetaClass().getJavaClass(); + Class valueClass = value.getClass(); + //noinspection unchecked + if (!fieldClass.isAssignableFrom(valueClass)) { + throw new IllegalArgumentException( + String.format("Could not set value with class %s to field with class %s", + fieldClass.getCanonicalName(), + valueClass.getCanonicalName()) + ); + } + } + + if (!InstanceUtils.propertyValueEquals(prevValue, value)) { + updateInstance(value); + updateComponent(value); + fireChangeListeners(value); + } else { + updateComponent(prevValue); + } + } + + private void updateInstance(Object value) { + if (updatingInstance) + return; + + if (InstanceUtils.propertyValueEquals(prevValue, value)) + return; + + updatingInstance = true; + try { + if (datasource != null && metaProperty != null && datasource.getState() == Datasource.State.VALID && + datasource.getItem() != null) + InstanceUtils.setValueEx(datasource.getItem(), metaPropertyPath.getPath(), value); + } finally { + updatingInstance = false; + } + } + + @Override + public Datasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return metaProperty; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return metaPropertyPath; + } + + public void checkDatasourceProperty(Datasource datasource, String property){ + checkNotNullArgument(datasource); + checkNotNullArgument(property); + + MetaPropertyPath metaPropertyPath = getResolvedMetaPropertyPath(datasource.getMetaClass(), property); + if (!metaPropertyPath.getRange().isClass()) { + throw new DevelopmentException(String.format("property '%s.%s' should have Entity type", datasource.getMetaClass().getName(), property)); + } + } + + @Override + public void setDatasource(Datasource datasource, String property) { + checkDatasourceProperty(datasource, property); + this.datasource = datasource; + + // null datasource is not supported for this class + /*if (datasource == null) { + setValue(null); + return; + }*/ + + resolveMetaPropertyPath(datasource.getMetaClass(), property); + + itemChangeListener = e -> { + if (updatingInstance) { + return; + } + + Object value = InstanceUtils.getValueEx(e.getItem(), metaPropertyPath.getPath()); + updateComponent(value); + fireChangeListeners(value); + }; + //noinspection unchecked + datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener)); + + itemPropertyChangeListener = e -> { + if (updatingInstance) { + return; + } + + if (e.getProperty().equals(metaProperty.getName())) { + updateComponent(e.getValue()); + fireChangeListeners(e.getValue()); + } + }; + //noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + if ((datasource.getState() == Datasource.State.VALID) && (datasource.getItem() != null)) { + Object newValue = InstanceUtils.getValueEx(datasource.getItem(), metaPropertyPath.getPath()); + updateComponent(newValue); + fireChangeListeners(newValue); + } + + initRequired(metaPropertyPath); + + if (metaProperty.isReadOnly()) { + setEditable(false); + } + + handleFilteredAttributes(this, this.datasource, metaPropertyPath); + securityItemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath); + // noinspection unchecked + this.datasource.addItemChangeListener(new WeakItemChangeListener(this.datasource, securityItemChangeListener)); + + initBeanValidator(); + } + + protected void fireChangeListeners(Object newValue) { + if (!InstanceUtils.propertyValueEquals(prevValue, newValue)) { + Object oldValue = prevValue; + + prevValue = newValue; + + fireValueChanged(oldValue, newValue); + } + } + + protected void updateComponent(Object value) { + String text; + + if (value == null) { + text = ""; + } else { + if (value instanceof Instance) { + if (captionMode.equals(CaptionMode.ITEM)) { + text = ((Instance) value).getInstanceName(); + } else { + Object propertyValue = ((Instance)value).getValue(captionProperty); + MetaClass valueClass = metadata.getClassNN(value.getClass()); + MetaProperty property = valueClass.getProperty(captionProperty); + + text = metadataTools.format(propertyValue, property); + } + } else { + text = value.toString(); + } + } + + impl.setValue(text); + prevTextValue = text; + updateMissingValueState(); + } + + @Override + protected void setCaptionToComponent(String caption) { + super.setCaptionToComponent(caption); + + requestContainerUpdate(); + } + + @Override + public String getDescription() { + return impl.getEditor().getToolTipText(); + } + + @Override + public void setDescription(String description) { + if (!ObjectUtils.equals(this.getDescription(), description)) { + impl.getEditor().setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl.getEditor()); + + requestContainerUpdate(); + } + } + + @Override + protected void setEditableToComponent(boolean editable) { + for (Action action : actionsOrder) { + if (action instanceof StandardAction) { + ((StandardAction) action).setEditable(isEditable()); + } + } + if (!editable && impl.getEditor() instanceof JTextComponent) { + JTextComponent editor = (JTextComponent) impl.getEditor(); + editor.setEditable(false); + } + updateMissingValueState(); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + for (DesktopButton button : buttons) { + button.setParentEnabled(resultEnabled); + } + + if (impl.getEditor() instanceof JTextComponent) { + JTextComponent editor = (JTextComponent) impl.getEditor(); + editor.setFocusable(resultEnabled); + } + } + + @Override + public void addAction(Action action) { + int index = findActionById(actionsOrder, action.getId()); + if (index < 0) { + index = actionsOrder.size(); + } + + addAction(action, index); + } + + @Override + public void addAction(Action action, int index) { + checkNotNullArgument(action, "action must be non null"); + + int oldIndex = findActionById(actionsOrder, action.getId()); + if (oldIndex >= 0) { + removeAction(actionsOrder.get(oldIndex)); + if (index > oldIndex) { + index--; + } + } + + actionsOrder.add(index, action); + + DesktopButton dButton = new DesktopButton(); + dButton.setParentEnabled(isEnabledWithParent()); + dButton.setShouldBeFocused(false); + dButton.setAction(action); + dButton.getImpl().setFocusable(false); + dButton.getImpl().setText(""); + + impl.addButton(dButton.getImpl(), index); + buttons.add(dButton); + + // apply Editable after action owner is set + if (action instanceof StandardAction) { + ((StandardAction) action).setEditable(isEditable()); + } + + updateOrderedShortcuts(); + + ActionMap actionMap = getImpl().getInputField().getActionMap(); + actionMap.put(action.getId(), new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + action.actionPerform(dButton); + } + }); + + if (action.getShortcutCombination() != null) { + InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); + + KeyStroke shortcutKeyStroke = DesktopComponentsHelper.convertKeyCombination(action.getShortcutCombination()); + inputMap.put(shortcutKeyStroke, action.getId()); + } + + actionsPermissions.apply(action); + } + + @Override + public void removeAction(@Nullable Action action) { + if (action != null) { + if (actionsOrder.remove(action)) { + if (action.getOwner() != null && action.getOwner() instanceof DesktopButton) { + JButton button = ((DesktopButton) action.getOwner()).getImpl(); + impl.removeButton(button); + } + + InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); + ActionMap actionMap = getImpl().getInputField().getActionMap(); + List keyStrokes = keyStrokesMap.get(action); + if (keyStrokes != null) { + for (KeyStroke keyStroke : keyStrokes) { + inputMap.remove(keyStroke); + } + actionMap.remove(action.getId()); + } + + updateOrderedShortcuts(); + } + } + } + + protected void updateOrderedShortcuts() { + InputMap inputMap = getImpl().getInputField().getInputMap(JComponent.WHEN_FOCUSED); + for (int i = 0; i < 9; i++) { + KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_1 + i, modifiersMask, false); + inputMap.remove(keyStroke); + } + + int index = 0; + for (Action action : actionsOrder) { + KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_1 + index, modifiersMask, false); + List keyStrokes = new LinkedList<>(); + keyStrokes.add(keyStroke); + keyStrokesMap.put(action, keyStrokes); + + inputMap.put(keyStroke, action.getId()); + + index++; + } + } + + @Override + public void removeAction(@Nullable String id) { + Action action = getAction(id); + if (action != null) { + removeAction(action); + } + } + + @Override + public void removeAllActions() { + for (Action action : new ArrayList<>(actionsOrder)) { + removeAction(action); + } + } + + @Override + public Collection getActions() { + return Collections.unmodifiableCollection(actionsOrder); + } + + @Override + @Nullable + public Action getAction(String id) { + for (Action action : getActions()) { + if (ObjectUtils.equals(action.getId(), id)) { + return action; + } + } + return null; + } + + @Override + public void updateMissingValueState() { + if (!(impl.getEditor() instanceof JTextComponent)) { + return; + } + JTextComponent editor = (JTextComponent) impl.getEditor(); + boolean value = required && isEditableWithParent() && StringUtils.isBlank(editor.getText()); + + decorateMissingValue(impl.getEditor(), value); + } + + @Override + public ActionsPermissions getActionsPermissions() { + return actionsPermissions; + } + + @Override + public void setLookupSelectHandler(Runnable selectHandler) { + // do nothing + } + + @Override + public Collection getLookupSelectedItems() { + return Collections.singleton(getValue()); + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPopupButton.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPopupButton.java index 5c0fcc978c..1551aa3087 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPopupButton.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopPopupButton.java @@ -1,547 +1,547 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopResources; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Button; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.*; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import javax.swing.BoxLayout; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.List; - -import static java.awt.Component.CENTER_ALIGNMENT; - -public class DesktopPopupButton extends DesktopAbstractActionsHolderComponent implements PopupButton { - - public static final String DROP_DOWN_ICON = "/components/popupbutton/open-popup.png"; - - protected JPopupMenu popup; - - protected String icon; - - protected DesktopResources resources = App.getInstance().getResources(); - - protected List initializedActions = new ArrayList<>(); - protected final JLabel captionLabel; - protected final JLabel rightIcon; - - protected boolean togglePopupVisibilityOnClick = true; // just stub - protected PopupOpenDirection popupOpenDirection = PopupOpenDirection.BOTTOM_RIGHT; // just stub - protected boolean closePopupOnOutsideClick = true; // just stub - protected Component popupContent; // just stub - - public DesktopPopupButton() { - popup = new JPopupMenu(); - - impl = new JButton(); - impl.setLayout(new BoxLayout(impl, BoxLayout.X_AXIS)); - - captionLabel = new JLabel(); - impl.add(Box.createHorizontalGlue()); - impl.add(captionLabel); - captionLabel.setAlignmentX(CENTER_ALIGNMENT); - - rightIcon = new JLabel(); - rightIcon.setIcon(resources.getIcon(DROP_DOWN_ICON)); - rightIcon.setAlignmentX(CENTER_ALIGNMENT); - impl.add(rightIcon); - impl.add(Box.createHorizontalGlue()); - - impl.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (popup.isVisible()) - popup.setVisible(false); - else - showPopup(); - } - } - ); - DesktopComponentsHelper.adjustSize(impl); - } - - protected void showPopup() { - popup.removeAll(); - - for (final Action action : actionList) { - if (action.isVisible()) { - final JMenuItem menuItem = new JMenuItem(action.getCaption()); - menuItem.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - action.actionPerform((Component) action.getOwner()); - } - } - ); - menuItem.setEnabled(action.isEnabled()); - menuItem.setName(action.getId()); - - initAction(action, menuItem); - - popup.add(menuItem); - } - } - - int popupHeight = popup.getComponentCount() * 25; - - Point pt = new Point(); - SwingUtilities.convertPointToScreen(pt, impl); - - int y; - if (pt.getY() + impl.getHeight() + popupHeight < Toolkit.getDefaultToolkit().getScreenSize().getHeight()) { - y = impl.getHeight(); - } else { - y = -popupHeight; - } - - // do not show ugly empty popup - if (popup.getComponentCount() > 0) { - popup.show(impl, 0, y); - } - } - - protected void initAction(final Action action, final JMenuItem menuItem) { - if (initializedActions.contains(action)) - return; - - action.addPropertyChangeListener( - new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (Action.PROP_CAPTION.equals(evt.getPropertyName())) { - menuItem.setText(action.getCaption()); - } else if (Action.PROP_ENABLED.equals(evt.getPropertyName())) { - menuItem.setEnabled(action.isEnabled()); - } else if (Action.PROP_VISIBLE.equals(evt.getPropertyName())) { - menuItem.setVisible(action.isVisible()); - } - } - } - ); - - initializedActions.add(action); - } - - @Override - public boolean isPopupVisible() { - return popup.isVisible(); - } - - @Override - public void setPopupVisible(boolean popupVisible) { - if (popupVisible && !popup.isVisible()) { - showPopup(); - } else if (popup.isVisible()) { - popup.setVisible(false); - } - } - - @Override - public void setMenuWidth(String width) { - // unsupported - } - - @Override - public float getMenuWidth() { - return 0; // unsupported - } - - @Override - public int getMenuWidthUnits() { - return UNITS_PIXELS; // unsupported - } - - @Override - public boolean isAutoClose() { - return true; - } - - @Override - public void setAutoClose(boolean autoClose) { - } - - @Override - public void setShowActionIcons(boolean showActionIcons) { - // do nothing - } - - @Override - public boolean isShowActionIcons() { - return false; - } - - @Override - public boolean isTogglePopupVisibilityOnClick() { - return togglePopupVisibilityOnClick; - } - - @Override - public void setTogglePopupVisibilityOnClick(boolean togglePopupVisibilityOnClick) { - this.togglePopupVisibilityOnClick = togglePopupVisibilityOnClick; - } - - @Override - public PopupOpenDirection getPopupOpenDirection() { - return popupOpenDirection; - } - - @Override - public void setPopupOpenDirection(PopupOpenDirection popupOpenDirection) { - this.popupOpenDirection = popupOpenDirection; - } - - @Override - public boolean isClosePopupOnOutsideClick() { - return closePopupOnOutsideClick; - } - - @Override - public void setClosePopupOnOutsideClick(boolean closePopupOnOutsideClick) { - this.closePopupOnOutsideClick = closePopupOnOutsideClick; - } - - @Override - public void setPopupContent(Component popupContent) { - this.popupContent = popupContent; - } - - @Override - public Component getPopupContent() { - return popupContent; - } - - @Override - public void addPopupVisibilityListener(PopupVisibilityListener listener) { - // stub - } - - @Override - public void removePopupVisibilityListener(PopupVisibilityListener listener) { - // stub - } - - @Override - public String getCaption() { - return impl.getText(); - } - - @Override - public void setCaption(String caption) { - captionLabel.setText(caption); - - if (StringUtils.isNotEmpty(caption) || icon != null) { - rightIcon.setBorder(new EmptyBorder(0, 5, 0, 0)); - } else { - rightIcon.setBorder(null); - } - } - - @Override - public String getDescription() { - return getImpl().getToolTipText(); - } - - @Override - public void setDescription(String description) { - getImpl().setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } - - @Override - public String getIcon() { - return icon; - } - - @Override - public void setIcon(String icon) { - this.icon = icon; - if (icon != null) { - captionLabel.setIcon(resources.getIcon(icon)); - } else { - captionLabel.setIcon(resources.getIcon(DROP_DOWN_ICON)); - } - - if (StringUtils.isNotEmpty(getCaption()) || icon != null) { - rightIcon.setBorder(new EmptyBorder(0, 5, 0, 0)); - } else { - rightIcon.setBorder(null); - } - } - - @Override - public boolean isFocusable() { - return impl.isFocusable(); - } - - @Override - public void setFocusable(boolean focusable) { - impl.setFocusable(focusable); - } - - @Override - public void addAction(Action action, int index) { - super.addAction(action, index); - action.addOwner(new ButtonStub(action)); - } - - /** - * This class is only needed to serve as a pseudo-owner for actions. - */ - protected class ButtonStub implements Button { - - protected Action action; - protected boolean responsive = false; - - public ButtonStub(Action action) { - this.action = action; - } - - @Override - public Action getAction() { - return action; - } - - @Override - public void setAction(Action action) { - } - - @Override - public Frame getFrame() { - return DesktopPopupButton.this.getFrame(); - } - - @Override - public void setFrame(Frame frame) { - } - - @Override - public String getId() { - return "__" + action.getId() + "_button"; - } - - @Override - public void setId(String id) { - } - - @Override - public boolean isResponsive() { - return responsive; - } - - @Override - public void setResponsive(boolean responsive) { - this.responsive = responsive; - } - - @Override - public Component getParent() { - return null; - } - - @Override - public void setParent(Component parent) { - } - - @Override - public String getDebugId() { - return getId(); - } - - @Override - public void setDebugId(String id) { - } - - @Override - public boolean isEnabled() { - return action.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - } - - @Override - public boolean isVisible() { - return DesktopPopupButton.this.isVisible(); - } - - @Override - public void setVisible(boolean visible) { - } - - @Override - public boolean isVisibleItself() { - return DesktopPopupButton.this.isVisibleItself(); - } - - @Override - public boolean isEnabledItself() { - return action.isEnabled(); - } - - @Override - public void requestFocus() { - } - - @Override - public float getHeight() { - return 0; - } - - @Override - public int getHeightUnits() { - return 0; - } - - @Override - public void setHeight(String height) { - } - - @Override - public float getWidth() { - return 0; - } - - @Override - public int getWidthUnits() { - return 0; - } - - @Override - public void setWidth(String width) { - } - - @Override - public Alignment getAlignment() { - return DesktopPopupButton.this.getAlignment(); - } - - @Override - public void setAlignment(Alignment alignment) { - } - - @Override - public String getStyleName() { - return DesktopPopupButton.this.getStyleName(); - } - - @Override - public void setStyleName(String styleName) { - DesktopPopupButton.this.setStyleName(styleName); - } - - @Override - public void addStyleName(String styleName) { - DesktopPopupButton.this.addStyleName(styleName); - } - - @Override - public void removeStyleName(String styleName) { - DesktopPopupButton.this.removeStyleName(styleName); - } - - @Override - public X unwrap(Class internalComponentClass) { - return null; - } - - @Override - public X unwrapComposition(Class internalCompositionClass) { - return null; - } - - @Override - public String getCaption() { - return action.getCaption(); - } - - @Override - public void setCaption(String caption) { - } - - @Override - public String getDescription() { - return DesktopPopupButton.this.getDescription(); - } - - @Override - public void setDescription(String description) { - } - - @Override - public String getIcon() { - return action.getIcon(); - } - - @Override - public void setIcon(String icon) { - } - - @Override - public boolean isFocusable() { - return DesktopPopupButton.this.isFocusable(); - } - - @Override - public void setFocusable(boolean focusable) { - } - - @Override - public int getTabIndex() { - return 0; - } - - @Override - public void setTabIndex(int tabIndex) { - } - - @Override - public void setDisableOnClick(boolean value) { - } - - @Override - public boolean isDisableOnClick() { - return false; - } - - @Override - public boolean isUseResponsePending() { - return false; - } - - @Override - public void setUseResponsePending(boolean useResponsePending) { - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopResources; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Button; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.*; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import javax.swing.BoxLayout; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +import static java.awt.Component.CENTER_ALIGNMENT; + +public class DesktopPopupButton extends DesktopAbstractActionsHolderComponent implements PopupButton { + + public static final String DROP_DOWN_ICON = "/components/popupbutton/open-popup.png"; + + protected JPopupMenu popup; + + protected String icon; + + protected DesktopResources resources = App.getInstance().getResources(); + + protected List initializedActions = new ArrayList<>(); + protected final JLabel captionLabel; + protected final JLabel rightIcon; + + protected boolean togglePopupVisibilityOnClick = true; // just stub + protected PopupOpenDirection popupOpenDirection = PopupOpenDirection.BOTTOM_RIGHT; // just stub + protected boolean closePopupOnOutsideClick = true; // just stub + protected Component popupContent; // just stub + + public DesktopPopupButton() { + popup = new JPopupMenu(); + + impl = new JButton(); + impl.setLayout(new BoxLayout(impl, BoxLayout.X_AXIS)); + + captionLabel = new JLabel(); + impl.add(Box.createHorizontalGlue()); + impl.add(captionLabel); + captionLabel.setAlignmentX(CENTER_ALIGNMENT); + + rightIcon = new JLabel(); + rightIcon.setIcon(resources.getIcon(DROP_DOWN_ICON)); + rightIcon.setAlignmentX(CENTER_ALIGNMENT); + impl.add(rightIcon); + impl.add(Box.createHorizontalGlue()); + + impl.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (popup.isVisible()) + popup.setVisible(false); + else + showPopup(); + } + } + ); + DesktopComponentsHelper.adjustSize(impl); + } + + protected void showPopup() { + popup.removeAll(); + + for (final Action action : actionList) { + if (action.isVisible()) { + final JMenuItem menuItem = new JMenuItem(action.getCaption()); + menuItem.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + action.actionPerform((Component) action.getOwner()); + } + } + ); + menuItem.setEnabled(action.isEnabled()); + menuItem.setName(action.getId()); + + initAction(action, menuItem); + + popup.add(menuItem); + } + } + + int popupHeight = popup.getComponentCount() * 25; + + Point pt = new Point(); + SwingUtilities.convertPointToScreen(pt, impl); + + int y; + if (pt.getY() + impl.getHeight() + popupHeight < Toolkit.getDefaultToolkit().getScreenSize().getHeight()) { + y = impl.getHeight(); + } else { + y = -popupHeight; + } + + // do not show ugly empty popup + if (popup.getComponentCount() > 0) { + popup.show(impl, 0, y); + } + } + + protected void initAction(final Action action, final JMenuItem menuItem) { + if (initializedActions.contains(action)) + return; + + action.addPropertyChangeListener( + new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (Action.PROP_CAPTION.equals(evt.getPropertyName())) { + menuItem.setText(action.getCaption()); + } else if (Action.PROP_ENABLED.equals(evt.getPropertyName())) { + menuItem.setEnabled(action.isEnabled()); + } else if (Action.PROP_VISIBLE.equals(evt.getPropertyName())) { + menuItem.setVisible(action.isVisible()); + } + } + } + ); + + initializedActions.add(action); + } + + @Override + public boolean isPopupVisible() { + return popup.isVisible(); + } + + @Override + public void setPopupVisible(boolean popupVisible) { + if (popupVisible && !popup.isVisible()) { + showPopup(); + } else if (popup.isVisible()) { + popup.setVisible(false); + } + } + + @Override + public void setMenuWidth(String width) { + // unsupported + } + + @Override + public float getMenuWidth() { + return 0; // unsupported + } + + @Override + public int getMenuWidthUnits() { + return UNITS_PIXELS; // unsupported + } + + @Override + public boolean isAutoClose() { + return true; + } + + @Override + public void setAutoClose(boolean autoClose) { + } + + @Override + public void setShowActionIcons(boolean showActionIcons) { + // do nothing + } + + @Override + public boolean isShowActionIcons() { + return false; + } + + @Override + public boolean isTogglePopupVisibilityOnClick() { + return togglePopupVisibilityOnClick; + } + + @Override + public void setTogglePopupVisibilityOnClick(boolean togglePopupVisibilityOnClick) { + this.togglePopupVisibilityOnClick = togglePopupVisibilityOnClick; + } + + @Override + public PopupOpenDirection getPopupOpenDirection() { + return popupOpenDirection; + } + + @Override + public void setPopupOpenDirection(PopupOpenDirection popupOpenDirection) { + this.popupOpenDirection = popupOpenDirection; + } + + @Override + public boolean isClosePopupOnOutsideClick() { + return closePopupOnOutsideClick; + } + + @Override + public void setClosePopupOnOutsideClick(boolean closePopupOnOutsideClick) { + this.closePopupOnOutsideClick = closePopupOnOutsideClick; + } + + @Override + public void setPopupContent(Component popupContent) { + this.popupContent = popupContent; + } + + @Override + public Component getPopupContent() { + return popupContent; + } + + @Override + public void addPopupVisibilityListener(PopupVisibilityListener listener) { + // stub + } + + @Override + public void removePopupVisibilityListener(PopupVisibilityListener listener) { + // stub + } + + @Override + public String getCaption() { + return impl.getText(); + } + + @Override + public void setCaption(String caption) { + captionLabel.setText(caption); + + if (StringUtils.isNotEmpty(caption) || icon != null) { + rightIcon.setBorder(new EmptyBorder(0, 5, 0, 0)); + } else { + rightIcon.setBorder(null); + } + } + + @Override + public String getDescription() { + return getImpl().getToolTipText(); + } + + @Override + public void setDescription(String description) { + getImpl().setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } + + @Override + public String getIcon() { + return icon; + } + + @Override + public void setIcon(String icon) { + this.icon = icon; + if (icon != null) { + captionLabel.setIcon(resources.getIcon(icon)); + } else { + captionLabel.setIcon(resources.getIcon(DROP_DOWN_ICON)); + } + + if (StringUtils.isNotEmpty(getCaption()) || icon != null) { + rightIcon.setBorder(new EmptyBorder(0, 5, 0, 0)); + } else { + rightIcon.setBorder(null); + } + } + + @Override + public boolean isFocusable() { + return impl.isFocusable(); + } + + @Override + public void setFocusable(boolean focusable) { + impl.setFocusable(focusable); + } + + @Override + public void addAction(Action action, int index) { + super.addAction(action, index); + action.addOwner(new ButtonStub(action)); + } + + /** + * This class is only needed to serve as a pseudo-owner for actions. + */ + protected class ButtonStub implements Button { + + protected Action action; + protected boolean responsive = false; + + public ButtonStub(Action action) { + this.action = action; + } + + @Override + public Action getAction() { + return action; + } + + @Override + public void setAction(Action action) { + } + + @Override + public Frame getFrame() { + return DesktopPopupButton.this.getFrame(); + } + + @Override + public void setFrame(Frame frame) { + } + + @Override + public String getId() { + return "__" + action.getId() + "_button"; + } + + @Override + public void setId(String id) { + } + + @Override + public boolean isResponsive() { + return responsive; + } + + @Override + public void setResponsive(boolean responsive) { + this.responsive = responsive; + } + + @Override + public Component getParent() { + return null; + } + + @Override + public void setParent(Component parent) { + } + + @Override + public String getDebugId() { + return getId(); + } + + @Override + public void setDebugId(String id) { + } + + @Override + public boolean isEnabled() { + return action.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + } + + @Override + public boolean isVisible() { + return DesktopPopupButton.this.isVisible(); + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public boolean isVisibleItself() { + return DesktopPopupButton.this.isVisibleItself(); + } + + @Override + public boolean isEnabledItself() { + return action.isEnabled(); + } + + @Override + public void requestFocus() { + } + + @Override + public float getHeight() { + return 0; + } + + @Override + public int getHeightUnits() { + return 0; + } + + @Override + public void setHeight(String height) { + } + + @Override + public float getWidth() { + return 0; + } + + @Override + public int getWidthUnits() { + return 0; + } + + @Override + public void setWidth(String width) { + } + + @Override + public Alignment getAlignment() { + return DesktopPopupButton.this.getAlignment(); + } + + @Override + public void setAlignment(Alignment alignment) { + } + + @Override + public String getStyleName() { + return DesktopPopupButton.this.getStyleName(); + } + + @Override + public void setStyleName(String styleName) { + DesktopPopupButton.this.setStyleName(styleName); + } + + @Override + public void addStyleName(String styleName) { + DesktopPopupButton.this.addStyleName(styleName); + } + + @Override + public void removeStyleName(String styleName) { + DesktopPopupButton.this.removeStyleName(styleName); + } + + @Override + public X unwrap(Class internalComponentClass) { + return null; + } + + @Override + public X unwrapComposition(Class internalCompositionClass) { + return null; + } + + @Override + public String getCaption() { + return action.getCaption(); + } + + @Override + public void setCaption(String caption) { + } + + @Override + public String getDescription() { + return DesktopPopupButton.this.getDescription(); + } + + @Override + public void setDescription(String description) { + } + + @Override + public String getIcon() { + return action.getIcon(); + } + + @Override + public void setIcon(String icon) { + } + + @Override + public boolean isFocusable() { + return DesktopPopupButton.this.isFocusable(); + } + + @Override + public void setFocusable(boolean focusable) { + } + + @Override + public int getTabIndex() { + return 0; + } + + @Override + public void setTabIndex(int tabIndex) { + } + + @Override + public void setDisableOnClick(boolean value) { + } + + @Override + public boolean isDisableOnClick() { + return false; + } + + @Override + public boolean isUseResponsePending() { + return false; + } + + @Override + public void setUseResponsePending(boolean useResponsePending) { + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopProgressBar.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopProgressBar.java index a46cc6691e..431239ebd8 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopProgressBar.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopProgressBar.java @@ -1,142 +1,142 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.gui.components.ProgressBar; -import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; -import com.haulmont.cuba.gui.data.ValueListener; -import org.apache.commons.lang.ObjectUtils; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * Desktop implementation of progress bar depending on swing JProgressBar component. - */ -public class DesktopProgressBar extends DesktopAbstractComponent implements ProgressBar { - - protected boolean editable = true; - protected List valueChangeListeners = new ArrayList<>(); - protected Object prevValue; - - private static final int WHOLE_PROGRESS = 100; - - public DesktopProgressBar() { - impl = new JProgressBar(); - impl.setMinimum(0); - impl.setMaximum(WHOLE_PROGRESS); - } - - @Override - public void addListener(ValueListener listener) { - addValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - @Override - public void removeListener(ValueListener listener) { - removeValueChangeListener(new ComponentValueListenerWrapper(listener)); - } - - protected void fireValueChanged(Object prevValue, Object value) { - for (ValueChangeListener listener : new ArrayList<>(valueChangeListeners)) { - listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); - } - } - - @Override - public void addValueChangeListener(ValueChangeListener listener) { - if (!valueChangeListeners.contains(listener)) { - valueChangeListeners.add(listener); - } - } - - @Override - public void removeValueChangeListener(ValueChangeListener listener) { - valueChangeListeners.remove(listener); - } - - @Override - public boolean isIndeterminate() { - return impl.isIndeterminate(); - } - - @Override - public void setIndeterminate(boolean indeterminate) { - impl.setIndeterminate(indeterminate); - } - - @Override - public Float getValue() { - Float value = convertValueFromSwing(impl.getValue()); - return value; - } - - @Override - public void setValue(Object value) { - DesktopBackgroundWorker.checkSwingUIAccess(); - - if (!ObjectUtils.equals(prevValue, value)) { - updateComponent(value); - fireChangeListeners(value); - } - } - - protected void fireChangeListeners(Object newValue) { - Object oldValue = prevValue; - prevValue = newValue; - if (!ObjectUtils.equals(oldValue, newValue)) { - fireValueChanged(oldValue, newValue); - } - } - - protected void updateComponent(Object value) { - float floatValue = value != null ? ((Number) value).floatValue() : 0; - int progress = convertValueToSwing(floatValue); - impl.setValue(progress); - } - - @Override - public boolean isEditable() { - return editable; - } - - @Override - public void setEditable(boolean editable) { - this.editable = editable; - } - - protected int convertValueToSwing(float progress) { - return Math.round(progress * WHOLE_PROGRESS); - } - - protected float convertValueFromSwing(int progress) { - return (float) progress / (float) WHOLE_PROGRESS; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.gui.components.ProgressBar; +import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; +import com.haulmont.cuba.gui.data.ValueListener; +import org.apache.commons.lang.ObjectUtils; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Desktop implementation of progress bar depending on swing JProgressBar component. + */ +public class DesktopProgressBar extends DesktopAbstractComponent implements ProgressBar { + + protected boolean editable = true; + protected List valueChangeListeners = new ArrayList<>(); + protected Object prevValue; + + private static final int WHOLE_PROGRESS = 100; + + public DesktopProgressBar() { + impl = new JProgressBar(); + impl.setMinimum(0); + impl.setMaximum(WHOLE_PROGRESS); + } + + @Override + public void addListener(ValueListener listener) { + addValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + @Override + public void removeListener(ValueListener listener) { + removeValueChangeListener(new ComponentValueListenerWrapper(listener)); + } + + protected void fireValueChanged(Object prevValue, Object value) { + for (ValueChangeListener listener : new ArrayList<>(valueChangeListeners)) { + listener.valueChanged(new ValueChangeEvent(this, prevValue, value)); + } + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + if (!valueChangeListeners.contains(listener)) { + valueChangeListeners.add(listener); + } + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + valueChangeListeners.remove(listener); + } + + @Override + public boolean isIndeterminate() { + return impl.isIndeterminate(); + } + + @Override + public void setIndeterminate(boolean indeterminate) { + impl.setIndeterminate(indeterminate); + } + + @Override + public Float getValue() { + Float value = convertValueFromSwing(impl.getValue()); + return value; + } + + @Override + public void setValue(Object value) { + DesktopBackgroundWorker.checkSwingUIAccess(); + + if (!ObjectUtils.equals(prevValue, value)) { + updateComponent(value); + fireChangeListeners(value); + } + } + + protected void fireChangeListeners(Object newValue) { + Object oldValue = prevValue; + prevValue = newValue; + if (!ObjectUtils.equals(oldValue, newValue)) { + fireValueChanged(oldValue, newValue); + } + } + + protected void updateComponent(Object value) { + float floatValue = value != null ? ((Number) value).floatValue() : 0; + int progress = convertValueToSwing(floatValue); + impl.setValue(progress); + } + + @Override + public boolean isEditable() { + return editable; + } + + @Override + public void setEditable(boolean editable) { + this.editable = editable; + } + + protected int convertValueToSwing(float progress) { + return Math.round(progress * WHOLE_PROGRESS); + } + + protected float convertValueFromSwing(int progress) { + return (float) progress / (float) WHOLE_PROGRESS; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopResizableTextArea.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopResizableTextArea.java index 743b4bb3c1..6792f4ca87 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopResizableTextArea.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopResizableTextArea.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.ResizableTextArea; -import org.dom4j.Element; - -public class DesktopResizableTextArea extends DesktopTextArea implements ResizableTextArea { - - protected boolean resizable = false; - protected boolean settingsEnabled = true; - protected ResizeDirection resizeDirection = ResizeDirection.NONE; - - @Override - public boolean isResizable() { - return resizable; - } - - @Override - public void setResizable(boolean resizable) { - this.resizable = resizable; - //Do nothing, because desktop text area is not resizable - } - - @Override - public void addResizeListener(com.haulmont.cuba.gui.components.ResizeListener resizeListener) { - //Do nothing, because desktop text area is not resizable - } - - @Override - public void removeResizeListener(com.haulmont.cuba.gui.components.ResizeListener resizeListener) { - //Do nothing, because desktop text area is not resizable - } - - @Override - public void addResizeListener(ResizeListener resizeListener) { - //Do nothing, because desktop text area is not resizable - } - - @Override - public void removeResizeListener(ResizeListener resizeListener) { - //Do nothing, because desktop text area is not resizable - } - - @Override - public void applySettings(Element element) { - //Do nothing, because desktop text area is not resizable - } - - @Override - public boolean saveSettings(Element element) { - return false; - } - - @Override - public boolean isSettingsEnabled() { - return settingsEnabled; - } - - @Override - public void setSettingsEnabled(boolean settingsEnabled) { - this.settingsEnabled = settingsEnabled; - //Do nothing, because desktop text area is not resizable - } - - @Override - public void setResizableDirection(ResizeDirection direction) { - resizeDirection = direction; - //Do nothing, because desktop text area is not resizable - } - - @Override - public ResizeDirection getResizableDirection() { - //Do nothing, because desktop text area is not resizable - return resizeDirection; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.ResizableTextArea; +import org.dom4j.Element; + +public class DesktopResizableTextArea extends DesktopTextArea implements ResizableTextArea { + + protected boolean resizable = false; + protected boolean settingsEnabled = true; + protected ResizeDirection resizeDirection = ResizeDirection.NONE; + + @Override + public boolean isResizable() { + return resizable; + } + + @Override + public void setResizable(boolean resizable) { + this.resizable = resizable; + //Do nothing, because desktop text area is not resizable + } + + @Override + public void addResizeListener(com.haulmont.cuba.gui.components.ResizeListener resizeListener) { + //Do nothing, because desktop text area is not resizable + } + + @Override + public void removeResizeListener(com.haulmont.cuba.gui.components.ResizeListener resizeListener) { + //Do nothing, because desktop text area is not resizable + } + + @Override + public void addResizeListener(ResizeListener resizeListener) { + //Do nothing, because desktop text area is not resizable + } + + @Override + public void removeResizeListener(ResizeListener resizeListener) { + //Do nothing, because desktop text area is not resizable + } + + @Override + public void applySettings(Element element) { + //Do nothing, because desktop text area is not resizable + } + + @Override + public boolean saveSettings(Element element) { + return false; + } + + @Override + public boolean isSettingsEnabled() { + return settingsEnabled; + } + + @Override + public void setSettingsEnabled(boolean settingsEnabled) { + this.settingsEnabled = settingsEnabled; + //Do nothing, because desktop text area is not resizable + } + + @Override + public void setResizableDirection(ResizeDirection direction) { + resizeDirection = direction; + //Do nothing, because desktop text area is not resizable + } + + @Override + public ResizeDirection getResizableDirection() { + //Do nothing, because desktop text area is not resizable + return resizeDirection; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopRowsCount.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopRowsCount.java index cab2871792..04326b0395 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopRowsCount.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopRowsCount.java @@ -1,375 +1,375 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.components.ListComponent; -import com.haulmont.cuba.gui.components.RowsCount; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.CollectionDatasource.Operation; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; -import org.jdesktop.swingx.JXHyperlink; -import org.jdesktop.swingx.JXTable; - -import javax.swing.*; -import java.awt.*; - -public class DesktopRowsCount extends DesktopAbstractComponent - implements RowsCount { - - protected CollectionDatasource datasource; - protected boolean refreshing; - protected State state; - protected State lastState; - protected int start; - protected int size; - protected ListComponent owner; - protected boolean samePage; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - public DesktopRowsCount() { - impl = new RowsCountComponent(); - } - - @Override - public CollectionDatasource getDatasource() { - return datasource; - } - - @Override - public void setDatasource(CollectionDatasource datasource) { - this.datasource = datasource; - if (datasource != null) { - collectionChangeListener = e -> { - samePage = Operation.REFRESH != e.getOperation() - && Operation.CLEAR != e.getOperation(); - onCollectionChanged(); - }; - //noinspection unchecked - this.datasource.addCollectionChangeListener(new WeakCollectionChangeListener(this.datasource, collectionChangeListener)); - - impl.getCountButton().addActionListener(e -> onLinkClick()); - - impl.getPrevButton().addActionListener(e -> onPrevClick()); - impl.getNextButton().addActionListener(e -> onNextClick()); - impl.getFirstButton().addActionListener(e -> onFirstClick()); - impl.getLastButton().addActionListener(e -> onLastClick()); - if (datasource.getState() == Datasource.State.VALID) { - onCollectionChanged(); - } - } - } - - @Override - public ListComponent getOwner() { - return owner; - } - - @Override - public void setOwner(ListComponent owner) { - this.owner = owner; - } - - protected void onCollectionChanged() { - if (datasource == null) { - return; - } - - String msgKey; - size = datasource.size(); - start = 0; - - boolean refreshSizeButton = false; - if (datasource instanceof CollectionDatasource.SupportsPaging) { - CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; - if (samePage) { - state = lastState == null ? State.FIRST_COMPLETE : lastState; - start = ds.getFirstResult(); - samePage = false; - refreshSizeButton = State.LAST.equals(state); - } else if ((size == 0 || size < ds.getMaxResults()) && ds.getFirstResult() == 0) { - state = State.FIRST_COMPLETE; - lastState = state; - } else if (size == ds.getMaxResults() && ds.getFirstResult() == 0) { - state = State.FIRST_INCOMPLETE; - lastState = state; - } else if (size == ds.getMaxResults() && ds.getFirstResult() > 0) { - state = State.MIDDLE; - start = ds.getFirstResult(); - lastState = state; - } else if (size < ds.getMaxResults() && ds.getFirstResult() > 0) { - state = State.LAST; - start = ds.getFirstResult(); - lastState = state; - } else { - state = State.FIRST_COMPLETE; - lastState = state; - } - } else { - state = State.FIRST_COMPLETE; - lastState = state; - } - - String countValue; - switch (state) { - case FIRST_COMPLETE: - impl.getCountButton().setVisible(false); - impl.getPrevButton().setVisible(false); - impl.getNextButton().setVisible(false); - impl.getFirstButton().setVisible(false); - impl.getLastButton().setVisible(false); - if (size % 100 > 10 && size % 100 < 20) { - msgKey = "table.rowsCount.msg2Plural1"; - } else { - switch (size % 10) { - case 1: - msgKey = "table.rowsCount.msg2Singular"; - break; - case 2: - case 3: - case 4: - msgKey = "table.rowsCount.msg2Plural2"; - break; - default: - msgKey = "table.rowsCount.msg2Plural1"; - } - } - countValue = String.valueOf(size); - break; - case FIRST_INCOMPLETE: - impl.getCountButton().setVisible(true); - impl.getPrevButton().setVisible(false); - impl.getNextButton().setVisible(true); - impl.getFirstButton().setVisible(false); - impl.getLastButton().setVisible(true); - msgKey = "table.rowsCount.msg1"; - countValue = countValue(start, size); - break; - case MIDDLE: - impl.getCountButton().setVisible(true); - impl.getPrevButton().setVisible(true); - impl.getNextButton().setVisible(true); - impl.getFirstButton().setVisible(true); - impl.getLastButton().setVisible(true); - msgKey = "table.rowsCount.msg1"; - countValue = countValue(start, size); - break; - case LAST: - impl.getCountButton().setVisible(false); - impl.getPrevButton().setVisible(true); - impl.getNextButton().setVisible(false); - impl.getFirstButton().setVisible(true); - impl.getLastButton().setVisible(false); - msgKey = "table.rowsCount.msg2Plural2"; - countValue = countValue(start, size); - break; - default: - throw new UnsupportedOperationException(); - } - - String messagesPack = AppConfig.getMessagesPack(); - Messages messages = AppBeans.get(Messages.NAME); - impl.getLabel().setText(messages.formatMessage(messagesPack, msgKey, countValue)); - - if (impl.getCountButton().isVisible() && !refreshing || refreshSizeButton) { - impl.getCountButton().setText(messages.getMessage(messagesPack, "table.rowsCount.msg3")); - } - impl.repaint(); - impl.revalidate(); - } - - protected String countValue(int start, int size) { - if (size == 0) { - return String.valueOf(size); - } else { - return (start + 1) + "-" + (start + size); - } - } - - private void onLinkClick() { - if (datasource == null || !(datasource instanceof CollectionDatasource.SupportsPaging)) { - return; - } - - int count = ((CollectionDatasource.SupportsPaging) datasource).getCount(); - impl.getCountButton().setText(String.valueOf(count)); - } - - private void onNextClick() { - if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { - return; - } - - CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; - int firstResult = ds.getFirstResult(); - ds.setFirstResult(ds.getFirstResult() + ds.getMaxResults()); - refreshDatasource(ds); - - if (state == State.LAST && size == 0) { - ds.setFirstResult(firstResult); - int maxResults = ds.getMaxResults(); - ds.setMaxResults(maxResults + 1); - refreshDatasource(ds); - ds.setMaxResults(maxResults); - } - if (owner instanceof DesktopAbstractTable) { - JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); - table.scrollRowToVisible(0); - } - } - - private void onPrevClick() { - if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { - return; - } - - CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; - int newStart = ds.getFirstResult() - ds.getMaxResults(); - ds.setFirstResult(newStart < 0 ? 0 : newStart); - refreshDatasource(ds); - if (owner instanceof DesktopAbstractTable) { - JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); - table.scrollRowToVisible(0); - } - } - - protected void onFirstClick() { - if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { - return; - } - - CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; - ds.setFirstResult(0); - refreshDatasource(ds); - if (owner instanceof DesktopAbstractTable) { - JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); - table.scrollRowToVisible(0); - } - } - - protected void onLastClick() { - if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { - return; - } - - CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; - int count = ((CollectionDatasource.SupportsPaging) datasource).getCount(); - int itemsToDisplay = count % ds.getMaxResults(); - if (itemsToDisplay == 0) itemsToDisplay = ds.getMaxResults(); - - ds.setFirstResult(count - itemsToDisplay); - refreshDatasource(ds); - - if (owner instanceof DesktopAbstractTable) { - JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); - table.scrollRowToVisible(0); - } - } - - - private void refreshDatasource(CollectionDatasource.SupportsPaging ds) { - refreshing = true; - try { - ds.refresh(); - } finally { - refreshing = false; - } - } - - public static class RowsCountComponent extends JPanel { - - private JButton prevButton; - private JButton nextButton; - private JButton firstButton; - private JButton lastButton; - private JLabel label; - private JButton countButton; - private MigLayout layout; - - private final Dimension size = new Dimension(38, 25); - - public RowsCountComponent() { - LC lc = new LC(); - lc.insetsAll("2"); - - layout = new MigLayout(lc); - if (LayoutAdapter.isDebug()) { - lc.debug(1000); - } - setLayout(layout); - - firstButton = new JButton("<<"); - add(firstButton); - firstButton.setPreferredSize(size); - firstButton.setMinimumSize(size); - - prevButton = new JButton("<"); - add(prevButton); - prevButton.setPreferredSize(size); - prevButton.setMinimumSize(size); - - label = new JLabel(); - add(label); - - countButton = new JXHyperlink(); - countButton.setText("[?]"); - add(countButton); - - nextButton = new JButton(">"); - add(nextButton); - nextButton.setPreferredSize(size); - nextButton.setMinimumSize(size); - - lastButton = new JButton(">>"); - add(lastButton); - lastButton.setPreferredSize(size); - lastButton.setMinimumSize(size); - } - - public JLabel getLabel() { - return label; - } - - public JButton getCountButton() { - return countButton; - } - - public JButton getPrevButton() { - return prevButton; - } - - public JButton getNextButton() { - return nextButton; - } - - public JButton getFirstButton() { - return firstButton; - } - - public JButton getLastButton() { - return lastButton; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.components.ListComponent; +import com.haulmont.cuba.gui.components.RowsCount; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.CollectionDatasource.Operation; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; +import org.jdesktop.swingx.JXHyperlink; +import org.jdesktop.swingx.JXTable; + +import javax.swing.*; +import java.awt.*; + +public class DesktopRowsCount extends DesktopAbstractComponent + implements RowsCount { + + protected CollectionDatasource datasource; + protected boolean refreshing; + protected State state; + protected State lastState; + protected int start; + protected int size; + protected ListComponent owner; + protected boolean samePage; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + public DesktopRowsCount() { + impl = new RowsCountComponent(); + } + + @Override + public CollectionDatasource getDatasource() { + return datasource; + } + + @Override + public void setDatasource(CollectionDatasource datasource) { + this.datasource = datasource; + if (datasource != null) { + collectionChangeListener = e -> { + samePage = Operation.REFRESH != e.getOperation() + && Operation.CLEAR != e.getOperation(); + onCollectionChanged(); + }; + //noinspection unchecked + this.datasource.addCollectionChangeListener(new WeakCollectionChangeListener(this.datasource, collectionChangeListener)); + + impl.getCountButton().addActionListener(e -> onLinkClick()); + + impl.getPrevButton().addActionListener(e -> onPrevClick()); + impl.getNextButton().addActionListener(e -> onNextClick()); + impl.getFirstButton().addActionListener(e -> onFirstClick()); + impl.getLastButton().addActionListener(e -> onLastClick()); + if (datasource.getState() == Datasource.State.VALID) { + onCollectionChanged(); + } + } + } + + @Override + public ListComponent getOwner() { + return owner; + } + + @Override + public void setOwner(ListComponent owner) { + this.owner = owner; + } + + protected void onCollectionChanged() { + if (datasource == null) { + return; + } + + String msgKey; + size = datasource.size(); + start = 0; + + boolean refreshSizeButton = false; + if (datasource instanceof CollectionDatasource.SupportsPaging) { + CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; + if (samePage) { + state = lastState == null ? State.FIRST_COMPLETE : lastState; + start = ds.getFirstResult(); + samePage = false; + refreshSizeButton = State.LAST.equals(state); + } else if ((size == 0 || size < ds.getMaxResults()) && ds.getFirstResult() == 0) { + state = State.FIRST_COMPLETE; + lastState = state; + } else if (size == ds.getMaxResults() && ds.getFirstResult() == 0) { + state = State.FIRST_INCOMPLETE; + lastState = state; + } else if (size == ds.getMaxResults() && ds.getFirstResult() > 0) { + state = State.MIDDLE; + start = ds.getFirstResult(); + lastState = state; + } else if (size < ds.getMaxResults() && ds.getFirstResult() > 0) { + state = State.LAST; + start = ds.getFirstResult(); + lastState = state; + } else { + state = State.FIRST_COMPLETE; + lastState = state; + } + } else { + state = State.FIRST_COMPLETE; + lastState = state; + } + + String countValue; + switch (state) { + case FIRST_COMPLETE: + impl.getCountButton().setVisible(false); + impl.getPrevButton().setVisible(false); + impl.getNextButton().setVisible(false); + impl.getFirstButton().setVisible(false); + impl.getLastButton().setVisible(false); + if (size % 100 > 10 && size % 100 < 20) { + msgKey = "table.rowsCount.msg2Plural1"; + } else { + switch (size % 10) { + case 1: + msgKey = "table.rowsCount.msg2Singular"; + break; + case 2: + case 3: + case 4: + msgKey = "table.rowsCount.msg2Plural2"; + break; + default: + msgKey = "table.rowsCount.msg2Plural1"; + } + } + countValue = String.valueOf(size); + break; + case FIRST_INCOMPLETE: + impl.getCountButton().setVisible(true); + impl.getPrevButton().setVisible(false); + impl.getNextButton().setVisible(true); + impl.getFirstButton().setVisible(false); + impl.getLastButton().setVisible(true); + msgKey = "table.rowsCount.msg1"; + countValue = countValue(start, size); + break; + case MIDDLE: + impl.getCountButton().setVisible(true); + impl.getPrevButton().setVisible(true); + impl.getNextButton().setVisible(true); + impl.getFirstButton().setVisible(true); + impl.getLastButton().setVisible(true); + msgKey = "table.rowsCount.msg1"; + countValue = countValue(start, size); + break; + case LAST: + impl.getCountButton().setVisible(false); + impl.getPrevButton().setVisible(true); + impl.getNextButton().setVisible(false); + impl.getFirstButton().setVisible(true); + impl.getLastButton().setVisible(false); + msgKey = "table.rowsCount.msg2Plural2"; + countValue = countValue(start, size); + break; + default: + throw new UnsupportedOperationException(); + } + + String messagesPack = AppConfig.getMessagesPack(); + Messages messages = AppBeans.get(Messages.NAME); + impl.getLabel().setText(messages.formatMessage(messagesPack, msgKey, countValue)); + + if (impl.getCountButton().isVisible() && !refreshing || refreshSizeButton) { + impl.getCountButton().setText(messages.getMessage(messagesPack, "table.rowsCount.msg3")); + } + impl.repaint(); + impl.revalidate(); + } + + protected String countValue(int start, int size) { + if (size == 0) { + return String.valueOf(size); + } else { + return (start + 1) + "-" + (start + size); + } + } + + private void onLinkClick() { + if (datasource == null || !(datasource instanceof CollectionDatasource.SupportsPaging)) { + return; + } + + int count = ((CollectionDatasource.SupportsPaging) datasource).getCount(); + impl.getCountButton().setText(String.valueOf(count)); + } + + private void onNextClick() { + if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { + return; + } + + CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; + int firstResult = ds.getFirstResult(); + ds.setFirstResult(ds.getFirstResult() + ds.getMaxResults()); + refreshDatasource(ds); + + if (state == State.LAST && size == 0) { + ds.setFirstResult(firstResult); + int maxResults = ds.getMaxResults(); + ds.setMaxResults(maxResults + 1); + refreshDatasource(ds); + ds.setMaxResults(maxResults); + } + if (owner instanceof DesktopAbstractTable) { + JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); + table.scrollRowToVisible(0); + } + } + + private void onPrevClick() { + if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { + return; + } + + CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; + int newStart = ds.getFirstResult() - ds.getMaxResults(); + ds.setFirstResult(newStart < 0 ? 0 : newStart); + refreshDatasource(ds); + if (owner instanceof DesktopAbstractTable) { + JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); + table.scrollRowToVisible(0); + } + } + + protected void onFirstClick() { + if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { + return; + } + + CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; + ds.setFirstResult(0); + refreshDatasource(ds); + if (owner instanceof DesktopAbstractTable) { + JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); + table.scrollRowToVisible(0); + } + } + + protected void onLastClick() { + if (!(datasource instanceof CollectionDatasource.SupportsPaging)) { + return; + } + + CollectionDatasource.SupportsPaging ds = (CollectionDatasource.SupportsPaging) datasource; + int count = ((CollectionDatasource.SupportsPaging) datasource).getCount(); + int itemsToDisplay = count % ds.getMaxResults(); + if (itemsToDisplay == 0) itemsToDisplay = ds.getMaxResults(); + + ds.setFirstResult(count - itemsToDisplay); + refreshDatasource(ds); + + if (owner instanceof DesktopAbstractTable) { + JXTable table = (JXTable) ((DesktopAbstractTable) owner).getComponent(); + table.scrollRowToVisible(0); + } + } + + + private void refreshDatasource(CollectionDatasource.SupportsPaging ds) { + refreshing = true; + try { + ds.refresh(); + } finally { + refreshing = false; + } + } + + public static class RowsCountComponent extends JPanel { + + private JButton prevButton; + private JButton nextButton; + private JButton firstButton; + private JButton lastButton; + private JLabel label; + private JButton countButton; + private MigLayout layout; + + private final Dimension size = new Dimension(38, 25); + + public RowsCountComponent() { + LC lc = new LC(); + lc.insetsAll("2"); + + layout = new MigLayout(lc); + if (LayoutAdapter.isDebug()) { + lc.debug(1000); + } + setLayout(layout); + + firstButton = new JButton("<<"); + add(firstButton); + firstButton.setPreferredSize(size); + firstButton.setMinimumSize(size); + + prevButton = new JButton("<"); + add(prevButton); + prevButton.setPreferredSize(size); + prevButton.setMinimumSize(size); + + label = new JLabel(); + add(label); + + countButton = new JXHyperlink(); + countButton.setText("[?]"); + add(countButton); + + nextButton = new JButton(">"); + add(nextButton); + nextButton.setPreferredSize(size); + nextButton.setMinimumSize(size); + + lastButton = new JButton(">>"); + add(lastButton); + lastButton.setPreferredSize(size); + lastButton.setMinimumSize(size); + } + + public JLabel getLabel() { + return label; + } + + public JButton getCountButton() { + return countButton; + } + + public JButton getPrevButton() { + return prevButton; + } + + public JButton getNextButton() { + return nextButton; + } + + public JButton getFirstButton() { + return firstButton; + } + + public JButton getLastButton() { + return lastButton; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopScrollBoxLayout.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopScrollBoxLayout.java index 9e39e1fde7..3f8f7e5589 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopScrollBoxLayout.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopScrollBoxLayout.java @@ -1,385 +1,385 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.google.common.collect.Iterables; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.MarginInfo; -import com.haulmont.cuba.gui.components.ScrollBoxLayout; -import org.apache.commons.lang.ObjectUtils; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class DesktopScrollBoxLayout extends DesktopAbstractComponent - implements ScrollBoxLayout, AutoExpanding, DesktopContainer { - - protected List components = new ArrayList<>(); - protected Orientation orientation = Orientation.VERTICAL; - protected ScrollBarPolicy scrollBarPolicy = ScrollBarPolicy.VERTICAL; - protected DesktopAbstractBox content; - - protected boolean scheduledRepaint = false; - - public DesktopScrollBoxLayout() { - impl = new JScrollPane(); - // by default it is turned off - impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - impl.setBorder(null); - - content = new DesktopVBox(); - - DesktopVBox contentPane = new DesktopVBox(); - contentPane.setContainer(this); - contentPane.add(content); - - impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane)); - - applyScrollBarPolicy(scrollBarPolicy); - - // support tables with 100% width like in web - impl.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - adjustViewPreferredSize(); - } - }); - - setWidth("100%"); - } - - private void adjustViewPreferredSize() { - JComponent view = DesktopComponentsHelper.getComposition(content); - Dimension minimumSize = view.getMinimumSize(); - Dimension preferredSize = null; - switch (scrollBarPolicy) { - case VERTICAL: - preferredSize = new Dimension(impl.getViewport().getWidth(), minimumSize.height); - break; - - case HORIZONTAL: - preferredSize = new Dimension(minimumSize.width, impl.getViewport().getHeight()); - break; - - case NONE: - preferredSize = new Dimension(impl.getViewport().getWidth(), impl.getViewport().getHeight()); - break; - - case BOTH: - preferredSize = new Dimension(minimumSize.width, minimumSize.height); - break; - } - view.setPreferredSize(preferredSize); - - requestRepaint(); - } - - protected void requestRepaint() { - if (!scheduledRepaint) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - JComponent view = DesktopComponentsHelper.getComposition(content); - - view.revalidate(); - view.repaint(); - - scheduledRepaint = false; - } - }); - - scheduledRepaint = true; - } - } - - @Override - public void add(Component component) { - add(component, getOwnComponents().size()); - } - - @Override - public void add(Component component, int index) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - DesktopAbstractBox newContent = null; - if (orientation == Orientation.VERTICAL && !(content instanceof DesktopVBox)) { - newContent = new DesktopVBox(); - } else if (orientation == Orientation.HORIZONTAL && !(content instanceof DesktopHBox)) { - newContent = new DesktopHBox(); - } - - if (newContent != null) { - content = newContent; - - DesktopVBox contentPane = new DesktopVBox(); - contentPane.add(content); - contentPane.setContainer(this); - - impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane)); - - applyScrollBarPolicy(scrollBarPolicy); - } - - content.add(component, index); - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - frame.registerComponent(component); - } - } - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - component.setParent(this); - - adjustViewPreferredSize(); - } - - @Override - public int indexOf(Component child) { - return Iterables.indexOf(components, c -> c == child); - } - - @Nullable - @Override - public Component getComponent(int index) { - return Iterables.get(components, index); - } - - @Override - public void remove(Component component) { - components.remove(component); - content.remove(component); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - - adjustViewPreferredSize(); - } - - @Override - public void removeAll() { - content.removeAll(); - - List innerComponents = new ArrayList<>(components); - components.clear(); - - for (Component component : innerComponents) { - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - } - - adjustViewPreferredSize(); - } - - @Override - public void setFrame(com.haulmont.cuba.gui.components.Frame frame) { - super.setFrame(frame); - - if (frame != null) { - for (Component childComponent : content.getOwnComponents()) { - if (childComponent instanceof BelongToFrame - && ((BelongToFrame) childComponent).getFrame() == null) { - ((BelongToFrame) childComponent).setFrame(frame); - } - } - } - } - - @Override - public Component getOwnComponent(String id) { - return content.getOwnComponent(id); - } - - @Nullable - @Override - public Component getComponent(String id) { - return content.getComponent(id); - } - - @Override - public Collection getOwnComponents() { - return content.getOwnComponents(); - } - - @Override - public Collection getComponents() { - return content.getComponents(); - } - - @Override - public boolean expandsWidth() { - return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsWidth(); - } - - @Override - public boolean expandsHeight() { - return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsHeight(); - } - - @Override - public Orientation getOrientation() { - return orientation; - } - - @Override - public void setOrientation(Orientation orientation) { - if (!ObjectUtils.equals(orientation, this.orientation)) { - if (!components.isEmpty()) - throw new IllegalStateException("Unable to change scrollbox orientation after adding components to it"); - - this.orientation = orientation; - } - } - - @Override - public ScrollBarPolicy getScrollBarPolicy() { - return scrollBarPolicy; - } - - @Override - public void setScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) { - if (this.scrollBarPolicy != scrollBarPolicy) { - applyScrollBarPolicy(scrollBarPolicy); - } - this.scrollBarPolicy = scrollBarPolicy; - } - - private void applyScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) { - switch (scrollBarPolicy) { - case BOTH: - impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - - content.setWidth("-1px"); - content.setHeight("-1px"); - break; - - case HORIZONTAL: - impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - - content.setWidth("-1px"); - content.setHeight("100%"); - break; - - case VERTICAL: - impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - - content.setWidth("100%"); - content.setHeight("-1px"); - break; - - case NONE: - impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - - content.setWidth("100%"); - content.setHeight("100%"); - break; - } - } - - @Override - public void setMargin(MarginInfo marginInfo) { - content.setMargin(marginInfo); - } - - @Override - public MarginInfo getMargin() { - return content.getMargin(); - } - - @Override - public void setSpacing(boolean enabled) { - content.setSpacing(enabled); - } - - @Override - public boolean getSpacing() { - return content.getSpacing(); - } - - @Override - public void updateComponent(Component child) { - adjustViewPreferredSize(); - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - for (Component component : components) { - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); - } - } - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - @Override - public void addShortcutAction(ShortcutAction action) { - // do nothing - } - - @Override - public void removeShortcutAction(ShortcutAction action) { - // do nothing - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.google.common.collect.Iterables; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.MarginInfo; +import com.haulmont.cuba.gui.components.ScrollBoxLayout; +import org.apache.commons.lang.ObjectUtils; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class DesktopScrollBoxLayout extends DesktopAbstractComponent + implements ScrollBoxLayout, AutoExpanding, DesktopContainer { + + protected List components = new ArrayList<>(); + protected Orientation orientation = Orientation.VERTICAL; + protected ScrollBarPolicy scrollBarPolicy = ScrollBarPolicy.VERTICAL; + protected DesktopAbstractBox content; + + protected boolean scheduledRepaint = false; + + public DesktopScrollBoxLayout() { + impl = new JScrollPane(); + // by default it is turned off + impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + impl.setBorder(null); + + content = new DesktopVBox(); + + DesktopVBox contentPane = new DesktopVBox(); + contentPane.setContainer(this); + contentPane.add(content); + + impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane)); + + applyScrollBarPolicy(scrollBarPolicy); + + // support tables with 100% width like in web + impl.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + adjustViewPreferredSize(); + } + }); + + setWidth("100%"); + } + + private void adjustViewPreferredSize() { + JComponent view = DesktopComponentsHelper.getComposition(content); + Dimension minimumSize = view.getMinimumSize(); + Dimension preferredSize = null; + switch (scrollBarPolicy) { + case VERTICAL: + preferredSize = new Dimension(impl.getViewport().getWidth(), minimumSize.height); + break; + + case HORIZONTAL: + preferredSize = new Dimension(minimumSize.width, impl.getViewport().getHeight()); + break; + + case NONE: + preferredSize = new Dimension(impl.getViewport().getWidth(), impl.getViewport().getHeight()); + break; + + case BOTH: + preferredSize = new Dimension(minimumSize.width, minimumSize.height); + break; + } + view.setPreferredSize(preferredSize); + + requestRepaint(); + } + + protected void requestRepaint() { + if (!scheduledRepaint) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JComponent view = DesktopComponentsHelper.getComposition(content); + + view.revalidate(); + view.repaint(); + + scheduledRepaint = false; + } + }); + + scheduledRepaint = true; + } + } + + @Override + public void add(Component component) { + add(component, getOwnComponents().size()); + } + + @Override + public void add(Component component, int index) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + DesktopAbstractBox newContent = null; + if (orientation == Orientation.VERTICAL && !(content instanceof DesktopVBox)) { + newContent = new DesktopVBox(); + } else if (orientation == Orientation.HORIZONTAL && !(content instanceof DesktopHBox)) { + newContent = new DesktopHBox(); + } + + if (newContent != null) { + content = newContent; + + DesktopVBox contentPane = new DesktopVBox(); + contentPane.add(content); + contentPane.setContainer(this); + + impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane)); + + applyScrollBarPolicy(scrollBarPolicy); + } + + content.add(component, index); + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + frame.registerComponent(component); + } + } + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + component.setParent(this); + + adjustViewPreferredSize(); + } + + @Override + public int indexOf(Component child) { + return Iterables.indexOf(components, c -> c == child); + } + + @Nullable + @Override + public Component getComponent(int index) { + return Iterables.get(components, index); + } + + @Override + public void remove(Component component) { + components.remove(component); + content.remove(component); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + + adjustViewPreferredSize(); + } + + @Override + public void removeAll() { + content.removeAll(); + + List innerComponents = new ArrayList<>(components); + components.clear(); + + for (Component component : innerComponents) { + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + } + + adjustViewPreferredSize(); + } + + @Override + public void setFrame(com.haulmont.cuba.gui.components.Frame frame) { + super.setFrame(frame); + + if (frame != null) { + for (Component childComponent : content.getOwnComponents()) { + if (childComponent instanceof BelongToFrame + && ((BelongToFrame) childComponent).getFrame() == null) { + ((BelongToFrame) childComponent).setFrame(frame); + } + } + } + } + + @Override + public Component getOwnComponent(String id) { + return content.getOwnComponent(id); + } + + @Nullable + @Override + public Component getComponent(String id) { + return content.getComponent(id); + } + + @Override + public Collection getOwnComponents() { + return content.getOwnComponents(); + } + + @Override + public Collection getComponents() { + return content.getComponents(); + } + + @Override + public boolean expandsWidth() { + return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsWidth(); + } + + @Override + public boolean expandsHeight() { + return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsHeight(); + } + + @Override + public Orientation getOrientation() { + return orientation; + } + + @Override + public void setOrientation(Orientation orientation) { + if (!ObjectUtils.equals(orientation, this.orientation)) { + if (!components.isEmpty()) + throw new IllegalStateException("Unable to change scrollbox orientation after adding components to it"); + + this.orientation = orientation; + } + } + + @Override + public ScrollBarPolicy getScrollBarPolicy() { + return scrollBarPolicy; + } + + @Override + public void setScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) { + if (this.scrollBarPolicy != scrollBarPolicy) { + applyScrollBarPolicy(scrollBarPolicy); + } + this.scrollBarPolicy = scrollBarPolicy; + } + + private void applyScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) { + switch (scrollBarPolicy) { + case BOTH: + impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + content.setWidth("-1px"); + content.setHeight("-1px"); + break; + + case HORIZONTAL: + impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + + content.setWidth("-1px"); + content.setHeight("100%"); + break; + + case VERTICAL: + impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + content.setWidth("100%"); + content.setHeight("-1px"); + break; + + case NONE: + impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + + content.setWidth("100%"); + content.setHeight("100%"); + break; + } + } + + @Override + public void setMargin(MarginInfo marginInfo) { + content.setMargin(marginInfo); + } + + @Override + public MarginInfo getMargin() { + return content.getMargin(); + } + + @Override + public void setSpacing(boolean enabled) { + content.setSpacing(enabled); + } + + @Override + public boolean getSpacing() { + return content.getSpacing(); + } + + @Override + public void updateComponent(Component child) { + adjustViewPreferredSize(); + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + for (Component component : components) { + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); + } + } + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + @Override + public void addShortcutAction(ShortcutAction action) { + // do nothing + } + + @Override + public void removeShortcutAction(ShortcutAction action) { + // do nothing + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSourceCodeEditor.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSourceCodeEditor.java index 424d69e7c0..33c4fefa84 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSourceCodeEditor.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSourceCodeEditor.java @@ -1,227 +1,227 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.components.SourceCodeEditor; -import com.haulmont.cuba.gui.components.autocomplete.AutoCompleteSupport; -import com.haulmont.cuba.gui.components.autocomplete.Suggester; -import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; -import org.fife.ui.rtextarea.RTextScrollPane; - -import javax.swing.*; -import javax.swing.text.Document; -import java.awt.*; -import java.awt.event.KeyEvent; - -public class DesktopSourceCodeEditor extends DesktopAbstractTextField implements SourceCodeEditor { - - protected JComponent composition; - - protected Suggester suggester; - protected Mode mode; - - protected boolean showGutter = true; - protected boolean showPrintMargin = true; - protected boolean highlightActiveLine = true; - protected boolean handleTabKey = false; - protected int printMarginColumn = 80; - - @Override - protected RSyntaxTextArea createTextComponentImpl() { - RSyntaxTextArea impl = new RSyntaxTextArea(); - - int height = (int) impl.getPreferredSize().getHeight(); - impl.setMinimumSize(new Dimension(0, height)); - - RTextScrollPane scrollPane = new RTextScrollPane(impl); - scrollPane.setLineNumbersEnabled(showGutter); - - composition = scrollPane; - composition.setPreferredSize(new Dimension(150, height)); - composition.setMinimumSize(new Dimension(0, height)); - - doc.putProperty("filterNewlines", false); - - return impl; - } - - @Override - public JComponent getComposition() { - return composition; - } - - @Override - protected TextFieldListener createTextListener() { - return new TextFieldListener() { - @Override - public void keyPressed(KeyEvent e) { - updateMissingValueState(); - } - }; - } - - @Override - protected Document createDocument() { - return new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_NONE); - } - - @Override - public Mode getMode() { - return mode; - } - - @Override - public void setMode(Mode mode) { - this.mode = mode; - - switch (mode) { - case Groovy: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_GROOVY); - break; - - case HTML: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_HTML); - break; - - case Java: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - break; - - case JavaScript: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); - break; - - case Properties: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE); - break; - - case SQL: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); - break; - - case XML: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML); - break; - - case CSS: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_CSS); - break; - - case SCSS: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_CSS); - break; - - case Text: - impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); - break; - } - } - - @Override - public Suggester getSuggester() { - return suggester; - } - - @Override - public void setSuggester(Suggester suggester) { - this.suggester = suggester; - } - - @Override - public AutoCompleteSupport getAutoCompleteSupport() { - return new AutoCompleteSupport() { - @Override - public int getCursorPosition() { - return 0; - } - - @Override - public Object getValue() { - return null; - } - }; - } - - @Override - public void setShowGutter(boolean showGutter) { - this.showGutter = showGutter; - ((RTextScrollPane)composition).setLineNumbersEnabled(showGutter); - } - - @Override - public boolean isShowGutter() { - return showGutter; - } - - @Override - public void setShowPrintMargin(boolean showPrintMargin) { - this.showPrintMargin = showPrintMargin; - } - - @Override - public boolean isShowPrintMargin() { - return showPrintMargin; - } - - @Override - public void setPrintMarginColumn(int printMarginColumn) { - this.printMarginColumn = printMarginColumn; - } - - @Override - public int getPrinMarginColumn() { - return printMarginColumn; - } - - @Override - public void setHighlightActiveLine(boolean highlightActiveLine) { - this.highlightActiveLine = highlightActiveLine; - } - - @Override - public boolean isHighlightActiveLine() { - return highlightActiveLine; - } - - @Override - public void setHandleTabKey(boolean handleTabKey) { - this.handleTabKey = handleTabKey; - } - - @Override - public boolean isHandleTabKey() { - return handleTabKey; - } - - @SuppressWarnings("unchecked") - @Override - public String getValue() { - return super.getValue(); - } - - @Override - public String getRawValue() { - return impl.getText(); - } - - @Override - public void resetEditHistory() { - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.components.SourceCodeEditor; +import com.haulmont.cuba.gui.components.autocomplete.AutoCompleteSupport; +import com.haulmont.cuba.gui.components.autocomplete.Suggester; +import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rtextarea.RTextScrollPane; + +import javax.swing.*; +import javax.swing.text.Document; +import java.awt.*; +import java.awt.event.KeyEvent; + +public class DesktopSourceCodeEditor extends DesktopAbstractTextField implements SourceCodeEditor { + + protected JComponent composition; + + protected Suggester suggester; + protected Mode mode; + + protected boolean showGutter = true; + protected boolean showPrintMargin = true; + protected boolean highlightActiveLine = true; + protected boolean handleTabKey = false; + protected int printMarginColumn = 80; + + @Override + protected RSyntaxTextArea createTextComponentImpl() { + RSyntaxTextArea impl = new RSyntaxTextArea(); + + int height = (int) impl.getPreferredSize().getHeight(); + impl.setMinimumSize(new Dimension(0, height)); + + RTextScrollPane scrollPane = new RTextScrollPane(impl); + scrollPane.setLineNumbersEnabled(showGutter); + + composition = scrollPane; + composition.setPreferredSize(new Dimension(150, height)); + composition.setMinimumSize(new Dimension(0, height)); + + doc.putProperty("filterNewlines", false); + + return impl; + } + + @Override + public JComponent getComposition() { + return composition; + } + + @Override + protected TextFieldListener createTextListener() { + return new TextFieldListener() { + @Override + public void keyPressed(KeyEvent e) { + updateMissingValueState(); + } + }; + } + + @Override + protected Document createDocument() { + return new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_NONE); + } + + @Override + public Mode getMode() { + return mode; + } + + @Override + public void setMode(Mode mode) { + this.mode = mode; + + switch (mode) { + case Groovy: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_GROOVY); + break; + + case HTML: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_HTML); + break; + + case Java: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + break; + + case JavaScript: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); + break; + + case Properties: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE); + break; + + case SQL: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); + break; + + case XML: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML); + break; + + case CSS: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_CSS); + break; + + case SCSS: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_CSS); + break; + + case Text: + impl.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); + break; + } + } + + @Override + public Suggester getSuggester() { + return suggester; + } + + @Override + public void setSuggester(Suggester suggester) { + this.suggester = suggester; + } + + @Override + public AutoCompleteSupport getAutoCompleteSupport() { + return new AutoCompleteSupport() { + @Override + public int getCursorPosition() { + return 0; + } + + @Override + public Object getValue() { + return null; + } + }; + } + + @Override + public void setShowGutter(boolean showGutter) { + this.showGutter = showGutter; + ((RTextScrollPane)composition).setLineNumbersEnabled(showGutter); + } + + @Override + public boolean isShowGutter() { + return showGutter; + } + + @Override + public void setShowPrintMargin(boolean showPrintMargin) { + this.showPrintMargin = showPrintMargin; + } + + @Override + public boolean isShowPrintMargin() { + return showPrintMargin; + } + + @Override + public void setPrintMarginColumn(int printMarginColumn) { + this.printMarginColumn = printMarginColumn; + } + + @Override + public int getPrinMarginColumn() { + return printMarginColumn; + } + + @Override + public void setHighlightActiveLine(boolean highlightActiveLine) { + this.highlightActiveLine = highlightActiveLine; + } + + @Override + public boolean isHighlightActiveLine() { + return highlightActiveLine; + } + + @Override + public void setHandleTabKey(boolean handleTabKey) { + this.handleTabKey = handleTabKey; + } + + @Override + public boolean isHandleTabKey() { + return handleTabKey; + } + + @SuppressWarnings("unchecked") + @Override + public String getValue() { + return super.getValue(); + } + + @Override + public String getRawValue() { + return impl.getText(); + } + + @Override + public void resetEditHistory() { + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSplitPanel.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSplitPanel.java index ba0f47dad8..0d9268e79d 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSplitPanel.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopSplitPanel.java @@ -1,379 +1,379 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.SplitPanel; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; -import javax.swing.plaf.synth.SynthSplitPaneUI; -import java.awt.*; -import java.util.*; -import java.util.List; - -public class DesktopSplitPanel extends DesktopAbstractComponent implements SplitPanel { - - protected boolean applyNewPosition = true; - protected int position = 50; - - protected boolean positionChanged = false; - - protected Map componentByIds = new HashMap<>(); - protected Collection ownComponents = new LinkedHashSet<>(); - protected boolean settingsEnabled = true; - protected boolean locked = false; - - public DesktopSplitPanel() { - impl = new JSplitPane() { - @Override - public void paint(Graphics g) { - super.paint(g); - - if (applyNewPosition) { - double ratio = position / 100.0; - - impl.setDividerLocation(ratio); - impl.setResizeWeight(ratio); - applyNewPosition = false; - } - } - }; - - // default orientation as web split - impl.setOrientation(JSplitPane.VERTICAL_SPLIT); - - impl.setUI(new SynthSplitPaneUI() { - @Override - protected void dragDividerTo(int location) { - super.dragDividerTo(location); - - // user touched split divider - positionChanged = true; - } - }); - - impl.setLeftComponent(new JPanel()); - impl.setRightComponent(new JPanel()); - - impl.getLeftComponent().setMinimumSize(new Dimension()); - impl.getRightComponent().setMinimumSize(new Dimension()); - } - - @Override - public int getOrientation() { - return impl.getOrientation() == JSplitPane.HORIZONTAL_SPLIT ? ORIENTATION_HORIZONTAL : ORIENTATION_VERTICAL; - } - - @Override - public void setOrientation(int orientation) { - impl.setOrientation(orientation == ORIENTATION_HORIZONTAL ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT); - } - - @Override - public void setSplitPosition(int pos) { - if (pos < 0 || pos > 100) { - throw new IllegalArgumentException("Split position must be between 0 and 100"); - } - - this.position = pos; - this.applyNewPosition = true; - - impl.revalidate(); - impl.repaint(); - } - - @Override - public void setSplitPosition(int pos, int unit) { - if (unit != UNITS_PERCENTAGE) { - // not supported - return; - } - - setSplitPosition(pos); - } - - @Override - public void setSplitPosition(int pos, int unit, boolean reversePosition) { - if (unit != UNITS_PERCENTAGE) { - // not supported - return; - } - - setSplitPosition(pos); - } - - @Override - public float getSplitPosition() { - return impl.getUI().getDividerLocation(impl); - } - - @Override - public int getSplitPositionUnit() { - return UNITS_PERCENTAGE; - } - - @Override - public void setMaxSplitPosition(int pos, int unit) { - if (unit != UNITS_PERCENTAGE) { - // not supported - return; - } - - setMaxSplitPosition(pos, UNITS_PIXELS); - } - - @Override - public void setMinSplitPosition(int pos, int unit) { - if (unit != UNITS_PERCENTAGE) { - // not supported - return; - } - - setMaxSplitPosition(pos, UNITS_PIXELS); - } - - @Override - public boolean isSplitPositionReversed() { - return false; - } - - @Override - public void setLocked(boolean locked) { - this.locked = locked; - - BasicSplitPaneDivider divider = ((BasicSplitPaneUI) impl.getUI()).getDivider(); - if (locked) { - divider.setDividerSize(0); - } else { - divider.setDividerSize(10); - } - - impl.revalidate(); - impl.repaint(); - } - - @Override - public boolean isLocked() { - return locked; - } - - @Override - public void setPositionUpdateListener(PositionUpdateListener positionListener) { - // not supported - } - - @Override - public PositionUpdateListener getPositionUpdateListener() { - // not supported - return null; - } - - @Override - public void addSplitPositionChangeListener(SplitPositionChangeListener listener) { - // not supported - } - - @Override - public void removeSplitPositionChangeListener(SplitPositionChangeListener listener) { - // not supported - } - - @Override - public void add(Component component) { - JComponent jComponent = DesktopComponentsHelper.getComposition(component); - jComponent.setMinimumSize(new Dimension()); - if (ownComponents.isEmpty()) { - impl.setLeftComponent(jComponent); - } else { - impl.setRightComponent(jComponent); - } - - if (component.getId() != null) { - componentByIds.put(component.getId(), component); - } - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - frame.registerComponent(component); - } - } - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - ownComponents.add(component); - } - - @Override - public void remove(Component component) { - JComponent jComponent = DesktopComponentsHelper.getComposition(component); - impl.remove(jComponent); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - if (component.getId() != null) { - componentByIds.remove(component.getId()); - } - ownComponents.remove(component); - } - - @Override - public void removeAll() { - impl.removeAll(); - componentByIds.clear(); - - List components = new ArrayList<>(ownComponents); - ownComponents.clear(); - - for (Component component : components) { - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - } - } - - @Override - public void setFrame(com.haulmont.cuba.gui.components.Frame frame) { - super.setFrame(frame); - - if (frame != null) { - for (Component childComponent : ownComponents) { - if (childComponent instanceof BelongToFrame - && ((BelongToFrame) childComponent).getFrame() == null) { - ((BelongToFrame) childComponent).setFrame(frame); - } - } - } - } - - @Override - public Component getOwnComponent(String id) { - return componentByIds.get(id); - } - - @Nullable - @Override - public Component getComponent(String id) { - return ComponentsHelper.getComponent(this, id); - } - - @Override - public Collection getOwnComponents() { - return Collections.unmodifiableCollection(ownComponents); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public void applySettings(Element element) { - if (!isSettingsEnabled()) { - return; - } - - Element e = element.element("position"); - if (e != null) { - String value = e.attributeValue("value"); - if (!StringUtils.isBlank(value)) { - // ignore defaults - this.applyNewPosition = false; - this.positionChanged = true; - - impl.setDividerLocation(Integer.parseInt(value)); - impl.setResizeWeight(position / 100.0); - } - } - } - - @Override - public boolean saveSettings(Element element) { - if (!isSettingsEnabled()) { - return false; - } - - if (!positionChanged) { - return false; // most probably user didn't change the divider location - } - - int location = impl.getUI().getDividerLocation(impl); - Element e = element.element("position"); - if (e == null) { - e = element.addElement("position"); - } - e.addAttribute("value", String.valueOf(location)); - return true; - } - - @Override - public boolean isSettingsEnabled() { - return settingsEnabled; - } - - @Override - public void setSettingsEnabled(boolean settingsEnabled) { - this.settingsEnabled = settingsEnabled; - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - boolean resultEnabled = isEnabledWithParent(); - for (Component component : ownComponents) { - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); - } - } - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.SplitPanel; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import javax.swing.plaf.synth.SynthSplitPaneUI; +import java.awt.*; +import java.util.*; +import java.util.List; + +public class DesktopSplitPanel extends DesktopAbstractComponent implements SplitPanel { + + protected boolean applyNewPosition = true; + protected int position = 50; + + protected boolean positionChanged = false; + + protected Map componentByIds = new HashMap<>(); + protected Collection ownComponents = new LinkedHashSet<>(); + protected boolean settingsEnabled = true; + protected boolean locked = false; + + public DesktopSplitPanel() { + impl = new JSplitPane() { + @Override + public void paint(Graphics g) { + super.paint(g); + + if (applyNewPosition) { + double ratio = position / 100.0; + + impl.setDividerLocation(ratio); + impl.setResizeWeight(ratio); + applyNewPosition = false; + } + } + }; + + // default orientation as web split + impl.setOrientation(JSplitPane.VERTICAL_SPLIT); + + impl.setUI(new SynthSplitPaneUI() { + @Override + protected void dragDividerTo(int location) { + super.dragDividerTo(location); + + // user touched split divider + positionChanged = true; + } + }); + + impl.setLeftComponent(new JPanel()); + impl.setRightComponent(new JPanel()); + + impl.getLeftComponent().setMinimumSize(new Dimension()); + impl.getRightComponent().setMinimumSize(new Dimension()); + } + + @Override + public int getOrientation() { + return impl.getOrientation() == JSplitPane.HORIZONTAL_SPLIT ? ORIENTATION_HORIZONTAL : ORIENTATION_VERTICAL; + } + + @Override + public void setOrientation(int orientation) { + impl.setOrientation(orientation == ORIENTATION_HORIZONTAL ? JSplitPane.HORIZONTAL_SPLIT : JSplitPane.VERTICAL_SPLIT); + } + + @Override + public void setSplitPosition(int pos) { + if (pos < 0 || pos > 100) { + throw new IllegalArgumentException("Split position must be between 0 and 100"); + } + + this.position = pos; + this.applyNewPosition = true; + + impl.revalidate(); + impl.repaint(); + } + + @Override + public void setSplitPosition(int pos, int unit) { + if (unit != UNITS_PERCENTAGE) { + // not supported + return; + } + + setSplitPosition(pos); + } + + @Override + public void setSplitPosition(int pos, int unit, boolean reversePosition) { + if (unit != UNITS_PERCENTAGE) { + // not supported + return; + } + + setSplitPosition(pos); + } + + @Override + public float getSplitPosition() { + return impl.getUI().getDividerLocation(impl); + } + + @Override + public int getSplitPositionUnit() { + return UNITS_PERCENTAGE; + } + + @Override + public void setMaxSplitPosition(int pos, int unit) { + if (unit != UNITS_PERCENTAGE) { + // not supported + return; + } + + setMaxSplitPosition(pos, UNITS_PIXELS); + } + + @Override + public void setMinSplitPosition(int pos, int unit) { + if (unit != UNITS_PERCENTAGE) { + // not supported + return; + } + + setMaxSplitPosition(pos, UNITS_PIXELS); + } + + @Override + public boolean isSplitPositionReversed() { + return false; + } + + @Override + public void setLocked(boolean locked) { + this.locked = locked; + + BasicSplitPaneDivider divider = ((BasicSplitPaneUI) impl.getUI()).getDivider(); + if (locked) { + divider.setDividerSize(0); + } else { + divider.setDividerSize(10); + } + + impl.revalidate(); + impl.repaint(); + } + + @Override + public boolean isLocked() { + return locked; + } + + @Override + public void setPositionUpdateListener(PositionUpdateListener positionListener) { + // not supported + } + + @Override + public PositionUpdateListener getPositionUpdateListener() { + // not supported + return null; + } + + @Override + public void addSplitPositionChangeListener(SplitPositionChangeListener listener) { + // not supported + } + + @Override + public void removeSplitPositionChangeListener(SplitPositionChangeListener listener) { + // not supported + } + + @Override + public void add(Component component) { + JComponent jComponent = DesktopComponentsHelper.getComposition(component); + jComponent.setMinimumSize(new Dimension()); + if (ownComponents.isEmpty()) { + impl.setLeftComponent(jComponent); + } else { + impl.setRightComponent(jComponent); + } + + if (component.getId() != null) { + componentByIds.put(component.getId(), component); + } + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + frame.registerComponent(component); + } + } + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + ownComponents.add(component); + } + + @Override + public void remove(Component component) { + JComponent jComponent = DesktopComponentsHelper.getComposition(component); + impl.remove(jComponent); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + if (component.getId() != null) { + componentByIds.remove(component.getId()); + } + ownComponents.remove(component); + } + + @Override + public void removeAll() { + impl.removeAll(); + componentByIds.clear(); + + List components = new ArrayList<>(ownComponents); + ownComponents.clear(); + + for (Component component : components) { + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + } + } + + @Override + public void setFrame(com.haulmont.cuba.gui.components.Frame frame) { + super.setFrame(frame); + + if (frame != null) { + for (Component childComponent : ownComponents) { + if (childComponent instanceof BelongToFrame + && ((BelongToFrame) childComponent).getFrame() == null) { + ((BelongToFrame) childComponent).setFrame(frame); + } + } + } + } + + @Override + public Component getOwnComponent(String id) { + return componentByIds.get(id); + } + + @Nullable + @Override + public Component getComponent(String id) { + return ComponentsHelper.getComponent(this, id); + } + + @Override + public Collection getOwnComponents() { + return Collections.unmodifiableCollection(ownComponents); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public void applySettings(Element element) { + if (!isSettingsEnabled()) { + return; + } + + Element e = element.element("position"); + if (e != null) { + String value = e.attributeValue("value"); + if (!StringUtils.isBlank(value)) { + // ignore defaults + this.applyNewPosition = false; + this.positionChanged = true; + + impl.setDividerLocation(Integer.parseInt(value)); + impl.setResizeWeight(position / 100.0); + } + } + } + + @Override + public boolean saveSettings(Element element) { + if (!isSettingsEnabled()) { + return false; + } + + if (!positionChanged) { + return false; // most probably user didn't change the divider location + } + + int location = impl.getUI().getDividerLocation(impl); + Element e = element.element("position"); + if (e == null) { + e = element.addElement("position"); + } + e.addAttribute("value", String.valueOf(location)); + return true; + } + + @Override + public boolean isSettingsEnabled() { + return settingsEnabled; + } + + @Override + public void setSettingsEnabled(boolean settingsEnabled) { + this.settingsEnabled = settingsEnabled; + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + boolean resultEnabled = isEnabledWithParent(); + for (Component component : ownComponents) { + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled); + } + } + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTabSheet.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTabSheet.java index 28c36fa7ae..82536cd177 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTabSheet.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTabSheet.java @@ -1,896 +1,896 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DetachedFrame; -import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; -import com.haulmont.cuba.desktop.sys.ButtonTabComponent; -import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.TabSheet; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.data.impl.DsContextImplementation; -import com.haulmont.cuba.gui.data.impl.compatibility.CompatibleTabSheetSelectedTabChangeListener; -import com.haulmont.cuba.gui.settings.Settings; -import com.haulmont.cuba.gui.xml.layout.ComponentLoader; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.*; - -public class DesktopTabSheet extends DesktopAbstractComponent - implements TabSheet, DesktopContainer, AutoExpanding, Component.UiPermissionAware { - - private final Logger log = LoggerFactory.getLogger(DesktopTabSheet.class); - - protected Map components = new HashMap<>(); - - protected List tabs = new ArrayList<>(); - - protected Map tabContents = new LinkedHashMap<>(); - - protected Set lazyTabs = new HashSet<>(); - - protected ComponentLoader.Context context; - - protected boolean initLazyTabListenerAdded; - protected boolean postInitTaskAdded; - protected boolean componentTabChangeListenerInitialized; - - protected List listeners = new ArrayList<>(); - - // CAUTION do not add ChangeListeners directly to impl - protected List implTabSheetChangeListeners = new ArrayList<>(); - - private boolean tabCaptionsAsHtml = false; // just stub - private boolean tabsVisible = true; // just stub - - public DesktopTabSheet() { - impl = new JTabbedPaneExt(); - impl.addChangeListener(e -> { - for (ChangeListener listener : new ArrayList<>(implTabSheetChangeListeners)) { - listener.stateChanged(e); - } - }); - - setWidth("100%"); - } - - @Override - public void add(Component component) { - throw new UnsupportedOperationException(); - } - - @Override - public void remove(Component component) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeAll() { - throw new UnsupportedOperationException(); - } - - @Override - public Component getOwnComponent(String id) { - for (Component tabComponent : components.keySet()) { - if (StringUtils.equals(id, tabComponent.getId())) { - return tabComponent; - } - } - - return null; - } - - @Override - public Component getComponent(String id) { - return ComponentsHelper.getComponent(this, id); - } - - @Override - public Collection getOwnComponents() { - return components.keySet(); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public Tab addTab(String name, Component component) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - TabImpl tab = new TabImpl(name, component, false); - - tabs.add(tab); - components.put(component, name); - - DesktopContainerHelper.assignContainer(component, this); - - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - JComponent comp = DesktopComponentsHelper.getComposition(component); - - impl.addTab("", comp); - int tabIndex = impl.indexOfComponent(comp); - tabContents.put(comp, tab); - setTabComponent(tab, tabIndex); - - if (frame != null) { - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(frame); - } else { - frame.registerComponent(component); - } - } - - adjustTabSize(component); - - component.setParent(this); - - return tab; - } - - @Override - public void setFrame(Frame frame) { - super.setFrame(frame); - - if (frame != null) { - for (Component childComponent : components.keySet()) { - if (childComponent instanceof BelongToFrame - && ((BelongToFrame) childComponent).getFrame() == null) { - ((BelongToFrame) childComponent).setFrame(frame); - } - } - } - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - - for (Component tab : components.keySet()) { - adjustTabSize(tab); - } - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - - for (Component tab : components.keySet()) { - adjustTabSize(tab); - } - } - - protected void setTabComponent(TabImpl tab, int componentIndex) { - ButtonTabComponent.CloseListener closeListener = new ButtonTabComponent.CloseListener(){ - @Override - public void onTabClose(int tabIndex) { - if (tab.getCloseHandler() != null) { - tab.getCloseHandler().onTabClose(tab); - } else { - removeTab(tab.getName()); - } - } - }; - - ButtonTabComponent.DetachListener detachListener = new ButtonTabComponent.DetachListener() { - @Override - public void onDetach(int tabIndex) { - detachTab(tabIndex); - } - }; - - ButtonTabComponent btnTabComponent = new ButtonTabComponent(impl, false, false, closeListener, detachListener); - tab.setButtonTabComponent(btnTabComponent); - impl.setTabComponentAt(componentIndex, btnTabComponent); - } - - @Override - public Tab addLazyTab(String name, Element descriptor, ComponentLoader loader) { - DesktopVBox tabContent = new DesktopVBox(); - adjustTabSize(tabContent); - - TabImpl tab = new TabImpl(name, tabContent, true); - tabs.add(tab); - components.put(tabContent, name); - - DesktopContainerHelper.assignContainer(tabContent, this); - - if (!isEnabledWithParent()) { - tabContent.setParentEnabled(false); - } - - final JComponent comp = DesktopComponentsHelper.getComposition(tabContent); - - impl.addTab("", comp); - int tabIndex = impl.indexOfComponent(comp); - tabContents.put(comp, tab); - - setTabComponent(tab, tabIndex); - lazyTabs.add(new LazyTabInfo(tab, tabContent, descriptor, loader)); - - if (!initLazyTabListenerAdded) { - implTabSheetChangeListeners.add(new LazyTabChangeListener()); - initLazyTabListenerAdded = true; - } - - context = loader.getContext(); - - if (!postInitTaskAdded) { - context.addPostInitTask((context1, window) -> - initComponentTabChangeListener() - ); - postInitTaskAdded = true; - } - return tab; - } - - protected void adjustTabSize(Component tabComponent) { - if (getWidth() >= 0) { - tabComponent.setWidth("100%"); - } else { - tabComponent.setWidth(Component.AUTO_SIZE); - } - - if (getHeight() >= 0) { - tabComponent.setHeight("100%"); - } else { - tabComponent.setHeight(Component.AUTO_SIZE); - } - } - - @Override - public void removeTab(String name) { - TabImpl tab = getTabImpl(name); - Component component = tab.getComponent(); - components.remove(component); - impl.remove(DesktopComponentsHelper.getComposition(component)); - - DesktopContainerHelper.assignContainer(component, null); - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - } - - @Override - public void removeAllTabs() { - impl.removeAll(); - - List innerComponents = new ArrayList<>(components.keySet()); - components.clear(); - - for (Component component : innerComponents) { - DesktopContainerHelper.assignContainer(component, null); - if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - component.setParent(null); - } - } - - protected TabImpl getTabImpl(String name) { - TabImpl tab = null; - for (TabImpl t : tabs) { - if (t.getName().equals(name)) { - tab = t; - break; - } - } - if (tab == null) - throw new IllegalStateException(String.format("Can't find tab '%s'", name)); - return tab; - } - - @Override - public Tab getSelectedTab() { - JComponent component = (JComponent) impl.getSelectedComponent(); - if (component == null) { - return null; // nothing selected - } - for (TabImpl tabImpl : tabs) { - if (DesktopComponentsHelper.getComposition(tabImpl.getComponent()).equals(component)) - return tabImpl; - } - return tabs.get(0); - } - - @Override - public void setSelectedTab(Tab tab) { - Component component = ((TabImpl) tab).getComponent(); - impl.setSelectedComponent(DesktopComponentsHelper.getComposition(component)); - } - - @Override - public void setSelectedTab(String name) { - TabImpl tab = getTabImpl(name); - impl.setSelectedComponent(DesktopComponentsHelper.getComposition(tab.getComponent())); - } - - @Override - public Tab getTab(String name) { - return getTabImpl(name); - } - - @Override - public Component getTabComponent(String name) { - TabImpl tab = getTabImpl(name); - return tab.getComponent(); - } - - @Override - public Collection getTabs() { - return Collections.unmodifiableCollection(tabs); - } - - @Override - public boolean isTabCaptionsAsHtml() { - return tabCaptionsAsHtml; - } - - @Override - public void setTabCaptionsAsHtml(boolean tabCaptionsAsHtml) { - this.tabCaptionsAsHtml = tabCaptionsAsHtml; - } - - @Override - public boolean isTabsVisible() { - return tabsVisible; - } - - @Override - public void setTabsVisible(boolean tabsVisible) { - this.tabsVisible = tabsVisible; - } - - @Override - public void addListener(TabChangeListener listener) { - initComponentTabChangeListener(); - - CompatibleTabSheetSelectedTabChangeListener adapter = new CompatibleTabSheetSelectedTabChangeListener(listener); - - if (!listeners.contains(adapter)) { - listeners.add(adapter); - } - } - - protected void initComponentTabChangeListener() { - // init component SelectedTabChangeListener only when needed, making sure it is - // after all lazy tabs listeners - if (!componentTabChangeListenerInitialized) { - implTabSheetChangeListeners.add(new ComponentTabChangeListener()); - componentTabChangeListenerInitialized = true; - } - } - - @Override - public void applyPermission(UiPermissionDescriptor permissionDescriptor) { - Preconditions.checkNotNullArgument(permissionDescriptor); - - final String subComponentId = permissionDescriptor.getSubComponentId(); - final TabSheet.Tab tab = getTab(subComponentId); - if (tab != null) { - UiPermissionValue permissionValue = permissionDescriptor.getPermissionValue(); - if (permissionValue == UiPermissionValue.HIDE) { - tab.setVisible(false); - } else if (permissionValue == UiPermissionValue.READ_ONLY) { - tab.setEnabled(false); - } - } else { - LoggerFactory.getLogger(DesktopTabSheet.class).info(String.format("Couldn't find component %s in window %s", - subComponentId, permissionDescriptor.getScreenId())); - } - } - - protected class ComponentTabChangeListener implements ChangeListener { - @Override - public void stateChanged(ChangeEvent e) { - if (context != null) { - context.executeInjectTasks(); - context.executePostWrapTasks(); - context.executeInitTasks(); - } - - // Fire GUI listener - fireTabChanged(); - - // Execute outstanding post init tasks after GUI listener. - // We suppose that context.executePostInitTasks() executes a task once and then remove it from task list. - if (context != null) { - context.executePostInitTasks(); - } - - Window window = ComponentsHelper.getWindow(DesktopTabSheet.this); - if (window != null) { - ((DsContextImplementation) window.getDsContext()).resumeSuspended(); - } else { - log.warn("Please specify Frame for TabSheet"); - } - } - } - - protected class LazyTabChangeListener implements ChangeListener { - @Override - public void stateChanged(ChangeEvent e) { - initLazyTab((JComponent) impl.getSelectedComponent()); - } - } - - protected void initLazyTab(JComponent tab) { - LazyTabInfo lti = null; - for (LazyTabInfo lazyTabInfo : lazyTabs) { - if (lazyTabInfo.getTabComponent() == tab) { - lti = lazyTabInfo; - break; - } - } - - if (lti == null) { // already initialized - return; - } - - if (!lti.getTab().isEnabled()) { - return; - } - - lazyTabs.remove(lti); - - lti.loader.createComponent(); - - Component lazyContent = lti.loader.getResultComponent(); - - lazyContent.setWidth("100%"); - lti.tabContent.add(lazyContent); - lti.tabContent.expand(lazyContent, "", ""); - lazyContent.setParent(this); - - lti.loader.loadComponent(); - - if (lazyContent instanceof DesktopAbstractComponent && !isEnabledWithParent()) { - ((DesktopAbstractComponent) lazyContent).setParentEnabled(false); - } - - final Window window = ComponentsHelper.getWindow(DesktopTabSheet.this); - if (window != null) { - ComponentsHelper.walkComponents( - lti.tabContent, - (component, name) -> { - if (component instanceof HasSettings) { - Settings settings = window.getSettings(); - if (settings != null) { - Element e = settings.get(name); - ((HasSettings) component).applySettings(e); - } - } - } - ); - - lti.getTab().setLazyInitialized(true); - } - } - - @Override - public void removeListener(TabChangeListener listener) { - listeners.remove(new CompatibleTabSheetSelectedTabChangeListener(listener)); - } - - protected void fireTabChanged() { - for (SelectedTabChangeListener listener : listeners) { - listener.selectedTabChanged(new SelectedTabChangeEvent(this, getTab())); - } - } - - @Override - public void addSelectedTabChangeListener(SelectedTabChangeListener listener) { - initComponentTabChangeListener(); - - if (!listeners.contains(listener)) { - listeners.add(listener); - } - } - - @Override - public void removeSelectedTabChangeListener(SelectedTabChangeListener listener) { - listeners.remove(listener); - } - - protected void updateTabVisibility(TabImpl tab) { - // find insert/remove index by visibility of existing tabs - int currentIndex = tab.getTabIndex(); - int idx = 0; - for (TabImpl t : tabs) { - if (t.equals(tab)) - break; - if (t.isVisible()) - idx++; - } - - JComponent comp = DesktopComponentsHelper.getComposition(tab.getComponent()); - if (currentIndex >= 0 || tab.isVisible()) { - if (tab.isVisible()) { - impl.insertTab(tab.getCaption(), null, comp, null, idx); - impl.setTabComponentAt(idx, tab.getButtonTabComponent()); - } else { - impl.removeTabAt(idx); - } - } else { //tab is detached - DetachedFrame detachedFrame = (DetachedFrame) SwingUtilities.getWindowAncestor(comp); - detachedFrame.dispose(); - } - // if we just detach component, it will return isVisible() == true - if (!tab.isVisible()) - comp.setVisible(false); - } - - @Override - public boolean expandsWidth() { - return true; - } - - @Override - public boolean expandsHeight() { - return false; - } - - @Override - public void updateComponent(Component child) { - // do nothing - requestContainerUpdate(); - } - - protected class TabImpl implements TabSheet.Tab { - - private String name; - private Component component; - private String caption; - private boolean enabled = true; - private boolean visible = true; - private boolean closable; - private boolean detachable; - private boolean lazy; - private boolean lazyInitialized; - private ButtonTabComponent buttonTabComponent; - - private String styleName; - - private TabCloseHandler closeHandler; - - public TabImpl(String name, Component component, boolean lazy) { - this.name = name; - this.component = component; - this.lazy = lazy; - } - - @Override - public String getName() { - return name; - } - - @Override - public void setName(String name) { - this.name = name; - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - DesktopTabSheet.this.impl.setTitleAt(getTabIndex(), caption); - getButtonTabComponent().setCaption(caption); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void setEnabled(boolean enabled) { - this.enabled = enabled; - buttonTabComponent.setEnabled(enabled); - int tabIndex = getTabIndex(); - - if (tabIndex >= 0) { - impl.setEnabledAt(getTabIndex(), enabled); - impl.setComponentAt(tabIndex, enabled ? DesktopComponentsHelper.getComposition(component) : null); - if (impl.getSelectedIndex() == tabIndex && isLazy() && enabled) { - initLazyTab(DesktopComponentsHelper.getComposition(component)); - } - } - - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(enabled); - } - } - - @Override - public boolean isVisible() { - return visible; - } - - @Override - public void setVisible(boolean visible) { - if (visible != this.visible) { - this.visible = visible; - DesktopTabSheet.this.updateTabVisibility(this); - } - } - - @Override - public boolean isClosable() { - return closable; - } - - @Override - public void setClosable(boolean closable) { - if (closable != this.closable) { - getButtonTabComponent().setCloseable(closable); - this.closable = closable; - } - } - - @Override - public boolean isDetachable() { - return detachable; - } - - @Override - public void setDetachable(boolean detachable) { - if (detachable != this.detachable) { - getButtonTabComponent().setDetachable(detachable); - this.detachable = detachable; - } - } - - @Override - public TabCloseHandler getCloseHandler() { - return closeHandler; - } - - @Override - public void setCloseHandler(TabCloseHandler tabCloseHandler) { - this.closeHandler = tabCloseHandler; - } - - public Component getComponent() { - return component; - } - - public int getTabIndex() { - return DesktopTabSheet.this.impl.indexOfTabComponent(buttonTabComponent); - } - - @Override - public String toString() { - return name; - } - - @Override - public void setStyleName(String styleName) { - this.styleName = styleName; - - ButtonTabComponent buttonTabComponent = getButtonTabComponent(); - App.getInstance().getTheme().applyStyle(buttonTabComponent.getTitleLabel(), styleName); - } - - @Override - public String getStyleName() { - return styleName; - } - - public ButtonTabComponent getButtonTabComponent() { - return buttonTabComponent; - } - - public void setButtonTabComponent(ButtonTabComponent buttonTabComponent) { - this.buttonTabComponent = buttonTabComponent; - } - - public boolean isLazyInitialized(){ - return lazyInitialized; - } - - public void setLazyInitialized(boolean lazyInitialized){ - this.lazyInitialized = lazyInitialized; - } - - public boolean isLazy(){ - return lazy; - } - - @Override - public String getIcon() { - return null; - } - - @Override - public void setIcon(String icon) { - // do nothing - } - } - - protected static class LazyTabInfo { - protected DesktopAbstractBox tabContent; - protected Element descriptor; - protected ComponentLoader loader; - protected TabImpl tabImpl; - - public LazyTabInfo(TabImpl tabImpl, DesktopAbstractBox tabContent, Element descriptor, - ComponentLoader loader) { - this.descriptor = descriptor; - this.loader = loader; - this.tabContent = tabContent; - this.tabImpl = tabImpl; - } - - protected JComponent getTabComponent() { - return DesktopComponentsHelper.getComposition(tabContent); - } - - protected TabImpl getTab(){ - return tabImpl; - } - } - - protected void detachTab(final int tabIndex) { - final JComponent tabContent = (JComponent) impl.getComponentAt(tabIndex); - TabImpl tabAtIndex = null; - for (TabImpl tab : tabs) { - if (DesktopComponentsHelper.getComposition(tab.getComponent()) == tabContent) { - tabAtIndex = tab; - if (tab.isLazy() && !tab.isLazyInitialized()) { - initLazyTab(tabContent); - } - break; - } - } - if (tabAtIndex == null) { - throw new IllegalStateException("Unable to find tab to detach"); - } - final TabImpl tabToDetach = tabAtIndex; - final ButtonTabComponent tabComponent = tabToDetach.getButtonTabComponent(); - final JFrame frame = new DetachedFrame(tabComponent.getCaption(), impl); - - frame.setLocationRelativeTo(DesktopComponentsHelper.getTopLevelFrame(this)); - impl.remove(tabContent); - updateTabsEnabledState(); - frame.setSize(impl.getSize()); - frame.add(tabContent); - - final HierarchyListener listener = new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) == HierarchyEvent.DISPLAYABILITY_CHANGED - && !impl.isDisplayable()) { - attachTab(frame, tabToDetach); - impl.removeHierarchyListener(this); - } - } - }; - - frame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - attachTab(frame, tabToDetach); - impl.removeHierarchyListener(listener); - } - }); - - impl.addHierarchyListener(listener); - frame.setVisible(true); - } - - protected void attachTab(JFrame frame, TabImpl tab) { - int tabIndex = 0; - int attachedBeforeCount = 0; - JComponent tabContent = DesktopComponentsHelper.getComposition(tab.getComponent()); - String caption = tab.getCaption(); - ButtonTabComponent tabComponent = tab.getButtonTabComponent(); - for (Map.Entry entry : tabContents.entrySet()) { - if (entry.getKey() == tabContent) { - tabIndex = attachedBeforeCount; - break; - } else if (entry.getKey().getParent() == impl) { - attachedBeforeCount++; - } - } - - impl.add(tabContent, tabIndex); - if (!tab.isEnabled()) { - impl.setComponentAt(tabIndex, null); - } - impl.setTitleAt(tabIndex, caption); - impl.setTabComponentAt(tabIndex, tabComponent); - updateTabsEnabledState(); - tabComponent.revalidate(); - tabComponent.repaint(); - frame.dispose(); - } - - protected void updateTabsEnabledState() { - for (TabImpl tab : tabs) { - int tabIndex = tab.getTabIndex(); - if (tabIndex >= 0) { - impl.setEnabledAt(tab.getTabIndex(), tab.isEnabled()); - } - } - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - for (Component component : components.keySet()) { - if (component instanceof DesktopAbstractComponent) { - JComponent composition = DesktopComponentsHelper.getComposition(component); - TabImpl tab = tabContents.get(composition); - - ((DesktopAbstractComponent) component).setParentEnabled(tab.isEnabled() && isEnabledWithParent()); - } - } - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DetachedFrame; +import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; +import com.haulmont.cuba.desktop.sys.ButtonTabComponent; +import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.TabSheet; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.data.impl.DsContextImplementation; +import com.haulmont.cuba.gui.data.impl.compatibility.CompatibleTabSheetSelectedTabChangeListener; +import com.haulmont.cuba.gui.settings.Settings; +import com.haulmont.cuba.gui.xml.layout.ComponentLoader; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.*; + +public class DesktopTabSheet extends DesktopAbstractComponent + implements TabSheet, DesktopContainer, AutoExpanding, Component.UiPermissionAware { + + private final Logger log = LoggerFactory.getLogger(DesktopTabSheet.class); + + protected Map components = new HashMap<>(); + + protected List tabs = new ArrayList<>(); + + protected Map tabContents = new LinkedHashMap<>(); + + protected Set lazyTabs = new HashSet<>(); + + protected ComponentLoader.Context context; + + protected boolean initLazyTabListenerAdded; + protected boolean postInitTaskAdded; + protected boolean componentTabChangeListenerInitialized; + + protected List listeners = new ArrayList<>(); + + // CAUTION do not add ChangeListeners directly to impl + protected List implTabSheetChangeListeners = new ArrayList<>(); + + private boolean tabCaptionsAsHtml = false; // just stub + private boolean tabsVisible = true; // just stub + + public DesktopTabSheet() { + impl = new JTabbedPaneExt(); + impl.addChangeListener(e -> { + for (ChangeListener listener : new ArrayList<>(implTabSheetChangeListeners)) { + listener.stateChanged(e); + } + }); + + setWidth("100%"); + } + + @Override + public void add(Component component) { + throw new UnsupportedOperationException(); + } + + @Override + public void remove(Component component) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeAll() { + throw new UnsupportedOperationException(); + } + + @Override + public Component getOwnComponent(String id) { + for (Component tabComponent : components.keySet()) { + if (StringUtils.equals(id, tabComponent.getId())) { + return tabComponent; + } + } + + return null; + } + + @Override + public Component getComponent(String id) { + return ComponentsHelper.getComponent(this, id); + } + + @Override + public Collection getOwnComponents() { + return components.keySet(); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public Tab addTab(String name, Component component) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + TabImpl tab = new TabImpl(name, component, false); + + tabs.add(tab); + components.put(component, name); + + DesktopContainerHelper.assignContainer(component, this); + + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + JComponent comp = DesktopComponentsHelper.getComposition(component); + + impl.addTab("", comp); + int tabIndex = impl.indexOfComponent(comp); + tabContents.put(comp, tab); + setTabComponent(tab, tabIndex); + + if (frame != null) { + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(frame); + } else { + frame.registerComponent(component); + } + } + + adjustTabSize(component); + + component.setParent(this); + + return tab; + } + + @Override + public void setFrame(Frame frame) { + super.setFrame(frame); + + if (frame != null) { + for (Component childComponent : components.keySet()) { + if (childComponent instanceof BelongToFrame + && ((BelongToFrame) childComponent).getFrame() == null) { + ((BelongToFrame) childComponent).setFrame(frame); + } + } + } + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + + for (Component tab : components.keySet()) { + adjustTabSize(tab); + } + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + + for (Component tab : components.keySet()) { + adjustTabSize(tab); + } + } + + protected void setTabComponent(TabImpl tab, int componentIndex) { + ButtonTabComponent.CloseListener closeListener = new ButtonTabComponent.CloseListener(){ + @Override + public void onTabClose(int tabIndex) { + if (tab.getCloseHandler() != null) { + tab.getCloseHandler().onTabClose(tab); + } else { + removeTab(tab.getName()); + } + } + }; + + ButtonTabComponent.DetachListener detachListener = new ButtonTabComponent.DetachListener() { + @Override + public void onDetach(int tabIndex) { + detachTab(tabIndex); + } + }; + + ButtonTabComponent btnTabComponent = new ButtonTabComponent(impl, false, false, closeListener, detachListener); + tab.setButtonTabComponent(btnTabComponent); + impl.setTabComponentAt(componentIndex, btnTabComponent); + } + + @Override + public Tab addLazyTab(String name, Element descriptor, ComponentLoader loader) { + DesktopVBox tabContent = new DesktopVBox(); + adjustTabSize(tabContent); + + TabImpl tab = new TabImpl(name, tabContent, true); + tabs.add(tab); + components.put(tabContent, name); + + DesktopContainerHelper.assignContainer(tabContent, this); + + if (!isEnabledWithParent()) { + tabContent.setParentEnabled(false); + } + + final JComponent comp = DesktopComponentsHelper.getComposition(tabContent); + + impl.addTab("", comp); + int tabIndex = impl.indexOfComponent(comp); + tabContents.put(comp, tab); + + setTabComponent(tab, tabIndex); + lazyTabs.add(new LazyTabInfo(tab, tabContent, descriptor, loader)); + + if (!initLazyTabListenerAdded) { + implTabSheetChangeListeners.add(new LazyTabChangeListener()); + initLazyTabListenerAdded = true; + } + + context = loader.getContext(); + + if (!postInitTaskAdded) { + context.addPostInitTask((context1, window) -> + initComponentTabChangeListener() + ); + postInitTaskAdded = true; + } + return tab; + } + + protected void adjustTabSize(Component tabComponent) { + if (getWidth() >= 0) { + tabComponent.setWidth("100%"); + } else { + tabComponent.setWidth(Component.AUTO_SIZE); + } + + if (getHeight() >= 0) { + tabComponent.setHeight("100%"); + } else { + tabComponent.setHeight(Component.AUTO_SIZE); + } + } + + @Override + public void removeTab(String name) { + TabImpl tab = getTabImpl(name); + Component component = tab.getComponent(); + components.remove(component); + impl.remove(DesktopComponentsHelper.getComposition(component)); + + DesktopContainerHelper.assignContainer(component, null); + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + } + + @Override + public void removeAllTabs() { + impl.removeAll(); + + List innerComponents = new ArrayList<>(components.keySet()); + components.clear(); + + for (Component component : innerComponents) { + DesktopContainerHelper.assignContainer(component, null); + if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + component.setParent(null); + } + } + + protected TabImpl getTabImpl(String name) { + TabImpl tab = null; + for (TabImpl t : tabs) { + if (t.getName().equals(name)) { + tab = t; + break; + } + } + if (tab == null) + throw new IllegalStateException(String.format("Can't find tab '%s'", name)); + return tab; + } + + @Override + public Tab getSelectedTab() { + JComponent component = (JComponent) impl.getSelectedComponent(); + if (component == null) { + return null; // nothing selected + } + for (TabImpl tabImpl : tabs) { + if (DesktopComponentsHelper.getComposition(tabImpl.getComponent()).equals(component)) + return tabImpl; + } + return tabs.get(0); + } + + @Override + public void setSelectedTab(Tab tab) { + Component component = ((TabImpl) tab).getComponent(); + impl.setSelectedComponent(DesktopComponentsHelper.getComposition(component)); + } + + @Override + public void setSelectedTab(String name) { + TabImpl tab = getTabImpl(name); + impl.setSelectedComponent(DesktopComponentsHelper.getComposition(tab.getComponent())); + } + + @Override + public Tab getTab(String name) { + return getTabImpl(name); + } + + @Override + public Component getTabComponent(String name) { + TabImpl tab = getTabImpl(name); + return tab.getComponent(); + } + + @Override + public Collection getTabs() { + return Collections.unmodifiableCollection(tabs); + } + + @Override + public boolean isTabCaptionsAsHtml() { + return tabCaptionsAsHtml; + } + + @Override + public void setTabCaptionsAsHtml(boolean tabCaptionsAsHtml) { + this.tabCaptionsAsHtml = tabCaptionsAsHtml; + } + + @Override + public boolean isTabsVisible() { + return tabsVisible; + } + + @Override + public void setTabsVisible(boolean tabsVisible) { + this.tabsVisible = tabsVisible; + } + + @Override + public void addListener(TabChangeListener listener) { + initComponentTabChangeListener(); + + CompatibleTabSheetSelectedTabChangeListener adapter = new CompatibleTabSheetSelectedTabChangeListener(listener); + + if (!listeners.contains(adapter)) { + listeners.add(adapter); + } + } + + protected void initComponentTabChangeListener() { + // init component SelectedTabChangeListener only when needed, making sure it is + // after all lazy tabs listeners + if (!componentTabChangeListenerInitialized) { + implTabSheetChangeListeners.add(new ComponentTabChangeListener()); + componentTabChangeListenerInitialized = true; + } + } + + @Override + public void applyPermission(UiPermissionDescriptor permissionDescriptor) { + Preconditions.checkNotNullArgument(permissionDescriptor); + + final String subComponentId = permissionDescriptor.getSubComponentId(); + final TabSheet.Tab tab = getTab(subComponentId); + if (tab != null) { + UiPermissionValue permissionValue = permissionDescriptor.getPermissionValue(); + if (permissionValue == UiPermissionValue.HIDE) { + tab.setVisible(false); + } else if (permissionValue == UiPermissionValue.READ_ONLY) { + tab.setEnabled(false); + } + } else { + LoggerFactory.getLogger(DesktopTabSheet.class).info(String.format("Couldn't find component %s in window %s", + subComponentId, permissionDescriptor.getScreenId())); + } + } + + protected class ComponentTabChangeListener implements ChangeListener { + @Override + public void stateChanged(ChangeEvent e) { + if (context != null) { + context.executeInjectTasks(); + context.executePostWrapTasks(); + context.executeInitTasks(); + } + + // Fire GUI listener + fireTabChanged(); + + // Execute outstanding post init tasks after GUI listener. + // We suppose that context.executePostInitTasks() executes a task once and then remove it from task list. + if (context != null) { + context.executePostInitTasks(); + } + + Window window = ComponentsHelper.getWindow(DesktopTabSheet.this); + if (window != null) { + ((DsContextImplementation) window.getDsContext()).resumeSuspended(); + } else { + log.warn("Please specify Frame for TabSheet"); + } + } + } + + protected class LazyTabChangeListener implements ChangeListener { + @Override + public void stateChanged(ChangeEvent e) { + initLazyTab((JComponent) impl.getSelectedComponent()); + } + } + + protected void initLazyTab(JComponent tab) { + LazyTabInfo lti = null; + for (LazyTabInfo lazyTabInfo : lazyTabs) { + if (lazyTabInfo.getTabComponent() == tab) { + lti = lazyTabInfo; + break; + } + } + + if (lti == null) { // already initialized + return; + } + + if (!lti.getTab().isEnabled()) { + return; + } + + lazyTabs.remove(lti); + + lti.loader.createComponent(); + + Component lazyContent = lti.loader.getResultComponent(); + + lazyContent.setWidth("100%"); + lti.tabContent.add(lazyContent); + lti.tabContent.expand(lazyContent, "", ""); + lazyContent.setParent(this); + + lti.loader.loadComponent(); + + if (lazyContent instanceof DesktopAbstractComponent && !isEnabledWithParent()) { + ((DesktopAbstractComponent) lazyContent).setParentEnabled(false); + } + + final Window window = ComponentsHelper.getWindow(DesktopTabSheet.this); + if (window != null) { + ComponentsHelper.walkComponents( + lti.tabContent, + (component, name) -> { + if (component instanceof HasSettings) { + Settings settings = window.getSettings(); + if (settings != null) { + Element e = settings.get(name); + ((HasSettings) component).applySettings(e); + } + } + } + ); + + lti.getTab().setLazyInitialized(true); + } + } + + @Override + public void removeListener(TabChangeListener listener) { + listeners.remove(new CompatibleTabSheetSelectedTabChangeListener(listener)); + } + + protected void fireTabChanged() { + for (SelectedTabChangeListener listener : listeners) { + listener.selectedTabChanged(new SelectedTabChangeEvent(this, getTab())); + } + } + + @Override + public void addSelectedTabChangeListener(SelectedTabChangeListener listener) { + initComponentTabChangeListener(); + + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + @Override + public void removeSelectedTabChangeListener(SelectedTabChangeListener listener) { + listeners.remove(listener); + } + + protected void updateTabVisibility(TabImpl tab) { + // find insert/remove index by visibility of existing tabs + int currentIndex = tab.getTabIndex(); + int idx = 0; + for (TabImpl t : tabs) { + if (t.equals(tab)) + break; + if (t.isVisible()) + idx++; + } + + JComponent comp = DesktopComponentsHelper.getComposition(tab.getComponent()); + if (currentIndex >= 0 || tab.isVisible()) { + if (tab.isVisible()) { + impl.insertTab(tab.getCaption(), null, comp, null, idx); + impl.setTabComponentAt(idx, tab.getButtonTabComponent()); + } else { + impl.removeTabAt(idx); + } + } else { //tab is detached + DetachedFrame detachedFrame = (DetachedFrame) SwingUtilities.getWindowAncestor(comp); + detachedFrame.dispose(); + } + // if we just detach component, it will return isVisible() == true + if (!tab.isVisible()) + comp.setVisible(false); + } + + @Override + public boolean expandsWidth() { + return true; + } + + @Override + public boolean expandsHeight() { + return false; + } + + @Override + public void updateComponent(Component child) { + // do nothing + requestContainerUpdate(); + } + + protected class TabImpl implements TabSheet.Tab { + + private String name; + private Component component; + private String caption; + private boolean enabled = true; + private boolean visible = true; + private boolean closable; + private boolean detachable; + private boolean lazy; + private boolean lazyInitialized; + private ButtonTabComponent buttonTabComponent; + + private String styleName; + + private TabCloseHandler closeHandler; + + public TabImpl(String name, Component component, boolean lazy) { + this.name = name; + this.component = component; + this.lazy = lazy; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + DesktopTabSheet.this.impl.setTitleAt(getTabIndex(), caption); + getButtonTabComponent().setCaption(caption); + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + buttonTabComponent.setEnabled(enabled); + int tabIndex = getTabIndex(); + + if (tabIndex >= 0) { + impl.setEnabledAt(getTabIndex(), enabled); + impl.setComponentAt(tabIndex, enabled ? DesktopComponentsHelper.getComposition(component) : null); + if (impl.getSelectedIndex() == tabIndex && isLazy() && enabled) { + initLazyTab(DesktopComponentsHelper.getComposition(component)); + } + } + + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(enabled); + } + } + + @Override + public boolean isVisible() { + return visible; + } + + @Override + public void setVisible(boolean visible) { + if (visible != this.visible) { + this.visible = visible; + DesktopTabSheet.this.updateTabVisibility(this); + } + } + + @Override + public boolean isClosable() { + return closable; + } + + @Override + public void setClosable(boolean closable) { + if (closable != this.closable) { + getButtonTabComponent().setCloseable(closable); + this.closable = closable; + } + } + + @Override + public boolean isDetachable() { + return detachable; + } + + @Override + public void setDetachable(boolean detachable) { + if (detachable != this.detachable) { + getButtonTabComponent().setDetachable(detachable); + this.detachable = detachable; + } + } + + @Override + public TabCloseHandler getCloseHandler() { + return closeHandler; + } + + @Override + public void setCloseHandler(TabCloseHandler tabCloseHandler) { + this.closeHandler = tabCloseHandler; + } + + public Component getComponent() { + return component; + } + + public int getTabIndex() { + return DesktopTabSheet.this.impl.indexOfTabComponent(buttonTabComponent); + } + + @Override + public String toString() { + return name; + } + + @Override + public void setStyleName(String styleName) { + this.styleName = styleName; + + ButtonTabComponent buttonTabComponent = getButtonTabComponent(); + App.getInstance().getTheme().applyStyle(buttonTabComponent.getTitleLabel(), styleName); + } + + @Override + public String getStyleName() { + return styleName; + } + + public ButtonTabComponent getButtonTabComponent() { + return buttonTabComponent; + } + + public void setButtonTabComponent(ButtonTabComponent buttonTabComponent) { + this.buttonTabComponent = buttonTabComponent; + } + + public boolean isLazyInitialized(){ + return lazyInitialized; + } + + public void setLazyInitialized(boolean lazyInitialized){ + this.lazyInitialized = lazyInitialized; + } + + public boolean isLazy(){ + return lazy; + } + + @Override + public String getIcon() { + return null; + } + + @Override + public void setIcon(String icon) { + // do nothing + } + } + + protected static class LazyTabInfo { + protected DesktopAbstractBox tabContent; + protected Element descriptor; + protected ComponentLoader loader; + protected TabImpl tabImpl; + + public LazyTabInfo(TabImpl tabImpl, DesktopAbstractBox tabContent, Element descriptor, + ComponentLoader loader) { + this.descriptor = descriptor; + this.loader = loader; + this.tabContent = tabContent; + this.tabImpl = tabImpl; + } + + protected JComponent getTabComponent() { + return DesktopComponentsHelper.getComposition(tabContent); + } + + protected TabImpl getTab(){ + return tabImpl; + } + } + + protected void detachTab(final int tabIndex) { + final JComponent tabContent = (JComponent) impl.getComponentAt(tabIndex); + TabImpl tabAtIndex = null; + for (TabImpl tab : tabs) { + if (DesktopComponentsHelper.getComposition(tab.getComponent()) == tabContent) { + tabAtIndex = tab; + if (tab.isLazy() && !tab.isLazyInitialized()) { + initLazyTab(tabContent); + } + break; + } + } + if (tabAtIndex == null) { + throw new IllegalStateException("Unable to find tab to detach"); + } + final TabImpl tabToDetach = tabAtIndex; + final ButtonTabComponent tabComponent = tabToDetach.getButtonTabComponent(); + final JFrame frame = new DetachedFrame(tabComponent.getCaption(), impl); + + frame.setLocationRelativeTo(DesktopComponentsHelper.getTopLevelFrame(this)); + impl.remove(tabContent); + updateTabsEnabledState(); + frame.setSize(impl.getSize()); + frame.add(tabContent); + + final HierarchyListener listener = new HierarchyListener() { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) == HierarchyEvent.DISPLAYABILITY_CHANGED + && !impl.isDisplayable()) { + attachTab(frame, tabToDetach); + impl.removeHierarchyListener(this); + } + } + }; + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + attachTab(frame, tabToDetach); + impl.removeHierarchyListener(listener); + } + }); + + impl.addHierarchyListener(listener); + frame.setVisible(true); + } + + protected void attachTab(JFrame frame, TabImpl tab) { + int tabIndex = 0; + int attachedBeforeCount = 0; + JComponent tabContent = DesktopComponentsHelper.getComposition(tab.getComponent()); + String caption = tab.getCaption(); + ButtonTabComponent tabComponent = tab.getButtonTabComponent(); + for (Map.Entry entry : tabContents.entrySet()) { + if (entry.getKey() == tabContent) { + tabIndex = attachedBeforeCount; + break; + } else if (entry.getKey().getParent() == impl) { + attachedBeforeCount++; + } + } + + impl.add(tabContent, tabIndex); + if (!tab.isEnabled()) { + impl.setComponentAt(tabIndex, null); + } + impl.setTitleAt(tabIndex, caption); + impl.setTabComponentAt(tabIndex, tabComponent); + updateTabsEnabledState(); + tabComponent.revalidate(); + tabComponent.repaint(); + frame.dispose(); + } + + protected void updateTabsEnabledState() { + for (TabImpl tab : tabs) { + int tabIndex = tab.getTabIndex(); + if (tabIndex >= 0) { + impl.setEnabledAt(tab.getTabIndex(), tab.isEnabled()); + } + } + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + for (Component component : components.keySet()) { + if (component instanceof DesktopAbstractComponent) { + JComponent composition = DesktopComponentsHelper.getComposition(component); + TabImpl tab = tabContents.get(composition); + + ((DesktopAbstractComponent) component).setParentEnabled(tab.isEnabled() && isEnabledWithParent()); + } + } + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTable.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTable.java index 026349de78..d354593fb4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTable.java @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.gui.data.TableModelAdapter; -import com.haulmont.cuba.desktop.sys.vcl.JXTableExt; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import org.jdesktop.swingx.JXTable; - -import javax.swing.event.ChangeEvent; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import java.awt.*; - -public class DesktopTable extends DesktopAbstractTable { - - public DesktopTable() { - impl = new JXTableExt() { - @Override - public void setFont(Font font) { - super.setFont(font); - applyFont(this, font); - } - - /** - * Default implementation uses row sorter to return rows count, - * but there is nonconformity in how RowSorterImpl and table wrapper counts rows. - * Absence of this method will lead to empty table in case of sortable=false. - */ - @Override - public int getRowCount() { - return getModel().getRowCount(); - } - - @Override - public void editingStopped(ChangeEvent e) { - TableCellEditor editor = getCellEditor(); - if (editor != null) { - Object value = editor.getCellEditorValue(); - DesktopTable tableComponent = DesktopTable.this; - if (editingColumn >= 0) { - Column editColumn = tableComponent.getColumns().get(editingColumn); - - if (!(editor instanceof DesktopAbstractTable.EditableColumnTableCellEditor) - && !(editor instanceof DesktopAbstractTable.CellProviderEditor)) { - if (tableComponent.isEditable() && editColumn.isEditable() && - !tableModel.isGeneratedColumn(editColumn)) { - setValueAt(value, editingRow, editingColumn); - } - } - removeEditor(); - } - } - } - - @Override - public TableCellRenderer getCellRenderer(int row, int column) { - TableCellRenderer columnRenderer = DesktopTable.this.getColumnRenderer(column); - if (columnRenderer != null) { - return columnRenderer; - } - - return super.getCellRenderer(row, column); - } - - @Override - public boolean isCellEditable(int row, int column) { - if (DesktopTable.this.isCustomCellEditable(row, column)) { - return true; - } - - return super.isCellEditable(row, column); - } - - @Override - public TableCellEditor getCellEditor(int row, int column) { - TableCellEditor cellEditor = getColumnEditor(column); - if (cellEditor != null) { - return cellEditor; - } - - TableCellEditor tableCellEditor = DesktopTable.this.getCellEditor(row, column); - if (tableCellEditor != null) - return tableCellEditor; - - return super.getCellEditor(row, column); - } - }; - - initComponent(); - impl.setColumnControlVisible(true); - - tableSettings = new SwingXTableSettings(impl, columnsOrder); - } - - @Override - protected void initTableModel(CollectionDatasource datasource) { - tableModel = new TableModelAdapter(datasource, columnsOrder, true); - impl.setModel(tableModel); - } - - @Override - public void setSortable(boolean sortable) { - super.setSortable(sortable); - impl.setSortable(sortable); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.gui.data.TableModelAdapter; +import com.haulmont.cuba.desktop.sys.vcl.JXTableExt; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import org.jdesktop.swingx.JXTable; + +import javax.swing.event.ChangeEvent; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.awt.*; + +public class DesktopTable extends DesktopAbstractTable { + + public DesktopTable() { + impl = new JXTableExt() { + @Override + public void setFont(Font font) { + super.setFont(font); + applyFont(this, font); + } + + /** + * Default implementation uses row sorter to return rows count, + * but there is nonconformity in how RowSorterImpl and table wrapper counts rows. + * Absence of this method will lead to empty table in case of sortable=false. + */ + @Override + public int getRowCount() { + return getModel().getRowCount(); + } + + @Override + public void editingStopped(ChangeEvent e) { + TableCellEditor editor = getCellEditor(); + if (editor != null) { + Object value = editor.getCellEditorValue(); + DesktopTable tableComponent = DesktopTable.this; + if (editingColumn >= 0) { + Column editColumn = tableComponent.getColumns().get(editingColumn); + + if (!(editor instanceof DesktopAbstractTable.EditableColumnTableCellEditor) + && !(editor instanceof DesktopAbstractTable.CellProviderEditor)) { + if (tableComponent.isEditable() && editColumn.isEditable() && + !tableModel.isGeneratedColumn(editColumn)) { + setValueAt(value, editingRow, editingColumn); + } + } + removeEditor(); + } + } + } + + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + TableCellRenderer columnRenderer = DesktopTable.this.getColumnRenderer(column); + if (columnRenderer != null) { + return columnRenderer; + } + + return super.getCellRenderer(row, column); + } + + @Override + public boolean isCellEditable(int row, int column) { + if (DesktopTable.this.isCustomCellEditable(row, column)) { + return true; + } + + return super.isCellEditable(row, column); + } + + @Override + public TableCellEditor getCellEditor(int row, int column) { + TableCellEditor cellEditor = getColumnEditor(column); + if (cellEditor != null) { + return cellEditor; + } + + TableCellEditor tableCellEditor = DesktopTable.this.getCellEditor(row, column); + if (tableCellEditor != null) + return tableCellEditor; + + return super.getCellEditor(row, column); + } + }; + + initComponent(); + impl.setColumnControlVisible(true); + + tableSettings = new SwingXTableSettings(impl, columnsOrder); + } + + @Override + protected void initTableModel(CollectionDatasource datasource) { + tableModel = new TableModelAdapter(datasource, columnsOrder, true); + impl.setModel(tableModel); + } + + @Override + public void setSortable(boolean sortable) { + super.setSortable(sortable); + impl.setSortable(sortable); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTableCellEditor.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTableCellEditor.java index 5d364a2168..9c0b38646c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTableCellEditor.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTableCellEditor.java @@ -1,335 +1,335 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.sys.vcl.DatePicker.DatePicker; -import com.haulmont.cuba.desktop.sys.vcl.Flushable; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Label; -import org.jdesktop.swingx.JXHyperlink; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; - -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import java.awt.*; -import java.awt.Component; -import java.util.*; - -import static com.haulmont.cuba.gui.components.Component.BelongToFrame; - -public class DesktopTableCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { - - // Client property key for cell editor components, value of property contains table for this editor - public static final String CELL_EDITOR_TABLE = "CELL_EDITOR_TABLE"; - public static final String CELL_COMPONENT = "CELL_COMPONENT"; - - private static final long serialVersionUID = 5217563286634642347L; - - private Table.ColumnGenerator columnGenerator; - private Component activeComponent; - private Map cache = new HashMap<>(); - - // Used for properly removing column from table - private Table.Column associatedRuntimeColumn; - - /* - * true, if cells of this column hold editable content. - * Swing treats keyboard, mouse, focus events for editable and not-editable cells differently. - */ - private boolean editable; - private DesktopAbstractTable desktopAbstractTable; - private Border border; - private Class componentClass; - - private static final Set readOnlyComponentClasses = new HashSet(Arrays.asList( - Label.class, Checkbox.class - )); - - private static final Set inlineComponentClasses = new HashSet(Arrays.asList( - Label.class, Checkbox.class - )); - - public DesktopTableCellEditor(DesktopAbstractTable desktopAbstractTable, Table.ColumnGenerator columnGenerator, - Class componentClass) { - this.desktopAbstractTable = desktopAbstractTable; - this.columnGenerator = columnGenerator; - this.componentClass = componentClass; - this.editable = isEditableComponent(componentClass); - } - - /* - * If component is editable, it should gain focus from table. - * Mouse events like mouse dragging are treated differently for editable columns. - */ - protected boolean isEditableComponent(Class componentClass) { - if (componentClass == null) { - return true; - } - for (Class readOnlyClass : readOnlyComponentClasses) { - if (componentClass.isAssignableFrom(readOnlyClass)) { - return false; - } - } - return true; - } - - /* - * Inline components always fit in standard row height, - * so there is no need to pack rows for desktop table. - */ - public boolean isInline() { - if (componentClass == null) { - return false; - } - for (Class inlineClass : inlineComponentClasses) { - if (componentClass.isAssignableFrom(inlineClass)) { - return true; - } - } - return false; - } - - @Override - public boolean isCellEditable(EventObject e) { - return editable; - } - - public void setEditable(boolean editable) { - this.editable = editable; - } - - public Table.ColumnGenerator getColumnGenerator() { - return columnGenerator; - } - - protected Component getCellComponent(int row) { - Entity item = desktopAbstractTable.getTableModel().getItem(row); - - StopWatch sw = new Log4JStopWatch("TableColumnGenerator." + desktopAbstractTable.getId()); - @SuppressWarnings("unchecked") - com.haulmont.cuba.gui.components.Component component = columnGenerator.generateCell(item); - sw.stop(); - - Component comp; - if (component == null) { - comp = new JLabel(""); - } else if (component instanceof Table.PlainTextCell) { - comp = new JLabel(((Table.PlainTextCell) component).getText()); - } else { - if (component instanceof BelongToFrame) { - BelongToFrame belongToFrame = (BelongToFrame) component; - if (belongToFrame.getFrame() == null) { - belongToFrame.setFrame(desktopAbstractTable.getFrame()); - } - } - component.setParent(desktopAbstractTable); - - JComponent jComposition = DesktopComponentsHelper.getComposition(component); - jComposition.putClientProperty(CELL_EDITOR_TABLE, desktopAbstractTable.getComponent()); - jComposition.putClientProperty(CELL_COMPONENT, component); - - comp = jComposition; - } - - cache.put(row, comp); - return comp; - } - - public Table.Column getAssociatedRuntimeColumn() { - return associatedRuntimeColumn; - } - - public void setAssociatedRuntimeColumn(Table.Column associatedRuntimeColumn) { - this.associatedRuntimeColumn = associatedRuntimeColumn; - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - Component component = getCellComponent(row); - applyStyle(component, table, true, true, row); - - String stylename = desktopAbstractTable.getStylename(table, row, column); - desktopAbstractTable.applyStylename(isSelected, true, activeComponent, stylename); - return component; - } - - @Override - public Object getCellEditorValue() { - if (activeComponent != null) { - flush(activeComponent); - - Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - - if (focusOwner == activeComponent || - (activeComponent instanceof Container && ((Container) activeComponent).isAncestorOf(focusOwner))) { - desktopAbstractTable.impl.requestFocus(); - } - } - return ""; - } - - private void flush(Component component) { - if (component instanceof Flushable) { - ((Flushable) component).flushValue(); - } else if (component instanceof Container) { - for(Component child : ((Container) component).getComponents()){ - flush(child); - } - } - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, - boolean hasFocus, int row, int column) { - activeComponent = cache.get(row); - if (activeComponent == null) { - activeComponent = getCellComponent(row); - cache.put(row, activeComponent); - } - - applyStyle(activeComponent, table, isSelected, hasFocus, row); - - String stylename = desktopAbstractTable.getStylename(table, row, column); - desktopAbstractTable.applyStylename(isSelected, hasFocus, activeComponent, stylename); - - return activeComponent; - } - - public void clearCache() { - cache.clear(); - } - - public Border getBorder() { - return border; - } - - public void setBorder(Border border) { - this.border = border; - } - - public void applyStyle(java.awt.Component component, JTable table, boolean isSelected, boolean hasFocus, int row) { - if (!(component instanceof JComponent)) { - return; - } - JComponent jcomponent = (JComponent) component; - jcomponent.setOpaque(true); - - if (isSelected) { - if (isTextField(jcomponent)) { - // another JTextField dirty workaround. If use selectionBackground, then it's all blue - jcomponent.setBackground(table.getBackground()); - jcomponent.setForeground(table.getForeground()); - } else { - jcomponent.setBackground(table.getSelectionBackground()); - jcomponent.setForeground(table.getSelectionForeground()); - } - } else { - jcomponent.setForeground(table.getForeground()); - Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); - if (row % 2 == 1) { - Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); - if (alternateColor != null) { - background = alternateColor; - } - } - jcomponent.setBackground(background); - } - - com.haulmont.cuba.gui.components.Component cellComponent = - (com.haulmont.cuba.gui.components.Component) jcomponent.getClientProperty(CELL_COMPONENT); - if (cellComponent instanceof DesktopAbstractField) { - ((DesktopAbstractField) cellComponent).updateMissingValueState(); - } - - jcomponent.setFont(table.getFont()); - - assignBorder(table, isSelected, hasFocus, jcomponent); - } - - private boolean isTextField(JComponent jcomponent) { - if (jcomponent instanceof JTextField) { - return true; - } - if (jcomponent instanceof JPanel) { - Component[] panelChildren = jcomponent.getComponents(); - if ((panelChildren.length == 1 && panelChildren[0] instanceof JTextField)) { - return true; - } - } - return false; - } - - private boolean isLookupField(JComponent jcomponent) { - if (jcomponent instanceof JComboBox) { - return true; - } - if (jcomponent instanceof JPanel) { - Component[] panelChildren = jcomponent.getComponents(); - if ((panelChildren.length == 1 && panelChildren[0] instanceof JComboBox)) { - return true; - } - } - return false; - } - - private boolean isDateField(JComponent jcomponent) { - if (jcomponent instanceof JComboBox) { - return true; - } - if (jcomponent instanceof JPanel) { - Component[] panelChildren = jcomponent.getComponents(); - if ((panelChildren.length == 2 && panelChildren[0] instanceof DatePicker)) { - return true; - } - } - return false; - } - - private void assignBorder(JTable table, boolean isSelected, boolean hasFocus, JComponent jcomponent) { - if (isTextField(jcomponent)) { - // looks like simple label when with empty border - } else if (border != null) { - jcomponent.setBorder(border); - } else if (isLookupField(jcomponent) || isDateField(jcomponent) || jcomponent instanceof JXHyperlink) { - // empty borders for fields except text fields in tables - jcomponent.setBorder(new EmptyBorder(0, 0, 0, 0)); - } else { - if (hasFocus) { - Border border = null; - if (isSelected) { - border = UIManager.getDefaults().getBorder("Table.focusSelectedCellHighlightBorder"); - } - if (border == null) { - border = UIManager.getDefaults().getBorder("Table.focusCellHighlightBorder"); - } - jcomponent.setBorder(border); - } else { - jcomponent.setBorder(getNoFocusBorder(jcomponent, table)); - } - } - } - - private Border getNoFocusBorder(JComponent jcomponent, JTable table) { - return UIManager.getDefaults().getBorder("Table.cellNoFocusBorder"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.sys.vcl.DatePicker.DatePicker; +import com.haulmont.cuba.desktop.sys.vcl.Flushable; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Label; +import org.jdesktop.swingx.JXHyperlink; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.awt.*; +import java.awt.Component; +import java.util.*; + +import static com.haulmont.cuba.gui.components.Component.BelongToFrame; + +public class DesktopTableCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { + + // Client property key for cell editor components, value of property contains table for this editor + public static final String CELL_EDITOR_TABLE = "CELL_EDITOR_TABLE"; + public static final String CELL_COMPONENT = "CELL_COMPONENT"; + + private static final long serialVersionUID = 5217563286634642347L; + + private Table.ColumnGenerator columnGenerator; + private Component activeComponent; + private Map cache = new HashMap<>(); + + // Used for properly removing column from table + private Table.Column associatedRuntimeColumn; + + /* + * true, if cells of this column hold editable content. + * Swing treats keyboard, mouse, focus events for editable and not-editable cells differently. + */ + private boolean editable; + private DesktopAbstractTable desktopAbstractTable; + private Border border; + private Class componentClass; + + private static final Set readOnlyComponentClasses = new HashSet(Arrays.asList( + Label.class, Checkbox.class + )); + + private static final Set inlineComponentClasses = new HashSet(Arrays.asList( + Label.class, Checkbox.class + )); + + public DesktopTableCellEditor(DesktopAbstractTable desktopAbstractTable, Table.ColumnGenerator columnGenerator, + Class componentClass) { + this.desktopAbstractTable = desktopAbstractTable; + this.columnGenerator = columnGenerator; + this.componentClass = componentClass; + this.editable = isEditableComponent(componentClass); + } + + /* + * If component is editable, it should gain focus from table. + * Mouse events like mouse dragging are treated differently for editable columns. + */ + protected boolean isEditableComponent(Class componentClass) { + if (componentClass == null) { + return true; + } + for (Class readOnlyClass : readOnlyComponentClasses) { + if (componentClass.isAssignableFrom(readOnlyClass)) { + return false; + } + } + return true; + } + + /* + * Inline components always fit in standard row height, + * so there is no need to pack rows for desktop table. + */ + public boolean isInline() { + if (componentClass == null) { + return false; + } + for (Class inlineClass : inlineComponentClasses) { + if (componentClass.isAssignableFrom(inlineClass)) { + return true; + } + } + return false; + } + + @Override + public boolean isCellEditable(EventObject e) { + return editable; + } + + public void setEditable(boolean editable) { + this.editable = editable; + } + + public Table.ColumnGenerator getColumnGenerator() { + return columnGenerator; + } + + protected Component getCellComponent(int row) { + Entity item = desktopAbstractTable.getTableModel().getItem(row); + + StopWatch sw = new Log4JStopWatch("TableColumnGenerator." + desktopAbstractTable.getId()); + @SuppressWarnings("unchecked") + com.haulmont.cuba.gui.components.Component component = columnGenerator.generateCell(item); + sw.stop(); + + Component comp; + if (component == null) { + comp = new JLabel(""); + } else if (component instanceof Table.PlainTextCell) { + comp = new JLabel(((Table.PlainTextCell) component).getText()); + } else { + if (component instanceof BelongToFrame) { + BelongToFrame belongToFrame = (BelongToFrame) component; + if (belongToFrame.getFrame() == null) { + belongToFrame.setFrame(desktopAbstractTable.getFrame()); + } + } + component.setParent(desktopAbstractTable); + + JComponent jComposition = DesktopComponentsHelper.getComposition(component); + jComposition.putClientProperty(CELL_EDITOR_TABLE, desktopAbstractTable.getComponent()); + jComposition.putClientProperty(CELL_COMPONENT, component); + + comp = jComposition; + } + + cache.put(row, comp); + return comp; + } + + public Table.Column getAssociatedRuntimeColumn() { + return associatedRuntimeColumn; + } + + public void setAssociatedRuntimeColumn(Table.Column associatedRuntimeColumn) { + this.associatedRuntimeColumn = associatedRuntimeColumn; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + Component component = getCellComponent(row); + applyStyle(component, table, true, true, row); + + String stylename = desktopAbstractTable.getStylename(table, row, column); + desktopAbstractTable.applyStylename(isSelected, true, activeComponent, stylename); + return component; + } + + @Override + public Object getCellEditorValue() { + if (activeComponent != null) { + flush(activeComponent); + + Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + + if (focusOwner == activeComponent || + (activeComponent instanceof Container && ((Container) activeComponent).isAncestorOf(focusOwner))) { + desktopAbstractTable.impl.requestFocus(); + } + } + return ""; + } + + private void flush(Component component) { + if (component instanceof Flushable) { + ((Flushable) component).flushValue(); + } else if (component instanceof Container) { + for(Component child : ((Container) component).getComponents()){ + flush(child); + } + } + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + activeComponent = cache.get(row); + if (activeComponent == null) { + activeComponent = getCellComponent(row); + cache.put(row, activeComponent); + } + + applyStyle(activeComponent, table, isSelected, hasFocus, row); + + String stylename = desktopAbstractTable.getStylename(table, row, column); + desktopAbstractTable.applyStylename(isSelected, hasFocus, activeComponent, stylename); + + return activeComponent; + } + + public void clearCache() { + cache.clear(); + } + + public Border getBorder() { + return border; + } + + public void setBorder(Border border) { + this.border = border; + } + + public void applyStyle(java.awt.Component component, JTable table, boolean isSelected, boolean hasFocus, int row) { + if (!(component instanceof JComponent)) { + return; + } + JComponent jcomponent = (JComponent) component; + jcomponent.setOpaque(true); + + if (isSelected) { + if (isTextField(jcomponent)) { + // another JTextField dirty workaround. If use selectionBackground, then it's all blue + jcomponent.setBackground(table.getBackground()); + jcomponent.setForeground(table.getForeground()); + } else { + jcomponent.setBackground(table.getSelectionBackground()); + jcomponent.setForeground(table.getSelectionForeground()); + } + } else { + jcomponent.setForeground(table.getForeground()); + Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); + if (row % 2 == 1) { + Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); + if (alternateColor != null) { + background = alternateColor; + } + } + jcomponent.setBackground(background); + } + + com.haulmont.cuba.gui.components.Component cellComponent = + (com.haulmont.cuba.gui.components.Component) jcomponent.getClientProperty(CELL_COMPONENT); + if (cellComponent instanceof DesktopAbstractField) { + ((DesktopAbstractField) cellComponent).updateMissingValueState(); + } + + jcomponent.setFont(table.getFont()); + + assignBorder(table, isSelected, hasFocus, jcomponent); + } + + private boolean isTextField(JComponent jcomponent) { + if (jcomponent instanceof JTextField) { + return true; + } + if (jcomponent instanceof JPanel) { + Component[] panelChildren = jcomponent.getComponents(); + if ((panelChildren.length == 1 && panelChildren[0] instanceof JTextField)) { + return true; + } + } + return false; + } + + private boolean isLookupField(JComponent jcomponent) { + if (jcomponent instanceof JComboBox) { + return true; + } + if (jcomponent instanceof JPanel) { + Component[] panelChildren = jcomponent.getComponents(); + if ((panelChildren.length == 1 && panelChildren[0] instanceof JComboBox)) { + return true; + } + } + return false; + } + + private boolean isDateField(JComponent jcomponent) { + if (jcomponent instanceof JComboBox) { + return true; + } + if (jcomponent instanceof JPanel) { + Component[] panelChildren = jcomponent.getComponents(); + if ((panelChildren.length == 2 && panelChildren[0] instanceof DatePicker)) { + return true; + } + } + return false; + } + + private void assignBorder(JTable table, boolean isSelected, boolean hasFocus, JComponent jcomponent) { + if (isTextField(jcomponent)) { + // looks like simple label when with empty border + } else if (border != null) { + jcomponent.setBorder(border); + } else if (isLookupField(jcomponent) || isDateField(jcomponent) || jcomponent instanceof JXHyperlink) { + // empty borders for fields except text fields in tables + jcomponent.setBorder(new EmptyBorder(0, 0, 0, 0)); + } else { + if (hasFocus) { + Border border = null; + if (isSelected) { + border = UIManager.getDefaults().getBorder("Table.focusSelectedCellHighlightBorder"); + } + if (border == null) { + border = UIManager.getDefaults().getBorder("Table.focusCellHighlightBorder"); + } + jcomponent.setBorder(border); + } else { + jcomponent.setBorder(getNoFocusBorder(jcomponent, table)); + } + } + } + + private Border getNoFocusBorder(JComponent jcomponent, JTable table) { + return UIManager.getDefaults().getBorder("Table.cellNoFocusBorder"); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTextField.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTextField.java index e126bee161..2f5f79c6df 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTextField.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTextField.java @@ -1,278 +1,278 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; -import com.haulmont.cuba.desktop.sys.vcl.Flushable; -import com.haulmont.cuba.gui.components.Formatter; -import com.haulmont.cuba.gui.components.TextField; -import org.apache.commons.lang.StringUtils; -import org.jdesktop.swingx.prompt.PromptSupport; - -import javax.swing.*; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.util.ArrayList; - -public class DesktopTextField extends DesktopAbstractTextField implements TextField { - - protected String inputPrompt; - // just stub - protected CaseConversion caseConversion; - // just stub - protected int textChangeTimeout; - // just stub - protected TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY; - - protected java.util.List enterPressListeners = new ArrayList<>(); - - protected boolean enterPressInitialized = false; - - @Override - protected JTextField createTextComponentImpl() { - JTextField field = new FlushableTextField(); - - int height = (int) field.getPreferredSize().getHeight(); - field.setPreferredSize(new Dimension(150, height)); - return field; - } - - @Override - public int getMaxLength() { - return maxLength; - } - - @Override - public void setMaxLength(int value) { - maxLength = value; - ((TextComponentDocument) doc).setMaxLength(value); - } - - @Override - public boolean isTrimming() { - return trimming; - } - - @Override - public void setTrimming(boolean trimming) { - this.trimming = trimming; - } - - @Override - public Datatype getDatatype() { - return datatype; - } - - @Override - public void updateEnabled() { - super.updateEnabled(); - - refreshInputPrompt(); - } - - @Override - protected void setEditableToComponent(boolean editable) { - super.setEditableToComponent(editable); - - refreshInputPrompt(); - } - - protected void refreshInputPrompt() { - if (StringUtils.isNotBlank(inputPrompt)) { - if (isEnabledWithParent() && isEditableWithParent()) { - // Save old tooltipText value to use it later - String toolTipText = this.impl.getToolTipText(); - - PromptSupport.setPrompt(inputPrompt, impl); - - // Use old tooltipText value because it was overwritten in org.jdesktop.swingx.prompt.PromptSupport.setPrompt() - this.impl.setToolTipText(toolTipText); - } else { - PromptSupport.setPrompt(null, impl); - } - } - } - - @Override - public void setDatatype(Datatype datatype) { - this.datatype = datatype; - this.valueFormatter.setDatatype(datatype); - } - - @Override - public Formatter getFormatter() { - return valueFormatter.getFormatter(); - } - - @Override - public void setFormatter(Formatter formatter) { - valueFormatter.setFormatter(formatter); - } - - @Override - public String getInputPrompt() { - return inputPrompt; - } - - @Override - public void setInputPrompt(String inputPrompt) { - this.inputPrompt = inputPrompt; - - if ((!isEditableWithParent() || !this.impl.isEnabled()) && StringUtils.isNotBlank(inputPrompt)) { - return; - } - - if (StringUtils.isNotBlank(inputPrompt)) { - // Save old tooltipText value to use it later - String toolTipText = this.impl.getToolTipText(); - - PromptSupport.setPrompt(inputPrompt, impl); - - // Use old tooltipText value because it was overwritten in org.jdesktop.swingx.prompt.PromptSupport.setPrompt() - this.impl.setToolTipText(toolTipText); - } else { - PromptSupport.setPrompt(null, impl); - } - } - - @Override - public void setCursorPosition(int position) { - impl.setSelectionStart(position); - impl.setSelectionEnd(position); - } - - @Override - public CaseConversion getCaseConversion() { - return caseConversion; - } - - @Override - public void setCaseConversion(CaseConversion caseConversion) { - this.caseConversion = caseConversion; - } - - @Override - public String getRawValue() { - return impl.getText(); - } - - @Override - public void selectAll() { - impl.selectAll(); - } - - @Override - public void setSelectionRange(int pos, int length) { - impl.select(pos, pos + length); - } - - @Override - public void addTextChangeListener(TextChangeListener listener) { - } - - @Override - public void removeTextChangeListener(TextChangeListener listener) { - } - - @Override - public void setTextChangeTimeout(int timeout) { - this.textChangeTimeout = timeout; - } - - @Override - public int getTextChangeTimeout() { - return textChangeTimeout; - } - - @Override - public TextChangeEventMode getTextChangeEventMode() { - return textChangeEventMode; - } - - @Override - public void setTextChangeEventMode(TextChangeEventMode mode) { - Preconditions.checkNotNullArgument(mode); - this.textChangeEventMode = mode; - } - - @Override - public void addEnterPressListener(EnterPressListener listener) { - Preconditions.checkNotNullArgument(listener); - - if (!enterPressListeners.contains(listener)) { - enterPressListeners.add(listener); - } - - if (!enterPressInitialized) { - impl.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); - impl.getActionMap().put("enter", new ValidationAwareAction() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - EnterPressEvent event = new EnterPressEvent(DesktopTextField.this); - for (EnterPressListener enterPressListener : new ArrayList<>(enterPressListeners)) { - enterPressListener.enterPressed(event); - } - } - }); - enterPressInitialized = true; - } - } - - @Override - public void removeEnterPressListener(EnterPressListener listener) { - enterPressListeners.remove(listener); - } - - @Override - public void commit() { - // do nothing - } - - @Override - public void discard() { - // do nothing - } - - @Override - public boolean isBuffered() { - // do nothing - return false; - } - - @Override - public void setBuffered(boolean buffered) { - // do nothing - } - - @Override - public boolean isModified() { - // do nothing - return false; - } - - protected class FlushableTextField extends JTextField implements Flushable { - - @Override - public void flushValue() { - flush(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; +import com.haulmont.cuba.desktop.sys.vcl.Flushable; +import com.haulmont.cuba.gui.components.Formatter; +import com.haulmont.cuba.gui.components.TextField; +import org.apache.commons.lang.StringUtils; +import org.jdesktop.swingx.prompt.PromptSupport; + +import javax.swing.*; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.ArrayList; + +public class DesktopTextField extends DesktopAbstractTextField implements TextField { + + protected String inputPrompt; + // just stub + protected CaseConversion caseConversion; + // just stub + protected int textChangeTimeout; + // just stub + protected TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY; + + protected java.util.List enterPressListeners = new ArrayList<>(); + + protected boolean enterPressInitialized = false; + + @Override + protected JTextField createTextComponentImpl() { + JTextField field = new FlushableTextField(); + + int height = (int) field.getPreferredSize().getHeight(); + field.setPreferredSize(new Dimension(150, height)); + return field; + } + + @Override + public int getMaxLength() { + return maxLength; + } + + @Override + public void setMaxLength(int value) { + maxLength = value; + ((TextComponentDocument) doc).setMaxLength(value); + } + + @Override + public boolean isTrimming() { + return trimming; + } + + @Override + public void setTrimming(boolean trimming) { + this.trimming = trimming; + } + + @Override + public Datatype getDatatype() { + return datatype; + } + + @Override + public void updateEnabled() { + super.updateEnabled(); + + refreshInputPrompt(); + } + + @Override + protected void setEditableToComponent(boolean editable) { + super.setEditableToComponent(editable); + + refreshInputPrompt(); + } + + protected void refreshInputPrompt() { + if (StringUtils.isNotBlank(inputPrompt)) { + if (isEnabledWithParent() && isEditableWithParent()) { + // Save old tooltipText value to use it later + String toolTipText = this.impl.getToolTipText(); + + PromptSupport.setPrompt(inputPrompt, impl); + + // Use old tooltipText value because it was overwritten in org.jdesktop.swingx.prompt.PromptSupport.setPrompt() + this.impl.setToolTipText(toolTipText); + } else { + PromptSupport.setPrompt(null, impl); + } + } + } + + @Override + public void setDatatype(Datatype datatype) { + this.datatype = datatype; + this.valueFormatter.setDatatype(datatype); + } + + @Override + public Formatter getFormatter() { + return valueFormatter.getFormatter(); + } + + @Override + public void setFormatter(Formatter formatter) { + valueFormatter.setFormatter(formatter); + } + + @Override + public String getInputPrompt() { + return inputPrompt; + } + + @Override + public void setInputPrompt(String inputPrompt) { + this.inputPrompt = inputPrompt; + + if ((!isEditableWithParent() || !this.impl.isEnabled()) && StringUtils.isNotBlank(inputPrompt)) { + return; + } + + if (StringUtils.isNotBlank(inputPrompt)) { + // Save old tooltipText value to use it later + String toolTipText = this.impl.getToolTipText(); + + PromptSupport.setPrompt(inputPrompt, impl); + + // Use old tooltipText value because it was overwritten in org.jdesktop.swingx.prompt.PromptSupport.setPrompt() + this.impl.setToolTipText(toolTipText); + } else { + PromptSupport.setPrompt(null, impl); + } + } + + @Override + public void setCursorPosition(int position) { + impl.setSelectionStart(position); + impl.setSelectionEnd(position); + } + + @Override + public CaseConversion getCaseConversion() { + return caseConversion; + } + + @Override + public void setCaseConversion(CaseConversion caseConversion) { + this.caseConversion = caseConversion; + } + + @Override + public String getRawValue() { + return impl.getText(); + } + + @Override + public void selectAll() { + impl.selectAll(); + } + + @Override + public void setSelectionRange(int pos, int length) { + impl.select(pos, pos + length); + } + + @Override + public void addTextChangeListener(TextChangeListener listener) { + } + + @Override + public void removeTextChangeListener(TextChangeListener listener) { + } + + @Override + public void setTextChangeTimeout(int timeout) { + this.textChangeTimeout = timeout; + } + + @Override + public int getTextChangeTimeout() { + return textChangeTimeout; + } + + @Override + public TextChangeEventMode getTextChangeEventMode() { + return textChangeEventMode; + } + + @Override + public void setTextChangeEventMode(TextChangeEventMode mode) { + Preconditions.checkNotNullArgument(mode); + this.textChangeEventMode = mode; + } + + @Override + public void addEnterPressListener(EnterPressListener listener) { + Preconditions.checkNotNullArgument(listener); + + if (!enterPressListeners.contains(listener)) { + enterPressListeners.add(listener); + } + + if (!enterPressInitialized) { + impl.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); + impl.getActionMap().put("enter", new ValidationAwareAction() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + EnterPressEvent event = new EnterPressEvent(DesktopTextField.this); + for (EnterPressListener enterPressListener : new ArrayList<>(enterPressListeners)) { + enterPressListener.enterPressed(event); + } + } + }); + enterPressInitialized = true; + } + } + + @Override + public void removeEnterPressListener(EnterPressListener listener) { + enterPressListeners.remove(listener); + } + + @Override + public void commit() { + // do nothing + } + + @Override + public void discard() { + // do nothing + } + + @Override + public boolean isBuffered() { + // do nothing + return false; + } + + @Override + public void setBuffered(boolean buffered) { + // do nothing + } + + @Override + public boolean isModified() { + // do nothing + return false; + } + + protected class FlushableTextField extends JTextField implements Flushable { + + @Override + public void flushValue() { + flush(); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTokenList.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTokenList.java index 25517046a7..ad16680e7b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTokenList.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTokenList.java @@ -1,1327 +1,1327 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.ExtendedEntities; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.MigBoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; -import com.haulmont.cuba.desktop.sys.vcl.ExtFlowLayout; -import com.haulmont.cuba.gui.DialogParams; -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.WindowParams; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.gui.config.WindowInfo; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.NestedDatasource; -import com.haulmont.cuba.gui.data.ValueListener; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import net.miginfocom.layout.CC; -import net.miginfocom.swing.MigLayout; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.util.*; -import java.util.List; - -@SuppressWarnings("IncorrectCreateGuiComponent") -public class DesktopTokenList extends DesktopAbstractField implements TokenList { - - protected TokenStyleGenerator tokenStyleGenerator; - - protected CollectionDatasource datasource; - - protected String captionProperty; - - protected CaptionMode captionMode; - - protected Position position = Position.TOP; - - protected ItemChangeHandler itemChangeHandler; - - protected ItemClickListener itemClickListener; - - protected boolean inline; - - protected TokenListImpl rootPanel; - - protected DesktopButton addButton; - - protected DesktopButton clearButton; - - protected DesktopLookupPickerField lookupPickerField; - - protected String lookupScreen; - - protected WindowManager.OpenType lookupOpenMode = WindowManager.OpenType.THIS_TAB; - - protected Map lookupScreenParams; - - protected DialogParams lookupScreenDialogParams; - - protected boolean lookup = false; - - protected boolean clearEnabled = true; - - protected boolean simple = false; - - protected AfterLookupCloseHandler afterLookupCloseHandler; - - protected AfterLookupSelectionHandler afterLookupSelectionHandler; - - protected boolean multiselect; - - protected PickerField.LookupAction lookupAction; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - protected final ValueChangeListener lookupSelectListener = e -> { - if (isEditable()) { - addValueFromLookupPickerField(); - } - }; - - // stub - protected String lookupInputPrompt; - - public DesktopTokenList() { - rootPanel = new TokenListImpl(); - - impl = rootPanel.getImpl(); - addButton = new DesktopButton(); - - Messages messages = AppBeans.get(Messages.NAME); - addButton.setCaption(messages.getMessage(TokenList.class, "actions.Add")); - - clearButton = new DesktopButton(); - clearButton.setCaption(messages.getMessage(TokenList.class, "actions.Clear")); - - lookupPickerField = new DesktopLookupPickerField(); - lookupPickerField.addValueChangeListener(lookupSelectListener); - - setMultiSelect(false); - setWidth(Component.AUTO_SIZE); - setHeight(Component.AUTO_SIZE); - } - - @Override - public String getCaptionProperty() { - return captionProperty; - } - - @Override - public void setCaptionProperty(String captionProperty) { - this.captionProperty = captionProperty; - } - - @Override - public CaptionMode getCaptionMode() { - return captionMode; - } - - @Override - public void setCaptionMode(CaptionMode captionMode) { - this.captionMode = captionMode; - } - - @Override - public CollectionDatasource getDatasource() { - return datasource; - } - - @Override - public MetaProperty getMetaProperty() { - return null; - } - - @Override - public MetaPropertyPath getMetaPropertyPath() { - return null; - } - - @Override - public void setDatasource(Datasource datasource, String property) { - throw new UnsupportedOperationException("TokenList does not support datasource with property"); - } - - @SuppressWarnings("unchecked") - @Override - public void setDatasource(CollectionDatasource datasource) { - this.datasource = datasource; - - collectionChangeListener = e -> { - if (lookupPickerField != null) { - if (isLookup()) { - if (getLookupScreen() != null) - lookupAction.setLookupScreen(getLookupScreen()); - else - lookupAction.setLookupScreen(null); - - lookupAction.setLookupScreenOpenType(lookupOpenMode); - lookupAction.setLookupScreenParams(lookupScreenParams); - lookupAction.setLookupScreenDialogParams(lookupScreenDialogParams); - } - } - rootPanel.refreshComponent(); - rootPanel.refreshClickListeners(itemClickListener); - }; - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - } - - @Override - public LookupField.FilterMode getFilterMode() { - return lookupPickerField.getFilterMode(); - } - - @Override - public void setFilterMode(LookupField.FilterMode mode) { - lookupPickerField.setFilterMode(mode); - } - - @Override - public String getOptionsCaptionProperty() { - return lookupPickerField.getCaptionProperty(); - } - - @Override - public void setOptionsCaptionProperty(String captionProperty) { - lookupPickerField.setCaptionProperty(captionProperty); - } - - @Override - public CaptionMode getOptionsCaptionMode() { - return lookupPickerField.getCaptionMode(); - } - - @Override - public void setOptionsCaptionMode(CaptionMode captionMode) { - lookupPickerField.setCaptionMode(captionMode); - } - - @Override - public CollectionDatasource getOptionsDatasource() { - return lookupPickerField.getOptionsDatasource(); - } - - @Override - public void setOptionsDatasource(CollectionDatasource datasource) { - lookupPickerField.setOptionsDatasource(datasource); - } - - @Override - public void setRefreshOptionsOnLookupClose(boolean refresh) { - lookupPickerField.setRefreshOptionsOnLookupClose(refresh); - } - - @Override - public boolean isRefreshOptionsOnLookupClose() { - return lookupPickerField.isRefreshOptionsOnLookupClose(); - } - - @Override - public List getOptionsList() { - return lookupPickerField.getOptionsList(); - } - - @Override - public void setOptionsList(List optionsList) { - lookupPickerField.setOptionsList(optionsList); - } - - @Override - public Map getOptionsMap() { - return lookupPickerField.getOptionsMap(); - } - - @Override - public void setOptionsMap(Map map) { - lookupPickerField.setOptionsMap(map); - } - - @Override - public boolean isClearEnabled() { - return clearEnabled; - } - - @Override - public void setClearEnabled(boolean clearEnabled) { - if (this.clearEnabled != clearEnabled) { - clearButton.setVisible(clearEnabled); - this.clearEnabled = clearEnabled; - rootPanel.refreshComponent(); - } - } - - @Override - public boolean isLookup() { - return lookup; - } - - @Override - public void setLookup(boolean lookup) { - if (this.lookup != lookup) { - if (lookup) { - lookupAction = new PickerField.LookupAction(lookupPickerField) { - @Nonnull - @Override - protected Map prepareScreenParams() { - Map screenParams = super.prepareScreenParams(); - if (isMultiSelect()) { - screenParams = new HashMap<>(screenParams); - WindowParams.MULTI_SELECT.set(screenParams, true); - // for backward compatibility - screenParams.put("multiSelect", "true"); - } - - return screenParams; - } - - @SuppressWarnings("unchecked") - @Override - protected void handleLookupWindowSelection(Collection items) { - if (items.isEmpty()) { - return; - } - - @SuppressWarnings("unchecked") - Collection selected = items; - - CollectionDatasource optionsDatasource = lookupPickerField.getOptionsDatasource(); - if (optionsDatasource != null - && lookupPickerField.isRefreshOptionsOnLookupClose()) { - optionsDatasource.refresh(); - - if (datasource != null) { - for (Object obj : getDatasource().getItems()) { - Entity entity = (Entity) obj; - if (getOptionsDatasource().containsItem(entity.getId())) { - datasource.updateItem(getOptionsDatasource().getItem(entity.getId())); - } - } - } - } - - // add all selected items to tokens - if (itemChangeHandler != null) { - for (Entity newItem : selected) { - itemChangeHandler.addItem(newItem); - } - } else if (datasource != null) { - // get master entity and inverse attribute in case of nested datasource - Entity masterEntity = getMasterEntity(datasource); - MetaProperty inverseProp = getInverseProperty(datasource); - - for (Entity newItem : selected) { - if (!datasource.containsItem(newItem.getId())) { - // Initialize reference to master entity - if (inverseProp != null && isInitializeMasterReference(inverseProp)) { - newItem.setValue(inverseProp.getName(), masterEntity); - } - - datasource.addItem(newItem); - } - } - } - - afterSelect(items); - if (afterLookupSelectionHandler != null) { - afterLookupSelectionHandler.onSelect(items); - } - } - }; - lookupPickerField.addAction(lookupAction); - - if (getLookupScreen() != null) { - lookupAction.setLookupScreen(getLookupScreen()); - } - lookupAction.setLookupScreenOpenType(lookupOpenMode); - lookupAction.setLookupScreenParams(lookupScreenParams); - lookupAction.setLookupScreenDialogParams(lookupScreenDialogParams); - } else { - lookupPickerField.removeAction(lookupAction); - } - - lookupAction.setAfterLookupCloseHandler((window, actionId) -> { - if (afterLookupCloseHandler != null) { - afterLookupCloseHandler.onClose(window, actionId); - } - }); - - lookupAction.setAfterLookupSelectionHandler(items -> { - if (afterLookupSelectionHandler != null) { - afterLookupSelectionHandler.onSelect(items); - } - }); - } - this.lookup = lookup; - - rootPanel.refreshComponent(); - } - - @Override - public String getLookupScreen() { - return lookupScreen; - } - - @Override - public void setLookupScreen(String lookupScreen) { - this.lookupScreen = lookupScreen; - } - - @Override - public void setLookupScreenParams(Map params) { - this.lookupScreenParams = params; - } - - @Override - public Map getLookupScreenParams() { - return lookupScreenParams; - } - - @Override - public void setLookupScreenDialogParams(DialogParams dialogparams) { - this.lookupScreenDialogParams = dialogparams; - } - - @Deprecated - @Nullable - @Override - public DialogParams getLookupScreenDialogParams() { - return lookupScreenDialogParams; - } - - @Override - public boolean isMultiSelect() { - return multiselect; - } - - @Override - public void setMultiSelect(boolean multiselect) { - this.multiselect = multiselect; - } - - @Override - public boolean isSimple() { - return simple; - } - - @Override - public void setSimple(boolean simple) { - this.simple = simple; - this.addButton.setVisible(simple); - this.rootPanel.editor = null; - this.rootPanel.refreshComponent(); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public void setPosition(Position position) { - this.position = position; - this.rootPanel.editor = null; - this.rootPanel.refreshComponent(); - } - - @Override - public WindowManager.OpenType getLookupOpenMode() { - return lookupOpenMode; - } - - @Override - public void setLookupOpenMode(WindowManager.OpenType lookupOpenMode) { - this.lookupOpenMode = lookupOpenMode; - } - - @Override - public boolean isInline() { - return inline; - } - - @Override - public void setInline(boolean inline) { - this.inline = inline; - this.rootPanel.editor = null; - this.rootPanel.refreshComponent(); - } - - @Override - public String getAddButtonCaption() { - return addButton.getCaption(); - } - - @Override - public void setAddButtonCaption(String caption) { - addButton.setCaption(caption); - } - - @Override - public String getAddButtonIcon() { - return addButton.getIcon(); - } - - @Override - public void setAddButtonIcon(String icon) { - addButton.setIcon(icon); - } - - @Override - public String getClearButtonCaption() { - return clearButton.getCaption(); - } - - @Override - public void setClearButtonCaption(String caption) { - clearButton.setCaption(caption); - } - - @Override - public String getClearButtonIcon() { - return clearButton.getIcon(); - } - - @Override - public void setClearButtonIcon(String icon) { - clearButton.setIcon(icon); - } - - @Override - public ItemChangeHandler getItemChangeHandler() { - return itemChangeHandler; - } - - @Override - public void setItemChangeHandler(ItemChangeHandler handler) { - this.itemChangeHandler = handler; - } - - @Override - public ItemClickListener getItemClickListener() { - return this.itemClickListener; - } - - @Override - public void setItemClickListener(ItemClickListener itemClickListener) { - this.itemClickListener = itemClickListener; - this.rootPanel.refreshClickListeners(itemClickListener); - } - - @Override - public AfterLookupCloseHandler getAfterLookupCloseHandler() { - return afterLookupCloseHandler; - } - - @Override - public void setAfterLookupCloseHandler(AfterLookupCloseHandler afterLookupCloseHandler) { - this.afterLookupCloseHandler = afterLookupCloseHandler; - } - - @Override - public AfterLookupSelectionHandler getAfterLookupSelectionHandler() { - return afterLookupSelectionHandler; - } - - @Override - public void setAfterLookupSelectionHandler(AfterLookupSelectionHandler afterLookupSelectionHandler) { - this.afterLookupSelectionHandler = afterLookupSelectionHandler; - } - - @Override - public void setTokenStyleGenerator(TokenStyleGenerator tokenStyleGenerator) { - this.tokenStyleGenerator = tokenStyleGenerator; - } - - @Override - public TokenStyleGenerator getTokenStyleGenerator() { - return tokenStyleGenerator; - } - - @Override - public String getLookupInputPrompt() { - return lookupInputPrompt; - } - - @Override - public void setLookupInputPrompt(String inputPrompt) { - this.lookupInputPrompt = inputPrompt; - } - - @Override - public String getCaption() { - return rootPanel.getCaption(); - } - - @Override - public void setCaption(String caption) { - rootPanel.setCaption(caption); - } - - @Override - public String getDescription() { - return getImpl().getToolTipText(); - } - - @Override - public void setDescription(String description) { - getImpl().setToolTipText(description); - DesktopToolTipManager.getInstance().registerTooltip(impl); - } - - @Override - @SuppressWarnings("unchecked") - public T getValue() { - if (datasource != null) { - List items = new ArrayList<>(datasource.getItems()); - return (T) items; - } else { - return (T) Collections.emptyList(); - } - } - - @Override - public void setValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public void addListener(ValueListener listener) { - // todo - } - - @Override - public void removeListener(ValueListener listener) { - // todo - } - - @Override - public void addValueChangeListener(ValueChangeListener listener) { - LoggerFactory.getLogger(DesktopTokenList.class).warn("addValueChangeListener not implemented for TokenList"); - } - - @Override - public void removeValueChangeListener(ValueChangeListener listener) { - LoggerFactory.getLogger(DesktopTokenList.class).warn("removeValueChangeListener not implemented for TokenList"); - } - - @Override - protected void setEditableToComponent(boolean editable) { - rootPanel.refreshComponent(); - } - - @Override - protected void updateEnabled() { - super.updateEnabled(); - - if (lookupPickerField != null) { - lookupPickerField.setParentEnabled(isEnabledWithParent()); - } - if (addButton != null) { - addButton.setParentEnabled(isEnabledWithParent()); - } - - if (clearButton != null) { - clearButton.setParentEnabled(isEnabledWithParent()); - } - - if (rootPanel != null) { - rootPanel.refreshComponent(); - } - } - - protected String instanceCaption(Instance instance) { - if (instance == null) { - return ""; - } - if (captionProperty != null) { - if (instance.getMetaClass().getPropertyPath(captionProperty) != null) { - Object o = instance.getValueEx(captionProperty); - return o != null ? o.toString() : " "; - } - throw new IllegalArgumentException(String.format("Couldn't find property with name '%s'", - captionProperty)); - } else - return instance.getInstanceName(); - } - - public class TokenListLabel extends DesktopAbstractComponent { - - private DesktopLabel label; - private DesktopHBox composition; - private DesktopButton removeButton; - private DesktopButton openButton; - - private boolean editable; - private boolean enabled; - - private List listeners; - private ClickListener clickListener; - - public TokenListLabel() { - label = new DesktopLabel(); - label.setHeight("24px"); - composition = new DesktopHBox(); - - composition.setSpacing(true); - composition.add(label); - removeButton = new DesktopButton(); - removeButton.getImpl().setPreferredSize(new Dimension(0, 24)); - removeButton.setAction(new AbstractAction("actions.Remove") { - @Override - public String getCaption() { - return ""; - } - - @Override - public void actionPerform(Component component) { - fireRemoveListeners(); - } - }); - - composition.add(removeButton); - removeButton.setVisible(isEditable()); - removeButton.setIcon("icons/remove.png"); - - JButton button = (JButton) removeButton.getComponent(); - button.setBorder(new EmptyBorder(0, 3, 0, 3)); - button.setFocusPainted(false); - button.setBorderPainted(false); - button.setOpaque(false); - button.setContentAreaFilled(false); - button.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - openButton = new DesktopButton(); - openButton.getImpl().setPreferredSize(new Dimension(0, 24)); - openButton.setAction(new AbstractAction("actions.Open") { - @Override - public void actionPerform(Component component) { - fireClickListener(); - } - - @Override - public String getCaption() { - return ""; - } - }); - openButton.setIcon("/components/pickerfield/images/open-btn.png"); - composition.add(openButton); - openButton.setVisible(false); - - button = (JButton) openButton.getComponent(); - button.setBorder(new EmptyBorder(0, 3, 0, 3)); - button.setFocusPainted(false); - button.setBorderPainted(false); - button.setOpaque(false); - button.setContentAreaFilled(false); - button.setCursor(new Cursor(Cursor.HAND_CURSOR)); - - impl = (JLabel) label.getComponent(); - } - - @Override - public JComponent getComposition() { - return composition.getComposition(); - } - - public void setValue(String value) { - label.setValue(value); - } - - public Object getValue() { - return label.getValue(); - } - - public void setEditable(boolean editable) { - this.editable = editable; - removeButton.setVisible(editable); - } - - public boolean isEditable() { - return editable; - } - - @Override - public void setEnabled(boolean enabled) { - this.enabled = enabled; - removeButton.setEnabled(enabled); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - public void addListener(RemoveTokenListener listener) { - if (listeners == null) { - listeners = new ArrayList<>(); - } - listeners.add(listener); - } - - public void removeListener(RemoveTokenListener listener) { - if (listeners != null) { - listeners.remove(listener); - if (listeners.isEmpty()) { - listeners = null; - } - } - } - - public void setClickListener(ClickListener clickListener) { - this.clickListener = clickListener; - openButton.setVisible(clickListener != null); - } - - private void fireRemoveListeners() { - if (listeners != null) { - for (final RemoveTokenListener listener : listeners) { - listener.removeToken(this); - } - } - } - - private void fireClickListener() { - if (clickListener != null) - clickListener.onClick(this); - } - } - - public interface RemoveTokenListener { - void removeToken(TokenListLabel source); - } - - public interface ClickListener { - void onClick(TokenListLabel source); - } - - public class AddAction extends AbstractAction { - - public AddAction() { - super("actions.Add"); - } - - @Override - public String getCaption() { - return addButton.getCaption(); - } - - @Override - public void actionPerform(Component component) { - if (isSimple()) { - openLookupWindow(); - } else { - if (isEditable()) { - addValueFromLookupPickerField(); - } - } - } - - private void openLookupWindow() { - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - - String windowAlias; - if (getLookupScreen() != null) { - windowAlias = getLookupScreen(); - } else if (getOptionsDatasource() != null) { - windowAlias = windowConfig.getBrowseScreenId(getOptionsDatasource().getMetaClass()); - } else { - windowAlias = windowConfig.getBrowseScreenId(getDatasource().getMetaClass()); - } - - WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); - - Map params = new HashMap<>(); - params.put("windowOpener", DesktopTokenList.this.getFrame().getId()); - if (isMultiSelect()) { - WindowParams.MULTI_SELECT.set(params, true); - // for backward compatibility - params.put("multiSelect", "true"); - } - if (lookupScreenParams != null) { - params.putAll(lookupScreenParams); - } - - WindowManager wm = DesktopComponentsHelper.getTopLevelFrame(DesktopTokenList.this).getWindowManager(); - if (lookupOpenMode == WindowManager.OpenType.DIALOG) { - DialogParams dialogParams = wm.getDialogParams(); - - dialogParams.setResizable(true); - if (lookupScreenDialogParams != null) { - dialogParams.setWidth(lookupScreenDialogParams.getWidth()); - dialogParams.setHeight(lookupScreenDialogParams.getHeight()); - } else { - dialogParams.setWidth("800px"); - dialogParams.setHeight("600px"); - } - } - - Window.Lookup lookupWindow = wm.openLookup(windowInfo, new Window.Lookup.Handler() { - @Override - public void handleLookup(Collection items) { - if (lookupPickerField.isRefreshOptionsOnLookupClose()) { - lookupPickerField.getOptionsDatasource().refresh(); - } - - if (isEditable()) { - if (items == null || items.isEmpty()) return; - - handleLookupInternal(items); - - if (afterLookupSelectionHandler != null) { - afterLookupSelectionHandler.onSelect(items); - } - } - } - }, lookupOpenMode, params); - - if (afterLookupCloseHandler != null) { - lookupWindow.addCloseListener(actionId -> - afterLookupCloseHandler.onClose(lookupWindow, actionId) - ); - } - } - - @SuppressWarnings("unchecked") - protected void handleLookupInternal(Collection items) { - // get master entity and inverse attribute in case of nested datasource - Entity masterEntity = getMasterEntity(datasource); - MetaProperty inverseProp = getInverseProperty(datasource); - boolean initializeMasterReference = inverseProp != null && isInitializeMasterReference(inverseProp); - - for (final Object item : items) { - if (itemChangeHandler != null) { - itemChangeHandler.addItem(item); - } else { - if (item instanceof Entity) { - Entity entity = (Entity) item; - if (datasource != null && !datasource.containsItem(entity.getId())) { - // Initialize reference to master entity - if (initializeMasterReference) { - entity.setValue(inverseProp.getName(), masterEntity); - } - datasource.addItem(entity); - } - } - } - } - } - } - - @Override - public void setHeight(String height) { - float oldHeight = getHeight(); - - super.setHeight(height); - - rootPanel.setHeight(height); - - if ((getHeight() > 0 && oldHeight < 0) - || (getHeight() < 0 && oldHeight > 0)) { - rootPanel.refreshComponent(); - } - } - - @Override - public void setWidth(String width) { - float oldWidth = getWidth(); - - super.setWidth(width); - - rootPanel.setWidth(width); - - if ((getWidth() > 0 && oldWidth < 0) - || (getWidth() < 0 && oldWidth > 0)) { - rootPanel.refreshComponent(); - } - } - - @Override - public void setParent(Component parent) { - super.setParent(parent); - - rootPanel.setParent(parent); - } - - @Override - public void setContainer(DesktopContainer container) { - super.setContainer(container); - - rootPanel.setContainer(container); - } - - public class TokenListImpl extends DesktopVBox { - private DesktopScrollBoxLayout scrollContainer; - private JPanel tokensContainer; - - private DesktopHBox editor; - - private Map itemComponents = new HashMap<>(); - private Map componentItems = new HashMap<>(); - - private TokenListImpl() { - setSpacing(true); - setExpanded(true); - - scrollContainer = new DesktopScrollBoxLayout(); - tokensContainer = new JPanel(); - } - - protected void initField() { - DesktopHBox hBox = new DesktopHBox(); - hBox.setSpacing(true); - hBox.setWidth("100%"); - - if (!isSimple()) { - if (lookupPickerField.getParent() instanceof Container) { - ((Container) lookupPickerField.getParent()).remove(lookupPickerField); - } - lookupPickerField.setWidth("100%"); - hBox.add(lookupPickerField); - hBox.expand(lookupPickerField); - } - addButton.setAction(new AddAction()); - - lookupPickerField.setVisible(!isSimple()); - addButton.setVisible(isSimple()); - - addButton.setStyleName("add-btn"); - if (addButton.getParent() instanceof Container) { - ((Container) addButton.getParent()).remove(addButton); - } - hBox.add(addButton); - - clearButton.setAction(new AbstractAction("actions.Clear") { - @Override - public String getCaption() { - return clearButton.getCaption(); - } - - @Override - public void actionPerform(Component component) { - for (TokenListLabel item : new ArrayList<>(itemComponents.values())) { - doRemove(item); - } - } - }); - clearButton.setVisible(clearEnabled); - clearButton.setStyleName("clear-btn"); - if (clearButton.getParent() instanceof Container) { - ((Container) clearButton.getParent()).remove(clearButton); - } - if (isSimple()) { - DesktopHBox clearBox = new DesktopHBox(); - clearBox.add(clearButton); - hBox.add(clearBox); - hBox.expand(clearBox); - } else { - hBox.add(clearButton); - } - - editor = hBox; - } - - protected void setTokenStyle(TokenListLabel label, Object itemId) { - if (tokenStyleGenerator != null) { - String styleName = tokenStyleGenerator.getStyle(itemId); - if (styleName != null && !styleName.equals("")) { - label.setStyleName(styleName); - } - } - } - - public void refreshComponent() { - if (editor != null) { - remove(editor); - } - - if (editor == null) { - initField(); - } - - if (isEditable()) { - if (position == Position.TOP) { - add(editor, 0); - } else { - add(editor); - } - } - - if (inline) { - tokensContainer.setLayout(new ExtFlowLayout()); - } else { - BoxLayoutAdapter tcLayoutAdapter = MigBoxLayoutAdapter.create(tokensContainer); - tcLayoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - } - - CC tokensContainerCC = new CC(); - if ((getHeight() < 0 || getWidth() < 0) && !inline) { - MigLayoutHelper.applyWidth(tokensContainerCC, -1, UNITS_PIXELS, false); - } else { - MigLayoutHelper.applyWidth(tokensContainerCC, 100, UNITS_PERCENTAGE, false); - } - - MigLayoutHelper.applyHeight(tokensContainerCC, -1, UNITS_PIXELS, false); - - tokensContainer.removeAll(); - - remove(scrollContainer); - scrollContainer.removeAll(); - impl.remove(tokensContainer); - - if (getHeight() < 0 || getWidth() < 0) { - impl.add(tokensContainer, tokensContainerCC); - } else { - DesktopVBox scrollWrap = new DesktopVBox(); - scrollWrap.setHeight(AUTO_SIZE); - scrollWrap.getImpl().add(tokensContainer, tokensContainerCC); - - scrollContainer.setWidth("100%"); - scrollContainer.setHeight("100%"); - - if (inline) { - scrollContainer.setScrollBarPolicy(ScrollBoxLayout.ScrollBarPolicy.VERTICAL); - } else { - scrollContainer.setScrollBarPolicy(ScrollBoxLayout.ScrollBarPolicy.BOTH); - } - - scrollContainer.remove(scrollWrap); - scrollContainer.add(scrollWrap); - - add(scrollContainer); - } - - if (datasource != null) { - List usedItems = new ArrayList<>(); - - // New tokens - for (Object itemId : datasource.getItemIds()) { - Instance item = datasource.getItem(itemId); - TokenListLabel f = itemComponents.get(item); - if (f == null) { - f = createToken(); - itemComponents.put(item, f); - componentItems.put(f, item); - } - - f.setEnabled(DesktopTokenList.this.isEnabledWithParent()); - f.setEditable(isEditable()); - f.setValue(instanceCaption(item)); - - setTokenStyle(f, itemId); - - if (tokensContainer.getLayout() instanceof MigLayout) { - CC tokenCC = new CC(); - MigLayoutHelper.applyWidth(tokenCC, -1, UNITS_PIXELS, false); - MigLayoutHelper.applyHeight(tokenCC, -1, UNITS_PIXELS, false); - - tokensContainer.add(f.getComposition(), tokenCC); - } else { - tokensContainer.add(f.getComposition()); - } - - usedItems.add(item); - } - - // Remove obsolete items - for (Instance componentItem : new ArrayList<>(itemComponents.keySet())) { - if (!usedItems.contains(componentItem)) { - componentItems.remove(itemComponents.get(componentItem)); - itemComponents.remove(componentItem); - } - } - } - - tokensContainer.revalidate(); - tokensContainer.repaint(); - - requestRepaint(); - requestContainerUpdate(); - } - - public void refreshClickListeners(ItemClickListener listener) { - if (datasource != null && CollectionDatasource.State.VALID.equals(datasource.getState())) { - for (Object id : datasource.getItemIds()) { - Instance item = datasource.getItem(id); - final TokenListLabel label = itemComponents.get(item); - if (label != null) { - if (listener == null) { - label.setClickListener(null); - } else { - label.setClickListener(new ClickListener() { - @Override - public void onClick(TokenListLabel source) { - doClick(label); - } - }); - } - } - } - } - } - - protected TokenListLabel createToken() { - TokenListLabel label = new TokenListLabel(); - label.setWidth(Component.AUTO_SIZE); - label.addListener(new RemoveTokenListener() { - @Override - public void removeToken(final TokenListLabel source) { - if (isEditable()) { - doRemove(source); - } - } - }); - return label; - } - - protected void doRemove(TokenListLabel source) { - Instance item = componentItems.get(source); - if (item != null) { - itemComponents.remove(item); - componentItems.remove(source); - - if (itemChangeHandler != null) { //todo test - itemChangeHandler.removeItem(item); - } else { - // get inverse attribute in case of nested datasource - MetaProperty inverseProp = getInverseProperty(datasource); - boolean initializeMasterReference = inverseProp != null - && isInitializeMasterReference(inverseProp); - - if (initializeMasterReference) { - item.setValue(inverseProp.getName(), null); - datasource.excludeItem((Entity) item); - return; - } else { - datasource.removeItem((Entity) item); - } - } - } - } - - protected void doClick(TokenListLabel source) { - if (itemClickListener != null) { - Instance item = componentItems.get(source); - if (item != null) - itemClickListener.onClick(item); - } - } - } - - @SuppressWarnings("unchecked") - protected void addValueFromLookupPickerField() { - final Entity newItem = lookupPickerField.getValue(); - if (newItem == null) return; - if (itemChangeHandler != null) { - itemChangeHandler.addItem(newItem); - } else { - if (datasource != null) { - // get master entity and inverse attribute in case of nested datasource - Entity masterEntity = getMasterEntity(datasource); - MetaProperty inverseProp = getInverseProperty(datasource); - - if (!datasource.containsItem(newItem.getId())) { - // Initialize reference to master entity - if (inverseProp != null && isInitializeMasterReference(inverseProp)) { - newItem.setValue(inverseProp.getName(), masterEntity); - } - - datasource.addItem(newItem); - } - } - } - lookupPickerField.setValue(null); - - if (lookupPickerField.isRefreshOptionsOnLookupClose()) { - for (Object obj : getDatasource().getItems()) { - Entity entity = (Entity) obj; - if (getOptionsDatasource().containsItem(entity.getId())) { - datasource.updateItem(getOptionsDatasource().getItem(entity.getId())); - } - } - } - } - - @Nullable - protected Entity getMasterEntity(CollectionDatasource datasource) { - if (datasource instanceof NestedDatasource) { - Datasource masterDs = ((NestedDatasource) datasource).getMaster(); - com.google.common.base.Preconditions.checkState(masterDs != null); - return masterDs.getItem(); - } - return null; - } - - @Nullable - protected MetaProperty getInverseProperty(CollectionDatasource datasource) { - if (datasource instanceof NestedDatasource) { - MetaProperty metaProperty = ((NestedDatasource) datasource).getProperty(); - com.google.common.base.Preconditions.checkState(metaProperty != null); - return metaProperty.getInverse(); - } - return null; - } - - protected boolean isInitializeMasterReference(MetaProperty inverseProp) { - return !inverseProp.getRange().getCardinality().isMany() - && isInversePropertyAssignableFromDsClass(inverseProp); - - } - - protected boolean isInversePropertyAssignableFromDsClass(MetaProperty inverseProp) { - Metadata metadata = AppBeans.get(Metadata.NAME); - ExtendedEntities extendedEntities = metadata.getExtendedEntities(); - - Class inversePropClass = extendedEntities.getEffectiveClass(inverseProp.getDomain()); - Class dsClass = extendedEntities.getEffectiveClass(datasource.getMetaClass()); - - //noinspection unchecked - return inversePropClass.isAssignableFrom(dsClass); - } - - @Override - protected boolean isEmpty(Object value) { - return super.isEmpty(value) || (value instanceof Collection && ((Collection) value).isEmpty()); - } - - @Override - public void requestFocus() { - if (simple) { - addButton.requestFocus(); - } else { - lookupPickerField.requestFocus(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.ExtendedEntities; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.desktop.sys.DesktopToolTipManager; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.MigBoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; +import com.haulmont.cuba.desktop.sys.vcl.ExtFlowLayout; +import com.haulmont.cuba.gui.DialogParams; +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.WindowParams; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.gui.config.WindowInfo; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.NestedDatasource; +import com.haulmont.cuba.gui.data.ValueListener; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import net.miginfocom.layout.CC; +import net.miginfocom.swing.MigLayout; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.util.*; +import java.util.List; + +@SuppressWarnings("IncorrectCreateGuiComponent") +public class DesktopTokenList extends DesktopAbstractField implements TokenList { + + protected TokenStyleGenerator tokenStyleGenerator; + + protected CollectionDatasource datasource; + + protected String captionProperty; + + protected CaptionMode captionMode; + + protected Position position = Position.TOP; + + protected ItemChangeHandler itemChangeHandler; + + protected ItemClickListener itemClickListener; + + protected boolean inline; + + protected TokenListImpl rootPanel; + + protected DesktopButton addButton; + + protected DesktopButton clearButton; + + protected DesktopLookupPickerField lookupPickerField; + + protected String lookupScreen; + + protected WindowManager.OpenType lookupOpenMode = WindowManager.OpenType.THIS_TAB; + + protected Map lookupScreenParams; + + protected DialogParams lookupScreenDialogParams; + + protected boolean lookup = false; + + protected boolean clearEnabled = true; + + protected boolean simple = false; + + protected AfterLookupCloseHandler afterLookupCloseHandler; + + protected AfterLookupSelectionHandler afterLookupSelectionHandler; + + protected boolean multiselect; + + protected PickerField.LookupAction lookupAction; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + protected final ValueChangeListener lookupSelectListener = e -> { + if (isEditable()) { + addValueFromLookupPickerField(); + } + }; + + // stub + protected String lookupInputPrompt; + + public DesktopTokenList() { + rootPanel = new TokenListImpl(); + + impl = rootPanel.getImpl(); + addButton = new DesktopButton(); + + Messages messages = AppBeans.get(Messages.NAME); + addButton.setCaption(messages.getMessage(TokenList.class, "actions.Add")); + + clearButton = new DesktopButton(); + clearButton.setCaption(messages.getMessage(TokenList.class, "actions.Clear")); + + lookupPickerField = new DesktopLookupPickerField(); + lookupPickerField.addValueChangeListener(lookupSelectListener); + + setMultiSelect(false); + setWidth(Component.AUTO_SIZE); + setHeight(Component.AUTO_SIZE); + } + + @Override + public String getCaptionProperty() { + return captionProperty; + } + + @Override + public void setCaptionProperty(String captionProperty) { + this.captionProperty = captionProperty; + } + + @Override + public CaptionMode getCaptionMode() { + return captionMode; + } + + @Override + public void setCaptionMode(CaptionMode captionMode) { + this.captionMode = captionMode; + } + + @Override + public CollectionDatasource getDatasource() { + return datasource; + } + + @Override + public MetaProperty getMetaProperty() { + return null; + } + + @Override + public MetaPropertyPath getMetaPropertyPath() { + return null; + } + + @Override + public void setDatasource(Datasource datasource, String property) { + throw new UnsupportedOperationException("TokenList does not support datasource with property"); + } + + @SuppressWarnings("unchecked") + @Override + public void setDatasource(CollectionDatasource datasource) { + this.datasource = datasource; + + collectionChangeListener = e -> { + if (lookupPickerField != null) { + if (isLookup()) { + if (getLookupScreen() != null) + lookupAction.setLookupScreen(getLookupScreen()); + else + lookupAction.setLookupScreen(null); + + lookupAction.setLookupScreenOpenType(lookupOpenMode); + lookupAction.setLookupScreenParams(lookupScreenParams); + lookupAction.setLookupScreenDialogParams(lookupScreenDialogParams); + } + } + rootPanel.refreshComponent(); + rootPanel.refreshClickListeners(itemClickListener); + }; + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + } + + @Override + public LookupField.FilterMode getFilterMode() { + return lookupPickerField.getFilterMode(); + } + + @Override + public void setFilterMode(LookupField.FilterMode mode) { + lookupPickerField.setFilterMode(mode); + } + + @Override + public String getOptionsCaptionProperty() { + return lookupPickerField.getCaptionProperty(); + } + + @Override + public void setOptionsCaptionProperty(String captionProperty) { + lookupPickerField.setCaptionProperty(captionProperty); + } + + @Override + public CaptionMode getOptionsCaptionMode() { + return lookupPickerField.getCaptionMode(); + } + + @Override + public void setOptionsCaptionMode(CaptionMode captionMode) { + lookupPickerField.setCaptionMode(captionMode); + } + + @Override + public CollectionDatasource getOptionsDatasource() { + return lookupPickerField.getOptionsDatasource(); + } + + @Override + public void setOptionsDatasource(CollectionDatasource datasource) { + lookupPickerField.setOptionsDatasource(datasource); + } + + @Override + public void setRefreshOptionsOnLookupClose(boolean refresh) { + lookupPickerField.setRefreshOptionsOnLookupClose(refresh); + } + + @Override + public boolean isRefreshOptionsOnLookupClose() { + return lookupPickerField.isRefreshOptionsOnLookupClose(); + } + + @Override + public List getOptionsList() { + return lookupPickerField.getOptionsList(); + } + + @Override + public void setOptionsList(List optionsList) { + lookupPickerField.setOptionsList(optionsList); + } + + @Override + public Map getOptionsMap() { + return lookupPickerField.getOptionsMap(); + } + + @Override + public void setOptionsMap(Map map) { + lookupPickerField.setOptionsMap(map); + } + + @Override + public boolean isClearEnabled() { + return clearEnabled; + } + + @Override + public void setClearEnabled(boolean clearEnabled) { + if (this.clearEnabled != clearEnabled) { + clearButton.setVisible(clearEnabled); + this.clearEnabled = clearEnabled; + rootPanel.refreshComponent(); + } + } + + @Override + public boolean isLookup() { + return lookup; + } + + @Override + public void setLookup(boolean lookup) { + if (this.lookup != lookup) { + if (lookup) { + lookupAction = new PickerField.LookupAction(lookupPickerField) { + @Nonnull + @Override + protected Map prepareScreenParams() { + Map screenParams = super.prepareScreenParams(); + if (isMultiSelect()) { + screenParams = new HashMap<>(screenParams); + WindowParams.MULTI_SELECT.set(screenParams, true); + // for backward compatibility + screenParams.put("multiSelect", "true"); + } + + return screenParams; + } + + @SuppressWarnings("unchecked") + @Override + protected void handleLookupWindowSelection(Collection items) { + if (items.isEmpty()) { + return; + } + + @SuppressWarnings("unchecked") + Collection selected = items; + + CollectionDatasource optionsDatasource = lookupPickerField.getOptionsDatasource(); + if (optionsDatasource != null + && lookupPickerField.isRefreshOptionsOnLookupClose()) { + optionsDatasource.refresh(); + + if (datasource != null) { + for (Object obj : getDatasource().getItems()) { + Entity entity = (Entity) obj; + if (getOptionsDatasource().containsItem(entity.getId())) { + datasource.updateItem(getOptionsDatasource().getItem(entity.getId())); + } + } + } + } + + // add all selected items to tokens + if (itemChangeHandler != null) { + for (Entity newItem : selected) { + itemChangeHandler.addItem(newItem); + } + } else if (datasource != null) { + // get master entity and inverse attribute in case of nested datasource + Entity masterEntity = getMasterEntity(datasource); + MetaProperty inverseProp = getInverseProperty(datasource); + + for (Entity newItem : selected) { + if (!datasource.containsItem(newItem.getId())) { + // Initialize reference to master entity + if (inverseProp != null && isInitializeMasterReference(inverseProp)) { + newItem.setValue(inverseProp.getName(), masterEntity); + } + + datasource.addItem(newItem); + } + } + } + + afterSelect(items); + if (afterLookupSelectionHandler != null) { + afterLookupSelectionHandler.onSelect(items); + } + } + }; + lookupPickerField.addAction(lookupAction); + + if (getLookupScreen() != null) { + lookupAction.setLookupScreen(getLookupScreen()); + } + lookupAction.setLookupScreenOpenType(lookupOpenMode); + lookupAction.setLookupScreenParams(lookupScreenParams); + lookupAction.setLookupScreenDialogParams(lookupScreenDialogParams); + } else { + lookupPickerField.removeAction(lookupAction); + } + + lookupAction.setAfterLookupCloseHandler((window, actionId) -> { + if (afterLookupCloseHandler != null) { + afterLookupCloseHandler.onClose(window, actionId); + } + }); + + lookupAction.setAfterLookupSelectionHandler(items -> { + if (afterLookupSelectionHandler != null) { + afterLookupSelectionHandler.onSelect(items); + } + }); + } + this.lookup = lookup; + + rootPanel.refreshComponent(); + } + + @Override + public String getLookupScreen() { + return lookupScreen; + } + + @Override + public void setLookupScreen(String lookupScreen) { + this.lookupScreen = lookupScreen; + } + + @Override + public void setLookupScreenParams(Map params) { + this.lookupScreenParams = params; + } + + @Override + public Map getLookupScreenParams() { + return lookupScreenParams; + } + + @Override + public void setLookupScreenDialogParams(DialogParams dialogparams) { + this.lookupScreenDialogParams = dialogparams; + } + + @Deprecated + @Nullable + @Override + public DialogParams getLookupScreenDialogParams() { + return lookupScreenDialogParams; + } + + @Override + public boolean isMultiSelect() { + return multiselect; + } + + @Override + public void setMultiSelect(boolean multiselect) { + this.multiselect = multiselect; + } + + @Override + public boolean isSimple() { + return simple; + } + + @Override + public void setSimple(boolean simple) { + this.simple = simple; + this.addButton.setVisible(simple); + this.rootPanel.editor = null; + this.rootPanel.refreshComponent(); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public void setPosition(Position position) { + this.position = position; + this.rootPanel.editor = null; + this.rootPanel.refreshComponent(); + } + + @Override + public WindowManager.OpenType getLookupOpenMode() { + return lookupOpenMode; + } + + @Override + public void setLookupOpenMode(WindowManager.OpenType lookupOpenMode) { + this.lookupOpenMode = lookupOpenMode; + } + + @Override + public boolean isInline() { + return inline; + } + + @Override + public void setInline(boolean inline) { + this.inline = inline; + this.rootPanel.editor = null; + this.rootPanel.refreshComponent(); + } + + @Override + public String getAddButtonCaption() { + return addButton.getCaption(); + } + + @Override + public void setAddButtonCaption(String caption) { + addButton.setCaption(caption); + } + + @Override + public String getAddButtonIcon() { + return addButton.getIcon(); + } + + @Override + public void setAddButtonIcon(String icon) { + addButton.setIcon(icon); + } + + @Override + public String getClearButtonCaption() { + return clearButton.getCaption(); + } + + @Override + public void setClearButtonCaption(String caption) { + clearButton.setCaption(caption); + } + + @Override + public String getClearButtonIcon() { + return clearButton.getIcon(); + } + + @Override + public void setClearButtonIcon(String icon) { + clearButton.setIcon(icon); + } + + @Override + public ItemChangeHandler getItemChangeHandler() { + return itemChangeHandler; + } + + @Override + public void setItemChangeHandler(ItemChangeHandler handler) { + this.itemChangeHandler = handler; + } + + @Override + public ItemClickListener getItemClickListener() { + return this.itemClickListener; + } + + @Override + public void setItemClickListener(ItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + this.rootPanel.refreshClickListeners(itemClickListener); + } + + @Override + public AfterLookupCloseHandler getAfterLookupCloseHandler() { + return afterLookupCloseHandler; + } + + @Override + public void setAfterLookupCloseHandler(AfterLookupCloseHandler afterLookupCloseHandler) { + this.afterLookupCloseHandler = afterLookupCloseHandler; + } + + @Override + public AfterLookupSelectionHandler getAfterLookupSelectionHandler() { + return afterLookupSelectionHandler; + } + + @Override + public void setAfterLookupSelectionHandler(AfterLookupSelectionHandler afterLookupSelectionHandler) { + this.afterLookupSelectionHandler = afterLookupSelectionHandler; + } + + @Override + public void setTokenStyleGenerator(TokenStyleGenerator tokenStyleGenerator) { + this.tokenStyleGenerator = tokenStyleGenerator; + } + + @Override + public TokenStyleGenerator getTokenStyleGenerator() { + return tokenStyleGenerator; + } + + @Override + public String getLookupInputPrompt() { + return lookupInputPrompt; + } + + @Override + public void setLookupInputPrompt(String inputPrompt) { + this.lookupInputPrompt = inputPrompt; + } + + @Override + public String getCaption() { + return rootPanel.getCaption(); + } + + @Override + public void setCaption(String caption) { + rootPanel.setCaption(caption); + } + + @Override + public String getDescription() { + return getImpl().getToolTipText(); + } + + @Override + public void setDescription(String description) { + getImpl().setToolTipText(description); + DesktopToolTipManager.getInstance().registerTooltip(impl); + } + + @Override + @SuppressWarnings("unchecked") + public T getValue() { + if (datasource != null) { + List items = new ArrayList<>(datasource.getItems()); + return (T) items; + } else { + return (T) Collections.emptyList(); + } + } + + @Override + public void setValue(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public void addListener(ValueListener listener) { + // todo + } + + @Override + public void removeListener(ValueListener listener) { + // todo + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + LoggerFactory.getLogger(DesktopTokenList.class).warn("addValueChangeListener not implemented for TokenList"); + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + LoggerFactory.getLogger(DesktopTokenList.class).warn("removeValueChangeListener not implemented for TokenList"); + } + + @Override + protected void setEditableToComponent(boolean editable) { + rootPanel.refreshComponent(); + } + + @Override + protected void updateEnabled() { + super.updateEnabled(); + + if (lookupPickerField != null) { + lookupPickerField.setParentEnabled(isEnabledWithParent()); + } + if (addButton != null) { + addButton.setParentEnabled(isEnabledWithParent()); + } + + if (clearButton != null) { + clearButton.setParentEnabled(isEnabledWithParent()); + } + + if (rootPanel != null) { + rootPanel.refreshComponent(); + } + } + + protected String instanceCaption(Instance instance) { + if (instance == null) { + return ""; + } + if (captionProperty != null) { + if (instance.getMetaClass().getPropertyPath(captionProperty) != null) { + Object o = instance.getValueEx(captionProperty); + return o != null ? o.toString() : " "; + } + throw new IllegalArgumentException(String.format("Couldn't find property with name '%s'", + captionProperty)); + } else + return instance.getInstanceName(); + } + + public class TokenListLabel extends DesktopAbstractComponent { + + private DesktopLabel label; + private DesktopHBox composition; + private DesktopButton removeButton; + private DesktopButton openButton; + + private boolean editable; + private boolean enabled; + + private List listeners; + private ClickListener clickListener; + + public TokenListLabel() { + label = new DesktopLabel(); + label.setHeight("24px"); + composition = new DesktopHBox(); + + composition.setSpacing(true); + composition.add(label); + removeButton = new DesktopButton(); + removeButton.getImpl().setPreferredSize(new Dimension(0, 24)); + removeButton.setAction(new AbstractAction("actions.Remove") { + @Override + public String getCaption() { + return ""; + } + + @Override + public void actionPerform(Component component) { + fireRemoveListeners(); + } + }); + + composition.add(removeButton); + removeButton.setVisible(isEditable()); + removeButton.setIcon("icons/remove.png"); + + JButton button = (JButton) removeButton.getComponent(); + button.setBorder(new EmptyBorder(0, 3, 0, 3)); + button.setFocusPainted(false); + button.setBorderPainted(false); + button.setOpaque(false); + button.setContentAreaFilled(false); + button.setCursor(new Cursor(Cursor.HAND_CURSOR)); + + openButton = new DesktopButton(); + openButton.getImpl().setPreferredSize(new Dimension(0, 24)); + openButton.setAction(new AbstractAction("actions.Open") { + @Override + public void actionPerform(Component component) { + fireClickListener(); + } + + @Override + public String getCaption() { + return ""; + } + }); + openButton.setIcon("/components/pickerfield/images/open-btn.png"); + composition.add(openButton); + openButton.setVisible(false); + + button = (JButton) openButton.getComponent(); + button.setBorder(new EmptyBorder(0, 3, 0, 3)); + button.setFocusPainted(false); + button.setBorderPainted(false); + button.setOpaque(false); + button.setContentAreaFilled(false); + button.setCursor(new Cursor(Cursor.HAND_CURSOR)); + + impl = (JLabel) label.getComponent(); + } + + @Override + public JComponent getComposition() { + return composition.getComposition(); + } + + public void setValue(String value) { + label.setValue(value); + } + + public Object getValue() { + return label.getValue(); + } + + public void setEditable(boolean editable) { + this.editable = editable; + removeButton.setVisible(editable); + } + + public boolean isEditable() { + return editable; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + removeButton.setEnabled(enabled); + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public void addListener(RemoveTokenListener listener) { + if (listeners == null) { + listeners = new ArrayList<>(); + } + listeners.add(listener); + } + + public void removeListener(RemoveTokenListener listener) { + if (listeners != null) { + listeners.remove(listener); + if (listeners.isEmpty()) { + listeners = null; + } + } + } + + public void setClickListener(ClickListener clickListener) { + this.clickListener = clickListener; + openButton.setVisible(clickListener != null); + } + + private void fireRemoveListeners() { + if (listeners != null) { + for (final RemoveTokenListener listener : listeners) { + listener.removeToken(this); + } + } + } + + private void fireClickListener() { + if (clickListener != null) + clickListener.onClick(this); + } + } + + public interface RemoveTokenListener { + void removeToken(TokenListLabel source); + } + + public interface ClickListener { + void onClick(TokenListLabel source); + } + + public class AddAction extends AbstractAction { + + public AddAction() { + super("actions.Add"); + } + + @Override + public String getCaption() { + return addButton.getCaption(); + } + + @Override + public void actionPerform(Component component) { + if (isSimple()) { + openLookupWindow(); + } else { + if (isEditable()) { + addValueFromLookupPickerField(); + } + } + } + + private void openLookupWindow() { + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + + String windowAlias; + if (getLookupScreen() != null) { + windowAlias = getLookupScreen(); + } else if (getOptionsDatasource() != null) { + windowAlias = windowConfig.getBrowseScreenId(getOptionsDatasource().getMetaClass()); + } else { + windowAlias = windowConfig.getBrowseScreenId(getDatasource().getMetaClass()); + } + + WindowInfo windowInfo = windowConfig.getWindowInfo(windowAlias); + + Map params = new HashMap<>(); + params.put("windowOpener", DesktopTokenList.this.getFrame().getId()); + if (isMultiSelect()) { + WindowParams.MULTI_SELECT.set(params, true); + // for backward compatibility + params.put("multiSelect", "true"); + } + if (lookupScreenParams != null) { + params.putAll(lookupScreenParams); + } + + WindowManager wm = DesktopComponentsHelper.getTopLevelFrame(DesktopTokenList.this).getWindowManager(); + if (lookupOpenMode == WindowManager.OpenType.DIALOG) { + DialogParams dialogParams = wm.getDialogParams(); + + dialogParams.setResizable(true); + if (lookupScreenDialogParams != null) { + dialogParams.setWidth(lookupScreenDialogParams.getWidth()); + dialogParams.setHeight(lookupScreenDialogParams.getHeight()); + } else { + dialogParams.setWidth("800px"); + dialogParams.setHeight("600px"); + } + } + + Window.Lookup lookupWindow = wm.openLookup(windowInfo, new Window.Lookup.Handler() { + @Override + public void handleLookup(Collection items) { + if (lookupPickerField.isRefreshOptionsOnLookupClose()) { + lookupPickerField.getOptionsDatasource().refresh(); + } + + if (isEditable()) { + if (items == null || items.isEmpty()) return; + + handleLookupInternal(items); + + if (afterLookupSelectionHandler != null) { + afterLookupSelectionHandler.onSelect(items); + } + } + } + }, lookupOpenMode, params); + + if (afterLookupCloseHandler != null) { + lookupWindow.addCloseListener(actionId -> + afterLookupCloseHandler.onClose(lookupWindow, actionId) + ); + } + } + + @SuppressWarnings("unchecked") + protected void handleLookupInternal(Collection items) { + // get master entity and inverse attribute in case of nested datasource + Entity masterEntity = getMasterEntity(datasource); + MetaProperty inverseProp = getInverseProperty(datasource); + boolean initializeMasterReference = inverseProp != null && isInitializeMasterReference(inverseProp); + + for (final Object item : items) { + if (itemChangeHandler != null) { + itemChangeHandler.addItem(item); + } else { + if (item instanceof Entity) { + Entity entity = (Entity) item; + if (datasource != null && !datasource.containsItem(entity.getId())) { + // Initialize reference to master entity + if (initializeMasterReference) { + entity.setValue(inverseProp.getName(), masterEntity); + } + datasource.addItem(entity); + } + } + } + } + } + } + + @Override + public void setHeight(String height) { + float oldHeight = getHeight(); + + super.setHeight(height); + + rootPanel.setHeight(height); + + if ((getHeight() > 0 && oldHeight < 0) + || (getHeight() < 0 && oldHeight > 0)) { + rootPanel.refreshComponent(); + } + } + + @Override + public void setWidth(String width) { + float oldWidth = getWidth(); + + super.setWidth(width); + + rootPanel.setWidth(width); + + if ((getWidth() > 0 && oldWidth < 0) + || (getWidth() < 0 && oldWidth > 0)) { + rootPanel.refreshComponent(); + } + } + + @Override + public void setParent(Component parent) { + super.setParent(parent); + + rootPanel.setParent(parent); + } + + @Override + public void setContainer(DesktopContainer container) { + super.setContainer(container); + + rootPanel.setContainer(container); + } + + public class TokenListImpl extends DesktopVBox { + private DesktopScrollBoxLayout scrollContainer; + private JPanel tokensContainer; + + private DesktopHBox editor; + + private Map itemComponents = new HashMap<>(); + private Map componentItems = new HashMap<>(); + + private TokenListImpl() { + setSpacing(true); + setExpanded(true); + + scrollContainer = new DesktopScrollBoxLayout(); + tokensContainer = new JPanel(); + } + + protected void initField() { + DesktopHBox hBox = new DesktopHBox(); + hBox.setSpacing(true); + hBox.setWidth("100%"); + + if (!isSimple()) { + if (lookupPickerField.getParent() instanceof Container) { + ((Container) lookupPickerField.getParent()).remove(lookupPickerField); + } + lookupPickerField.setWidth("100%"); + hBox.add(lookupPickerField); + hBox.expand(lookupPickerField); + } + addButton.setAction(new AddAction()); + + lookupPickerField.setVisible(!isSimple()); + addButton.setVisible(isSimple()); + + addButton.setStyleName("add-btn"); + if (addButton.getParent() instanceof Container) { + ((Container) addButton.getParent()).remove(addButton); + } + hBox.add(addButton); + + clearButton.setAction(new AbstractAction("actions.Clear") { + @Override + public String getCaption() { + return clearButton.getCaption(); + } + + @Override + public void actionPerform(Component component) { + for (TokenListLabel item : new ArrayList<>(itemComponents.values())) { + doRemove(item); + } + } + }); + clearButton.setVisible(clearEnabled); + clearButton.setStyleName("clear-btn"); + if (clearButton.getParent() instanceof Container) { + ((Container) clearButton.getParent()).remove(clearButton); + } + if (isSimple()) { + DesktopHBox clearBox = new DesktopHBox(); + clearBox.add(clearButton); + hBox.add(clearBox); + hBox.expand(clearBox); + } else { + hBox.add(clearButton); + } + + editor = hBox; + } + + protected void setTokenStyle(TokenListLabel label, Object itemId) { + if (tokenStyleGenerator != null) { + String styleName = tokenStyleGenerator.getStyle(itemId); + if (styleName != null && !styleName.equals("")) { + label.setStyleName(styleName); + } + } + } + + public void refreshComponent() { + if (editor != null) { + remove(editor); + } + + if (editor == null) { + initField(); + } + + if (isEditable()) { + if (position == Position.TOP) { + add(editor, 0); + } else { + add(editor); + } + } + + if (inline) { + tokensContainer.setLayout(new ExtFlowLayout()); + } else { + BoxLayoutAdapter tcLayoutAdapter = MigBoxLayoutAdapter.create(tokensContainer); + tcLayoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + } + + CC tokensContainerCC = new CC(); + if ((getHeight() < 0 || getWidth() < 0) && !inline) { + MigLayoutHelper.applyWidth(tokensContainerCC, -1, UNITS_PIXELS, false); + } else { + MigLayoutHelper.applyWidth(tokensContainerCC, 100, UNITS_PERCENTAGE, false); + } + + MigLayoutHelper.applyHeight(tokensContainerCC, -1, UNITS_PIXELS, false); + + tokensContainer.removeAll(); + + remove(scrollContainer); + scrollContainer.removeAll(); + impl.remove(tokensContainer); + + if (getHeight() < 0 || getWidth() < 0) { + impl.add(tokensContainer, tokensContainerCC); + } else { + DesktopVBox scrollWrap = new DesktopVBox(); + scrollWrap.setHeight(AUTO_SIZE); + scrollWrap.getImpl().add(tokensContainer, tokensContainerCC); + + scrollContainer.setWidth("100%"); + scrollContainer.setHeight("100%"); + + if (inline) { + scrollContainer.setScrollBarPolicy(ScrollBoxLayout.ScrollBarPolicy.VERTICAL); + } else { + scrollContainer.setScrollBarPolicy(ScrollBoxLayout.ScrollBarPolicy.BOTH); + } + + scrollContainer.remove(scrollWrap); + scrollContainer.add(scrollWrap); + + add(scrollContainer); + } + + if (datasource != null) { + List usedItems = new ArrayList<>(); + + // New tokens + for (Object itemId : datasource.getItemIds()) { + Instance item = datasource.getItem(itemId); + TokenListLabel f = itemComponents.get(item); + if (f == null) { + f = createToken(); + itemComponents.put(item, f); + componentItems.put(f, item); + } + + f.setEnabled(DesktopTokenList.this.isEnabledWithParent()); + f.setEditable(isEditable()); + f.setValue(instanceCaption(item)); + + setTokenStyle(f, itemId); + + if (tokensContainer.getLayout() instanceof MigLayout) { + CC tokenCC = new CC(); + MigLayoutHelper.applyWidth(tokenCC, -1, UNITS_PIXELS, false); + MigLayoutHelper.applyHeight(tokenCC, -1, UNITS_PIXELS, false); + + tokensContainer.add(f.getComposition(), tokenCC); + } else { + tokensContainer.add(f.getComposition()); + } + + usedItems.add(item); + } + + // Remove obsolete items + for (Instance componentItem : new ArrayList<>(itemComponents.keySet())) { + if (!usedItems.contains(componentItem)) { + componentItems.remove(itemComponents.get(componentItem)); + itemComponents.remove(componentItem); + } + } + } + + tokensContainer.revalidate(); + tokensContainer.repaint(); + + requestRepaint(); + requestContainerUpdate(); + } + + public void refreshClickListeners(ItemClickListener listener) { + if (datasource != null && CollectionDatasource.State.VALID.equals(datasource.getState())) { + for (Object id : datasource.getItemIds()) { + Instance item = datasource.getItem(id); + final TokenListLabel label = itemComponents.get(item); + if (label != null) { + if (listener == null) { + label.setClickListener(null); + } else { + label.setClickListener(new ClickListener() { + @Override + public void onClick(TokenListLabel source) { + doClick(label); + } + }); + } + } + } + } + } + + protected TokenListLabel createToken() { + TokenListLabel label = new TokenListLabel(); + label.setWidth(Component.AUTO_SIZE); + label.addListener(new RemoveTokenListener() { + @Override + public void removeToken(final TokenListLabel source) { + if (isEditable()) { + doRemove(source); + } + } + }); + return label; + } + + protected void doRemove(TokenListLabel source) { + Instance item = componentItems.get(source); + if (item != null) { + itemComponents.remove(item); + componentItems.remove(source); + + if (itemChangeHandler != null) { //todo test + itemChangeHandler.removeItem(item); + } else { + // get inverse attribute in case of nested datasource + MetaProperty inverseProp = getInverseProperty(datasource); + boolean initializeMasterReference = inverseProp != null + && isInitializeMasterReference(inverseProp); + + if (initializeMasterReference) { + item.setValue(inverseProp.getName(), null); + datasource.excludeItem((Entity) item); + return; + } else { + datasource.removeItem((Entity) item); + } + } + } + } + + protected void doClick(TokenListLabel source) { + if (itemClickListener != null) { + Instance item = componentItems.get(source); + if (item != null) + itemClickListener.onClick(item); + } + } + } + + @SuppressWarnings("unchecked") + protected void addValueFromLookupPickerField() { + final Entity newItem = lookupPickerField.getValue(); + if (newItem == null) return; + if (itemChangeHandler != null) { + itemChangeHandler.addItem(newItem); + } else { + if (datasource != null) { + // get master entity and inverse attribute in case of nested datasource + Entity masterEntity = getMasterEntity(datasource); + MetaProperty inverseProp = getInverseProperty(datasource); + + if (!datasource.containsItem(newItem.getId())) { + // Initialize reference to master entity + if (inverseProp != null && isInitializeMasterReference(inverseProp)) { + newItem.setValue(inverseProp.getName(), masterEntity); + } + + datasource.addItem(newItem); + } + } + } + lookupPickerField.setValue(null); + + if (lookupPickerField.isRefreshOptionsOnLookupClose()) { + for (Object obj : getDatasource().getItems()) { + Entity entity = (Entity) obj; + if (getOptionsDatasource().containsItem(entity.getId())) { + datasource.updateItem(getOptionsDatasource().getItem(entity.getId())); + } + } + } + } + + @Nullable + protected Entity getMasterEntity(CollectionDatasource datasource) { + if (datasource instanceof NestedDatasource) { + Datasource masterDs = ((NestedDatasource) datasource).getMaster(); + com.google.common.base.Preconditions.checkState(masterDs != null); + return masterDs.getItem(); + } + return null; + } + + @Nullable + protected MetaProperty getInverseProperty(CollectionDatasource datasource) { + if (datasource instanceof NestedDatasource) { + MetaProperty metaProperty = ((NestedDatasource) datasource).getProperty(); + com.google.common.base.Preconditions.checkState(metaProperty != null); + return metaProperty.getInverse(); + } + return null; + } + + protected boolean isInitializeMasterReference(MetaProperty inverseProp) { + return !inverseProp.getRange().getCardinality().isMany() + && isInversePropertyAssignableFromDsClass(inverseProp); + + } + + protected boolean isInversePropertyAssignableFromDsClass(MetaProperty inverseProp) { + Metadata metadata = AppBeans.get(Metadata.NAME); + ExtendedEntities extendedEntities = metadata.getExtendedEntities(); + + Class inversePropClass = extendedEntities.getEffectiveClass(inverseProp.getDomain()); + Class dsClass = extendedEntities.getEffectiveClass(datasource.getMetaClass()); + + //noinspection unchecked + return inversePropClass.isAssignableFrom(dsClass); + } + + @Override + protected boolean isEmpty(Object value) { + return super.isEmpty(value) || (value instanceof Collection && ((Collection) value).isEmpty()); + } + + @Override + public void requestFocus() { + if (simple) { + addButton.requestFocus(); + } else { + lookupPickerField.requestFocus(); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTree.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTree.java index 358d912ef3..1ff9e28b47 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTree.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTree.java @@ -1,706 +1,706 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; -import com.haulmont.cuba.gui.ComponentsHelper; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.HierarchicalDatasource; -import com.haulmont.cuba.gui.data.impl.CollectionDsActionsNotifier; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; -import java.util.List; - -public class DesktopTree extends DesktopAbstractActionsHolderComponent - implements Tree, LookupComponent.LookupSelectionChangeNotifier { - - protected String hierarchyProperty; - protected HierarchicalDatasource, Object> datasource; - protected JScrollPane treeView; - protected CaptionMode captionMode = CaptionMode.ITEM; - protected String captionProperty; - protected TreeModelAdapter model; - - protected ButtonsPanel buttonsPanel; - protected MigLayout layout; - protected JPanel panel; - protected JPanel topPanel; - - protected Action doubleClickAction; - protected MouseAdapter itemClickListener; - protected Action enterPressAction; - protected boolean editable = true; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - protected CollectionDsActionsNotifier collectionDsActionsNotifier; - - protected List lookupSelectionChangeListeners = new ArrayList<>(); - - public DesktopTree() { - layout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); - panel = new JPanel(layout); - - topPanel = new JPanel(new BorderLayout()); - topPanel.setVisible(false); - panel.add(topPanel, "growx"); - - impl = new JTree(); - treeView = new JScrollPane(impl); - panel.add(treeView, "grow"); - - impl.setRootVisible(false); - impl.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - impl.setExpandsSelectedPaths(true); - - impl.addMouseListener( - new MouseAdapter() { - - @Override - public void mousePressed(MouseEvent e) { - showPopup(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - showPopup(e); - } - - private void showPopup(MouseEvent e) { - if (e.isPopupTrigger()) { - // select row - Point p = e.getPoint(); - TreePath treePath = impl.getPathForLocation(p.x, p.y); - if (treePath != null) { - TreeSelectionModel model = impl.getSelectionModel(); - model.setSelectionPath(treePath); - } - // show popup menu - createPopupMenu().show(e.getComponent(), e.getX(), e.getY()); - } - } - } - ); - - impl.addKeyListener(new KeyAdapter() { - protected static final int ENTER_CODE = 10; - - @Override - public void keyPressed(KeyEvent e) { - if (ENTER_CODE == e.getKeyCode() && - e.getComponent() == DesktopTree.this.getComponent()) { - if (enterPressAction != null) { - enterPressAction.actionPerform(DesktopTree.this); - } else { - handleClickAction(); - } - } - } - }); - } - - protected void handleClickAction() { - Action action = getItemClickAction(); - if (action == null) { - action = getEnterPressAction(); - if (action == null) { - action = getAction("edit"); - if (action == null) { - action = getAction("view"); - } - } - } - - if (action != null && action.isEnabled()) { - Window window = ComponentsHelper.getWindowImplementation(DesktopTree.this); - if (window instanceof Window.Wrapper) { - window = ((Window.Wrapper) window).getWrappedWindow(); - } - - if (!(window instanceof Window.Lookup)) { - action.actionPerform(DesktopTree.this); - } else { - Window.Lookup lookup = (Window.Lookup) window; - - com.haulmont.cuba.gui.components.Component lookupComponent = lookup.getLookupComponent(); - if (lookupComponent != this) - action.actionPerform(DesktopTree.this); - else if (action.getId().equals(WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID)) { - action.actionPerform(DesktopTree.this); - } - } - } - } - - @Override - public void setLookupSelectHandler(Runnable selectHandler) { - impl.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { - int rowForLocation = impl.getRowForLocation(e.getX(), e.getY()); - TreePath pathForLocation = impl.getPathForRow(rowForLocation); - if (pathForLocation != null) { - CollectionDatasource treeCds = getDatasource(); - if (treeCds != null) { - TreeModelAdapter.Node treeItem = - (TreeModelAdapter.Node) pathForLocation.getLastPathComponent(); - if (treeItem != null) { - treeCds.setItem(treeItem.getEntity()); - selectHandler.run(); - } - } - } - } - } - }); - } - - @Override - public Collection getLookupSelectedItems() { - return getSelected(); - } - - @Override - public JComponent getComposition() { - return panel; - } - - @Override - protected void updateEnabled() { - super.updateEnabled(); - - impl.setEnabled(isEnabledWithParent()); - } - - @Override - public void expandTree() { - if (model == null) { - return; - } - - if (!model.isLeaf(model.getRoot())) { - recursiveExpand(model.getRoot()); - } - } - - @Override - public ButtonsPanel getButtonsPanel() { - return buttonsPanel; - } - - @Override - public void setButtonsPanel(ButtonsPanel panel) { - if (buttonsPanel != null && topPanel != null) { - topPanel.remove(DesktopComponentsHelper.unwrap(buttonsPanel)); - buttonsPanel.setParent(null); - } - buttonsPanel = panel; - if (panel != null) { - if (panel.getParent() != null && panel.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - topPanel.add(DesktopComponentsHelper.unwrap(panel), BorderLayout.LINE_START); - topPanel.setVisible(true); - panel.setParent(this); - } - } - - private void recursiveExpand(Object node) { - impl.expandPath(model.getTreePath(node)); - for (int i = 0; i < model.getChildCount(node); i++) { - Object child = model.getChild(node, i); - if (!model.isLeaf(child)) { - impl.expandPath(model.getTreePath(child)); - recursiveExpand(child); - } - } - } - - @Override - public void expand(Object itemId) { - if (datasource == null) { - return; - } - Entity item = datasource.getItem(itemId); - if (item == null) { - return; - } - - impl.expandPath(model.getTreePath(item)); - } - - @Override - public void collapseTree() { - if (model == null) { - return; - } - - impl.collapsePath(new TreePath(model.getRoot())); - } - - @Override - public void collapse(Object itemId) { - if (datasource == null) { - return; - } - Entity item = datasource.getItem(itemId); - if (item == null) { - return; - } - - impl.collapsePath(model.getTreePath(item)); - } - - @Override - public void expandUpTo(int level) { - if (getDatasource() == null) { - return; - } - - HierarchicalDatasource ds = getDatasource(); - java.util.List currentLevelItemIds = new ArrayList<>(ds.getRootItemIds()); - int i = 0; - while (i < level && !currentLevelItemIds.isEmpty()) { - for (Object itemId : new ArrayList<>(currentLevelItemIds)) { - Entity item = datasource.getItem(itemId); - impl.expandPath(model.getTreePath(item)); - - currentLevelItemIds.remove(itemId); - currentLevelItemIds.addAll(ds.getChildren(itemId)); - } - i++; - } - } - - @Override - public boolean isExpanded(Object itemId) { - if (datasource == null) { - return false; - } - Entity item = datasource.getItem(itemId); - if (item == null) { - return false; - } - - return impl.isExpanded(model.getTreePath(item)); - } - - @Override - public CaptionMode getCaptionMode() { - return captionMode; - } - - @Override - public void setCaptionMode(CaptionMode captionMode) { - if (this.captionMode != captionMode) { - this.captionMode = captionMode; - if (model != null) { - model.setCaptionMode(captionMode); - } - } - } - - @Override - public String getCaptionProperty() { - return captionProperty; - } - - @Override - public void setCaptionProperty(String captionProperty) { - if (!ObjectUtils.equals(this.captionProperty, captionProperty)) { - this.captionProperty = captionProperty; - if (model != null) { - model.setCaptionProperty(captionProperty); - - if (captionProperty != null) { - setCaptionMode(CaptionMode.PROPERTY); - } else { - setCaptionMode(CaptionMode.ITEM); - } - } - } - } - - @Override - public String getHierarchyProperty() { - return hierarchyProperty; - } - - @Override - public void setDatasource(HierarchicalDatasource datasource) { - this.datasource = datasource; - hierarchyProperty = datasource.getHierarchyPropertyName(); - - model = new TreeModelAdapter(datasource, captionMode, captionProperty, true); - impl.setModel(model); - - impl.addTreeSelectionListener(new SelectionListener()); - - UserSessionSource uss = AppBeans.get(UserSessionSource.NAME); - if (uss.getUserSession().isSpecificPermitted(ShowInfoAction.ACTION_PERMISSION)) { - ShowInfoAction action = (ShowInfoAction) getAction(ShowInfoAction.ACTION_ID); - if (action == null) { - action = new ShowInfoAction(); - addAction(action); - } - action.setDatasource(datasource); - } - - collectionChangeListener = e -> { - // #PL-2035, reload selection from ds - Set selectedItems = getSelected(); - if (selectedItems == null) { - selectedItems = Collections.emptySet(); - } - - Set newSelection = new HashSet<>(); - for (E entity : selectedItems) { - if (e.getDs().containsItem(entity.getId())) { - newSelection.add(entity); - } - } - - if (e.getDs().getState() == Datasource.State.VALID && e.getDs().getItem() != null) { - //noinspection unchecked - newSelection.add((E) e.getDs().getItem()); - } - - if (newSelection.isEmpty()) { - setSelected((Entity) null); - } else { - setSelected(newSelection); - } - }; - //noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - - collectionDsActionsNotifier = new CollectionDsActionsNotifier(this); - collectionDsActionsNotifier.bind(datasource); - - for (Action action : getActions()) { - action.refreshState(); - } - - assignAutoDebugId(); - } - - @Override - public void setItemClickAction(Action action) { - if (this.doubleClickAction != action) { - if (action != null) { - if (itemClickListener == null) { - itemClickListener = new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (isEditable()) { - if (e.getButton() == MouseEvent.BUTTON1 - && e.getClickCount() == 2 - && doubleClickAction != null) { - - int rowForLocation = impl.getRowForLocation(e.getX(), e.getY()); - TreePath pathForLocation = impl.getPathForRow(rowForLocation); - - if (pathForLocation != null) { - impl.setSelectionPath(pathForLocation); - - doubleClickAction.actionPerform(DesktopTree.this); - } - } - } - } - }; - impl.addMouseListener(itemClickListener); - impl.setToggleClickCount(0); - } - } else { - impl.removeMouseListener(itemClickListener); - impl.setToggleClickCount(2); - itemClickListener = null; - } - this.doubleClickAction = action; - } - } - - @Override - public Action getItemClickAction() { - return doubleClickAction; - } - - @Override - protected String getAlternativeDebugId() { - if (id != null) { - return id; - } - if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { - return getClass().getSimpleName() + "_" + datasource.getId(); - } - - return getClass().getSimpleName(); - } - - @Override - public boolean isMultiSelect() { - return impl.getSelectionModel().getSelectionMode() != TreeSelectionModel.SINGLE_TREE_SELECTION; - } - - @Override - public void setMultiSelect(boolean multiselect) { - int mode = multiselect ? - TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION : TreeSelectionModel.SINGLE_TREE_SELECTION; - impl.getSelectionModel().setSelectionMode(mode); - } - - @Override - public E getSingleSelected() { - Set selected = getSelected(); - return selected.isEmpty() ? null : selected.iterator().next(); - } - - @SuppressWarnings("unchecked") - @Override - public Set getSelected() { - Set selected = new HashSet<>(); - TreePath[] selectionPaths = impl.getSelectionPaths(); - if (selectionPaths != null) { - for (TreePath selectionPath : selectionPaths) { - Entity entity = model.getEntity(selectionPath.getLastPathComponent()); - if (entity != null) { - selected.add((E) entity); - } - } - } - return selected; - } - - @Override - public void setSelected(@Nullable Entity item) { - if (item != null) { - TreePath path = model.getTreePath(item); - impl.setSelectionPath(path); - } else { - impl.setSelectionPath(null); - } - } - - @Override - public void setSelected(Collection items) { - TreePath[] paths = new TreePath[items.size()]; - int i = 0; - for (Entity item : items) { - paths[i] = model.getTreePath(item); - } - impl.setSelectionPaths(paths); - } - - @Override - public HierarchicalDatasource getDatasource() { - return datasource; - } - - @Override - public void refresh() { - datasource.refresh(); - } - - @Override - public boolean isEditable() { - return editable; - } - - @Override - public void setEditable(boolean editable) { - this.editable = editable; - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - } - - @Override - public String getDescription() { - return impl.getToolTipText(); - } - - @Override - public void setDescription(String description) { - impl.setToolTipText(description); - } - - - @Override - protected void attachAction(Action action) { - if (action instanceof Action.HasTarget) { - ((Action.HasTarget) action).setTarget(this); - } - - super.attachAction(action); - } - - @Override - public void addLookupValueChangeListener(LookupSelectionChangeListener listener) { - if (!lookupSelectionChangeListeners.contains(listener)) { - lookupSelectionChangeListeners.add(listener); - } - } - - @Override - public void removeLookupValueChangeListener(LookupSelectionChangeListener listener) { - lookupSelectionChangeListeners.remove(listener); - } - - protected class SelectionListener implements TreeSelectionListener { - - @SuppressWarnings("unchecked") - @Override - public void valueChanged(TreeSelectionEvent e) { - Set selected = getSelected(); - if (selected.isEmpty()) { - Entity dsItem = datasource.getItemIfValid(); - datasource.setItem(null); - - if (dsItem == null) { - // in this case item change event will not be generated - refreshActionsState(); - } - } else { - Object item = selected.iterator().next(); - if (item != null) { - // reset selection and select new item - if (isMultiSelect()) { - datasource.setItem(null); - } - Entity newItem = selected.iterator().next(); - Entity dsItem = datasource.getItemIfValid(); - datasource.setItem(newItem); - - if (ObjectUtils.equals(dsItem, newItem)) { - // in this case item change event will not be generated - refreshActionsState(); - } - } else { - // todo remove this if branch, should not happen - Entity dsItem = datasource.getItemIfValid(); - datasource.setItem(null); - - if (dsItem == null) { - // in this case item change event will not be generated - refreshActionsState(); - } - } - } - - LookupSelectionChangeEvent selectionChangeEvent = new LookupSelectionChangeEvent(DesktopTree.this); - for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { - listener.lookupValueChanged(selectionChangeEvent); - } - } - } - - protected void refreshActionsState() { - for (Action action : getActions()) { - action.refreshState(); - } - } - - protected JPopupMenu createPopupMenu() { - JPopupMenu popup = new JPopupMenu(); - JMenuItem menuItem; - for (final com.haulmont.cuba.gui.components.Action action : actionList) { - if (StringUtils.isNotBlank(action.getCaption()) - && action.isVisible()) { - menuItem = new JMenuItem(action.getCaption()); - if (action.getIcon() != null) { - menuItem.setIcon(App.getInstance().getResources().getIcon(action.getIcon())); - } - if (action.getShortcutCombination() != null) { - menuItem.setAccelerator(DesktopComponentsHelper.convertKeyCombination(action.getShortcutCombination())); - } - menuItem.setEnabled(action.isEnabled()); - menuItem.addActionListener(e -> action.actionPerform(DesktopTree.this)); - popup.add(menuItem); - } - } - return popup; - } - - @Override - public void setStyleProvider(@Nullable StyleProvider styleProvider) { - // do nothing - } - - @Override - public void addStyleProvider(StyleProvider styleProvider) { - // do nothing - } - - @Override - public void removeStyleProvider(StyleProvider styleProvider) { - // do nothing - } - - @Override - public void setIconProvider(IconProvider iconProvider) { - // do nothing - } - - @Override - public void repaint() { - // do nothing - } - - @Override - public void setEnterPressAction(Action action) { - enterPressAction = action; - } - - @Override - public Action getEnterPressAction() { - return enterPressAction; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; +import com.haulmont.cuba.gui.ComponentsHelper; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.HierarchicalDatasource; +import com.haulmont.cuba.gui.data.impl.CollectionDsActionsNotifier; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.*; +import java.util.List; + +public class DesktopTree extends DesktopAbstractActionsHolderComponent + implements Tree, LookupComponent.LookupSelectionChangeNotifier { + + protected String hierarchyProperty; + protected HierarchicalDatasource, Object> datasource; + protected JScrollPane treeView; + protected CaptionMode captionMode = CaptionMode.ITEM; + protected String captionProperty; + protected TreeModelAdapter model; + + protected ButtonsPanel buttonsPanel; + protected MigLayout layout; + protected JPanel panel; + protected JPanel topPanel; + + protected Action doubleClickAction; + protected MouseAdapter itemClickListener; + protected Action enterPressAction; + protected boolean editable = true; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + protected CollectionDsActionsNotifier collectionDsActionsNotifier; + + protected List lookupSelectionChangeListeners = new ArrayList<>(); + + public DesktopTree() { + layout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); + panel = new JPanel(layout); + + topPanel = new JPanel(new BorderLayout()); + topPanel.setVisible(false); + panel.add(topPanel, "growx"); + + impl = new JTree(); + treeView = new JScrollPane(impl); + panel.add(treeView, "grow"); + + impl.setRootVisible(false); + impl.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + impl.setExpandsSelectedPaths(true); + + impl.addMouseListener( + new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + showPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + showPopup(e); + } + + private void showPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + // select row + Point p = e.getPoint(); + TreePath treePath = impl.getPathForLocation(p.x, p.y); + if (treePath != null) { + TreeSelectionModel model = impl.getSelectionModel(); + model.setSelectionPath(treePath); + } + // show popup menu + createPopupMenu().show(e.getComponent(), e.getX(), e.getY()); + } + } + } + ); + + impl.addKeyListener(new KeyAdapter() { + protected static final int ENTER_CODE = 10; + + @Override + public void keyPressed(KeyEvent e) { + if (ENTER_CODE == e.getKeyCode() && + e.getComponent() == DesktopTree.this.getComponent()) { + if (enterPressAction != null) { + enterPressAction.actionPerform(DesktopTree.this); + } else { + handleClickAction(); + } + } + } + }); + } + + protected void handleClickAction() { + Action action = getItemClickAction(); + if (action == null) { + action = getEnterPressAction(); + if (action == null) { + action = getAction("edit"); + if (action == null) { + action = getAction("view"); + } + } + } + + if (action != null && action.isEnabled()) { + Window window = ComponentsHelper.getWindowImplementation(DesktopTree.this); + if (window instanceof Window.Wrapper) { + window = ((Window.Wrapper) window).getWrappedWindow(); + } + + if (!(window instanceof Window.Lookup)) { + action.actionPerform(DesktopTree.this); + } else { + Window.Lookup lookup = (Window.Lookup) window; + + com.haulmont.cuba.gui.components.Component lookupComponent = lookup.getLookupComponent(); + if (lookupComponent != this) + action.actionPerform(DesktopTree.this); + else if (action.getId().equals(WindowDelegate.LOOKUP_ITEM_CLICK_ACTION_ID)) { + action.actionPerform(DesktopTree.this); + } + } + } + } + + @Override + public void setLookupSelectHandler(Runnable selectHandler) { + impl.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { + int rowForLocation = impl.getRowForLocation(e.getX(), e.getY()); + TreePath pathForLocation = impl.getPathForRow(rowForLocation); + if (pathForLocation != null) { + CollectionDatasource treeCds = getDatasource(); + if (treeCds != null) { + TreeModelAdapter.Node treeItem = + (TreeModelAdapter.Node) pathForLocation.getLastPathComponent(); + if (treeItem != null) { + treeCds.setItem(treeItem.getEntity()); + selectHandler.run(); + } + } + } + } + } + }); + } + + @Override + public Collection getLookupSelectedItems() { + return getSelected(); + } + + @Override + public JComponent getComposition() { + return panel; + } + + @Override + protected void updateEnabled() { + super.updateEnabled(); + + impl.setEnabled(isEnabledWithParent()); + } + + @Override + public void expandTree() { + if (model == null) { + return; + } + + if (!model.isLeaf(model.getRoot())) { + recursiveExpand(model.getRoot()); + } + } + + @Override + public ButtonsPanel getButtonsPanel() { + return buttonsPanel; + } + + @Override + public void setButtonsPanel(ButtonsPanel panel) { + if (buttonsPanel != null && topPanel != null) { + topPanel.remove(DesktopComponentsHelper.unwrap(buttonsPanel)); + buttonsPanel.setParent(null); + } + buttonsPanel = panel; + if (panel != null) { + if (panel.getParent() != null && panel.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + topPanel.add(DesktopComponentsHelper.unwrap(panel), BorderLayout.LINE_START); + topPanel.setVisible(true); + panel.setParent(this); + } + } + + private void recursiveExpand(Object node) { + impl.expandPath(model.getTreePath(node)); + for (int i = 0; i < model.getChildCount(node); i++) { + Object child = model.getChild(node, i); + if (!model.isLeaf(child)) { + impl.expandPath(model.getTreePath(child)); + recursiveExpand(child); + } + } + } + + @Override + public void expand(Object itemId) { + if (datasource == null) { + return; + } + Entity item = datasource.getItem(itemId); + if (item == null) { + return; + } + + impl.expandPath(model.getTreePath(item)); + } + + @Override + public void collapseTree() { + if (model == null) { + return; + } + + impl.collapsePath(new TreePath(model.getRoot())); + } + + @Override + public void collapse(Object itemId) { + if (datasource == null) { + return; + } + Entity item = datasource.getItem(itemId); + if (item == null) { + return; + } + + impl.collapsePath(model.getTreePath(item)); + } + + @Override + public void expandUpTo(int level) { + if (getDatasource() == null) { + return; + } + + HierarchicalDatasource ds = getDatasource(); + java.util.List currentLevelItemIds = new ArrayList<>(ds.getRootItemIds()); + int i = 0; + while (i < level && !currentLevelItemIds.isEmpty()) { + for (Object itemId : new ArrayList<>(currentLevelItemIds)) { + Entity item = datasource.getItem(itemId); + impl.expandPath(model.getTreePath(item)); + + currentLevelItemIds.remove(itemId); + currentLevelItemIds.addAll(ds.getChildren(itemId)); + } + i++; + } + } + + @Override + public boolean isExpanded(Object itemId) { + if (datasource == null) { + return false; + } + Entity item = datasource.getItem(itemId); + if (item == null) { + return false; + } + + return impl.isExpanded(model.getTreePath(item)); + } + + @Override + public CaptionMode getCaptionMode() { + return captionMode; + } + + @Override + public void setCaptionMode(CaptionMode captionMode) { + if (this.captionMode != captionMode) { + this.captionMode = captionMode; + if (model != null) { + model.setCaptionMode(captionMode); + } + } + } + + @Override + public String getCaptionProperty() { + return captionProperty; + } + + @Override + public void setCaptionProperty(String captionProperty) { + if (!ObjectUtils.equals(this.captionProperty, captionProperty)) { + this.captionProperty = captionProperty; + if (model != null) { + model.setCaptionProperty(captionProperty); + + if (captionProperty != null) { + setCaptionMode(CaptionMode.PROPERTY); + } else { + setCaptionMode(CaptionMode.ITEM); + } + } + } + } + + @Override + public String getHierarchyProperty() { + return hierarchyProperty; + } + + @Override + public void setDatasource(HierarchicalDatasource datasource) { + this.datasource = datasource; + hierarchyProperty = datasource.getHierarchyPropertyName(); + + model = new TreeModelAdapter(datasource, captionMode, captionProperty, true); + impl.setModel(model); + + impl.addTreeSelectionListener(new SelectionListener()); + + UserSessionSource uss = AppBeans.get(UserSessionSource.NAME); + if (uss.getUserSession().isSpecificPermitted(ShowInfoAction.ACTION_PERMISSION)) { + ShowInfoAction action = (ShowInfoAction) getAction(ShowInfoAction.ACTION_ID); + if (action == null) { + action = new ShowInfoAction(); + addAction(action); + } + action.setDatasource(datasource); + } + + collectionChangeListener = e -> { + // #PL-2035, reload selection from ds + Set selectedItems = getSelected(); + if (selectedItems == null) { + selectedItems = Collections.emptySet(); + } + + Set newSelection = new HashSet<>(); + for (E entity : selectedItems) { + if (e.getDs().containsItem(entity.getId())) { + newSelection.add(entity); + } + } + + if (e.getDs().getState() == Datasource.State.VALID && e.getDs().getItem() != null) { + //noinspection unchecked + newSelection.add((E) e.getDs().getItem()); + } + + if (newSelection.isEmpty()) { + setSelected((Entity) null); + } else { + setSelected(newSelection); + } + }; + //noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + + collectionDsActionsNotifier = new CollectionDsActionsNotifier(this); + collectionDsActionsNotifier.bind(datasource); + + for (Action action : getActions()) { + action.refreshState(); + } + + assignAutoDebugId(); + } + + @Override + public void setItemClickAction(Action action) { + if (this.doubleClickAction != action) { + if (action != null) { + if (itemClickListener == null) { + itemClickListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (isEditable()) { + if (e.getButton() == MouseEvent.BUTTON1 + && e.getClickCount() == 2 + && doubleClickAction != null) { + + int rowForLocation = impl.getRowForLocation(e.getX(), e.getY()); + TreePath pathForLocation = impl.getPathForRow(rowForLocation); + + if (pathForLocation != null) { + impl.setSelectionPath(pathForLocation); + + doubleClickAction.actionPerform(DesktopTree.this); + } + } + } + } + }; + impl.addMouseListener(itemClickListener); + impl.setToggleClickCount(0); + } + } else { + impl.removeMouseListener(itemClickListener); + impl.setToggleClickCount(2); + itemClickListener = null; + } + this.doubleClickAction = action; + } + } + + @Override + public Action getItemClickAction() { + return doubleClickAction; + } + + @Override + protected String getAlternativeDebugId() { + if (id != null) { + return id; + } + if (datasource != null && StringUtils.isNotEmpty(datasource.getId())) { + return getClass().getSimpleName() + "_" + datasource.getId(); + } + + return getClass().getSimpleName(); + } + + @Override + public boolean isMultiSelect() { + return impl.getSelectionModel().getSelectionMode() != TreeSelectionModel.SINGLE_TREE_SELECTION; + } + + @Override + public void setMultiSelect(boolean multiselect) { + int mode = multiselect ? + TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION : TreeSelectionModel.SINGLE_TREE_SELECTION; + impl.getSelectionModel().setSelectionMode(mode); + } + + @Override + public E getSingleSelected() { + Set selected = getSelected(); + return selected.isEmpty() ? null : selected.iterator().next(); + } + + @SuppressWarnings("unchecked") + @Override + public Set getSelected() { + Set selected = new HashSet<>(); + TreePath[] selectionPaths = impl.getSelectionPaths(); + if (selectionPaths != null) { + for (TreePath selectionPath : selectionPaths) { + Entity entity = model.getEntity(selectionPath.getLastPathComponent()); + if (entity != null) { + selected.add((E) entity); + } + } + } + return selected; + } + + @Override + public void setSelected(@Nullable Entity item) { + if (item != null) { + TreePath path = model.getTreePath(item); + impl.setSelectionPath(path); + } else { + impl.setSelectionPath(null); + } + } + + @Override + public void setSelected(Collection items) { + TreePath[] paths = new TreePath[items.size()]; + int i = 0; + for (Entity item : items) { + paths[i] = model.getTreePath(item); + } + impl.setSelectionPaths(paths); + } + + @Override + public HierarchicalDatasource getDatasource() { + return datasource; + } + + @Override + public void refresh() { + datasource.refresh(); + } + + @Override + public boolean isEditable() { + return editable; + } + + @Override + public void setEditable(boolean editable) { + this.editable = editable; + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + } + + @Override + public String getDescription() { + return impl.getToolTipText(); + } + + @Override + public void setDescription(String description) { + impl.setToolTipText(description); + } + + + @Override + protected void attachAction(Action action) { + if (action instanceof Action.HasTarget) { + ((Action.HasTarget) action).setTarget(this); + } + + super.attachAction(action); + } + + @Override + public void addLookupValueChangeListener(LookupSelectionChangeListener listener) { + if (!lookupSelectionChangeListeners.contains(listener)) { + lookupSelectionChangeListeners.add(listener); + } + } + + @Override + public void removeLookupValueChangeListener(LookupSelectionChangeListener listener) { + lookupSelectionChangeListeners.remove(listener); + } + + protected class SelectionListener implements TreeSelectionListener { + + @SuppressWarnings("unchecked") + @Override + public void valueChanged(TreeSelectionEvent e) { + Set selected = getSelected(); + if (selected.isEmpty()) { + Entity dsItem = datasource.getItemIfValid(); + datasource.setItem(null); + + if (dsItem == null) { + // in this case item change event will not be generated + refreshActionsState(); + } + } else { + Object item = selected.iterator().next(); + if (item != null) { + // reset selection and select new item + if (isMultiSelect()) { + datasource.setItem(null); + } + Entity newItem = selected.iterator().next(); + Entity dsItem = datasource.getItemIfValid(); + datasource.setItem(newItem); + + if (ObjectUtils.equals(dsItem, newItem)) { + // in this case item change event will not be generated + refreshActionsState(); + } + } else { + // todo remove this if branch, should not happen + Entity dsItem = datasource.getItemIfValid(); + datasource.setItem(null); + + if (dsItem == null) { + // in this case item change event will not be generated + refreshActionsState(); + } + } + } + + LookupSelectionChangeEvent selectionChangeEvent = new LookupSelectionChangeEvent(DesktopTree.this); + for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { + listener.lookupValueChanged(selectionChangeEvent); + } + } + } + + protected void refreshActionsState() { + for (Action action : getActions()) { + action.refreshState(); + } + } + + protected JPopupMenu createPopupMenu() { + JPopupMenu popup = new JPopupMenu(); + JMenuItem menuItem; + for (final com.haulmont.cuba.gui.components.Action action : actionList) { + if (StringUtils.isNotBlank(action.getCaption()) + && action.isVisible()) { + menuItem = new JMenuItem(action.getCaption()); + if (action.getIcon() != null) { + menuItem.setIcon(App.getInstance().getResources().getIcon(action.getIcon())); + } + if (action.getShortcutCombination() != null) { + menuItem.setAccelerator(DesktopComponentsHelper.convertKeyCombination(action.getShortcutCombination())); + } + menuItem.setEnabled(action.isEnabled()); + menuItem.addActionListener(e -> action.actionPerform(DesktopTree.this)); + popup.add(menuItem); + } + } + return popup; + } + + @Override + public void setStyleProvider(@Nullable StyleProvider styleProvider) { + // do nothing + } + + @Override + public void addStyleProvider(StyleProvider styleProvider) { + // do nothing + } + + @Override + public void removeStyleProvider(StyleProvider styleProvider) { + // do nothing + } + + @Override + public void setIconProvider(IconProvider iconProvider) { + // do nothing + } + + @Override + public void repaint() { + // do nothing + } + + @Override + public void setEnterPressAction(Action action) { + enterPressAction = action; + } + + @Override + public Action getEnterPressAction() { + return enterPressAction; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTreeTable.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTreeTable.java index b9660226c4..ae455ba8d8 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTreeTable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopTreeTable.java @@ -1,433 +1,433 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter; -import com.haulmont.cuba.desktop.sys.vcl.JXTreeTableExt; -import com.haulmont.cuba.gui.components.TreeTable; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.HierarchicalDatasource; -import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; -import org.jdesktop.swingx.JXTree; -import org.jdesktop.swingx.JXTreeTable; -import org.jdesktop.swingx.decorator.AbstractHighlighter; -import org.jdesktop.swingx.decorator.ComponentAdapter; - -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumnModel; -import javax.swing.table.TableModel; -import javax.swing.tree.TreePath; -import java.awt.*; -import java.util.*; - -public class DesktopTreeTable extends DesktopAbstractTable implements TreeTable { - - protected String hierarchyProperty; - - public DesktopTreeTable() { - impl = new JXTreeTableExt() { - @Override - public TableCellRenderer getCellRenderer(int row, int column) { - TableCellRenderer columnRenderer = DesktopTreeTable.this.getColumnRenderer(column); - if (columnRenderer != null) { - return columnRenderer; - } - - if (styleProviders != null) { - TableCellRenderer defaultRenderer = super.getCellRenderer(row, column); - return new StylingCellRenderer(defaultRenderer); - } else { - return super.getCellRenderer(row, column); - } - } - - @Override - public TableCellEditor getCellEditor(int row, int column) { - TableCellEditor cellEditor = getColumnEditor(column); - if (cellEditor != null) { - return cellEditor; - } - - return super.getCellEditor(row, column); - } - - @Override - public void setFont(Font font) { - super.setFont(font); - applyFont(this, font); - } - - @Override - public boolean isCellEditable(int row, int column) { - if (column < 0 || row < 0) { - return false; - } - - if (DesktopTreeTable.this.isCustomCellEditable(row, column)) { - return true; - } - - DesktopTreeTable treeTable = DesktopTreeTable.this; - Column editColumn = treeTable.getColumns().get(column); - return (treeTable.isEditable() && editColumn.isEditable()) - || tableModel.isGeneratedColumn(editColumn); - } - - /* Copies the JTable standard behaviour, that was overridden in JXTreeTable. - */ - @Override - public void setRowSorter(RowSorter sorter) { - setTableRowSorter(sorter); - } - - /** - * Default implementation uses row sorter to return rows count, - * but there is nonconformity in how RowSorterImpl and tree table wrapper counts rows. - * Absence of this method will lead to nontrivial NPE with obscure stack trace. - */ - @Override - public int getRowCount() { - if (datasource != null) { - CollectionDsHelper.autoRefreshInvalid(datasource, true); - } - - return getModel().getRowCount(); - } - - @Override - public void editingStopped(ChangeEvent e) { - TableCellEditor editor = getCellEditor(); - if (editor != null) { - Object value = editor.getCellEditorValue(); - DesktopTreeTable tableComponent = DesktopTreeTable.this; - Column editColumn = tableComponent.getColumns().get(editingColumn); - - if (!(editor instanceof DesktopAbstractTable.EditableColumnTableCellEditor)) { - if (tableComponent.isEditable() && editColumn.isEditable() && !tableModel.isGeneratedColumn(editColumn)) { - setValueAt(value, editingRow, editingColumn); - } - } - removeEditor(); - } - } - - @Override - protected void beforeDelayedStructureChange() { - ((com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter) tableModel).beforeDelayedStructureChange(); - } - - @Override - protected void afterDelayedStructureChange() { - ((com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter) tableModel).afterDelayedStructureChange(); - } - }; - - impl.addTreeExpansionListener(new TreeExpansionListener() { - @Override - public void treeExpanded(TreeExpansionEvent event) { - if (tableModel.hasGeneratedColumns()) - repaint(); - } - - @Override - public void treeCollapsed(TreeExpansionEvent event) { - if (tableModel.hasGeneratedColumns()) - repaint(); - } - }); - impl.setRootVisible(false); - impl.setColumnControlVisible(true); - - // apply alternate row color - impl.setHighlighters(new AbstractHighlighter() { - @Override - protected Component doHighlight(Component component, ComponentAdapter adapter) { - if (adapter.isHierarchical()) { - if (adapter.isSelected()) { - component.setBackground(impl.getSelectionBackground()); - component.setForeground(impl.getSelectionForeground()); - } else { - component.setForeground(impl.getForeground()); - Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); - if (adapter.row % 2 == 1) { - Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); - if (alternateColor != null) { - background = alternateColor; - } - } - component.setBackground(background); - } - } - return component; - } - }); - - initComponent(); - - tableSettings = new SwingXTableSettings(impl, columnsOrder); - } - - @Override - protected void initTableModel(CollectionDatasource datasource) { - tableModel = new TreeTableModelAdapter( - impl, - ((HierarchicalDatasource) datasource), - columnsOrder, - true - ); - impl.setTreeTableModel(((TreeTableModelAdapter) tableModel)); - } - - @Override - protected void initSelectionListener(final CollectionDatasource datasource) { - impl.getTreeSelectionModel().addTreeSelectionListener( - new TreeSelectionListener() { - @Override - @SuppressWarnings("unchecked") - public void valueChanged(TreeSelectionEvent e) { - if (isAdjusting || datasource == null) { - return; - } - selectedItems = getSelected(); - - // noinspection unchecked - if (selectedItems.isEmpty()) { - datasource.setItem(null); - } else { - // reset selection and select new item - if (isMultiSelect()) - datasource.setItem(null); - datasource.setItem(selectedItems.iterator().next()); - } - - LookupSelectionChangeEvent selectionChangeEvent = - new LookupSelectionChangeEvent(DesktopTreeTable.this); - for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { - listener.lookupValueChanged(selectionChangeEvent); - } - } - } - ); - } - - @Override - public String getHierarchyProperty() { - return hierarchyProperty; - } - - @Override - public void setDatasource(HierarchicalDatasource datasource) { - setDatasource((CollectionDatasource) datasource); - this.hierarchyProperty = datasource.getHierarchyPropertyName(); - } - - @Override - public void expandAll() { - TreeTableModelAdapter model = (TreeTableModelAdapter) tableModel; - if (!model.isLeaf(model.getRoot())) { - recursiveExpand(model.getRoot()); - } - readjustColumns(); - } - - private void recursiveExpand(Object node) { - TreeTableModelAdapter model = (TreeTableModelAdapter) tableModel; - impl.expandPath(model.getTreePath(node)); - for (int i = 0; i < model.getChildCount(node); i++) { - Object child = model.getChild(node, i); - if (!model.isLeaf(child)) { - impl.expandPath(model.getTreePath(child)); - recursiveExpand(child); - } - } - } - - @Override - public void expand(Object itemId) { - if (datasource == null) - return; - Entity item = datasource.getItem(itemId); - if (item == null) - return; - - impl.expandPath(((TreeTableModelAdapter) tableModel).getTreePath(item)); - } - - @Override - public void collapseAll() { - if (tableModel == null) - return; - - impl.collapsePath(new TreePath(((TreeTableModelAdapter) tableModel).getRoot())); - readjustColumns(); - } - - @Override - public void collapse(Object itemId) { - if (datasource == null) - return; - Entity item = datasource.getItem(itemId); - if (item == null) - return; - - impl.collapsePath(((TreeTableModelAdapter) tableModel).getTreePath(item)); - } - - @Override - public void expandUpTo(int level) { - if (getDatasource() == null) { - return; - } - - HierarchicalDatasource ds = getDatasource(); - java.util.List currentLevelItemIds = new ArrayList<>(ds.getRootItemIds()); - int i = 0; - while (i < level && !currentLevelItemIds.isEmpty()) { - for (Object itemId : new ArrayList<>(currentLevelItemIds)) { - Entity item = datasource.getItem(itemId); - impl.expandPath(((TreeTableModelAdapter) tableModel).getTreePath(item)); - - currentLevelItemIds.remove(itemId); - currentLevelItemIds.addAll(ds.getChildren(itemId)); - } - i++; - } - } - - @Override - public int getLevel(Object itemId) { - Object parentId; - if ((parentId = ((HierarchicalDatasource) datasource).getParent(itemId)) == null) { - return 0; - } - return getLevel(parentId) + 1; - } - - @Override - public boolean isExpanded(Object itemId) { - if (datasource == null) - return false; - Entity item = datasource.getItem(itemId); - if (item == null) - return false; - - return impl.isExpanded(((TreeTableModelAdapter) tableModel).getTreePath(item)); - } - - @SuppressWarnings("unchecked") - @Override - public Set getSelected() { - Set selected = new HashSet<>(); - TreePath[] selectionPaths = impl.getTreeSelectionModel().getSelectionPaths(); - if (selectionPaths != null) { - for (TreePath path : selectionPaths) { - Entity entity = ((TreeTableModelAdapter) tableModel).getEntity(path.getLastPathComponent()); - if (entity != null) - selected.add((E) entity); - } - } - return selected; - } - - @Override - public void setSelected(E item) { - if (item != null) { - setSelected(Collections.singleton(item)); - } else { - setSelected(Collections.emptySet()); - } - } - - @Override - public void setSelected(Collection items) { - if (items == null) { - items = Collections.emptySet(); - } - for (Entity item : items) { - // noinspection unchecked - if (!datasource.containsItem(item.getId())) { - throw new IllegalStateException("Datasource does not contain specified item: " + item.getId()); - } - } - impl.clearSelection(); - if (!items.isEmpty()) { - for (Entity item : items) { - TreePath treePath = ((TreeTableModelAdapter) tableModel).getTreePath(item); - impl.getTreeSelectionModel().addSelectionPath(treePath); - } - } - } - - @Override - public void packRows() { - if (!contentRepaintEnabled) - return; - - impl.setRowHeight(defaultRowHeight); - } - - @Override - protected void applyFont(JTable table, Font font) { - JXTreeTable treeTable = (JXTreeTable) table; - if (treeTable.getModel() != null && impl != null) { - int hierarchicalColumn = treeTable.getHierarchicalColumn(); - TableCellRenderer cellRenderer = treeTable.getCellRenderer(0, hierarchicalColumn); - if (cellRenderer instanceof DesktopAbstractTable.StylingCellRenderer) { - cellRenderer = ((DesktopAbstractTable.StylingCellRenderer) cellRenderer).getDelegate(); - } - if (cellRenderer instanceof JXTree) { - // default JXTreeTable renderer for hierarchical column is JXTree - ((JXTree) cellRenderer).setFont(font); - } - } - super.applyFont(table, font); - } - - @Override - public void setSortable(boolean sortable) { - super.setSortable(sortable); - impl.setSortable(sortable); - } - - @Override - public HierarchicalDatasource getDatasource() { - return (HierarchicalDatasource) super.getDatasource(); - } - - @Override - public void addGeneratedColumn(String columnId, ColumnGenerator generator, - Class componentClass) { - if (columnId == null) - throw new IllegalArgumentException("columnId is null"); - if (generator == null) - throw new IllegalArgumentException("generator is null"); - - Column col = getColumn(columnId); - - TableColumnModel columnModel = impl.getColumnModel(); - int columnIndex = columnModel.getColumnIndex(col); - if (columnIndex == 0) - throw new UnsupportedOperationException("Unable to add cell renderer for hierarchical column in TreeTable"); - - addGeneratedColumnInternal(columnId, generator, componentClass); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter; +import com.haulmont.cuba.desktop.sys.vcl.JXTreeTableExt; +import com.haulmont.cuba.gui.components.TreeTable; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.HierarchicalDatasource; +import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; +import org.jdesktop.swingx.JXTree; +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.decorator.AbstractHighlighter; +import org.jdesktop.swingx.decorator.ComponentAdapter; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.util.*; + +public class DesktopTreeTable extends DesktopAbstractTable implements TreeTable { + + protected String hierarchyProperty; + + public DesktopTreeTable() { + impl = new JXTreeTableExt() { + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + TableCellRenderer columnRenderer = DesktopTreeTable.this.getColumnRenderer(column); + if (columnRenderer != null) { + return columnRenderer; + } + + if (styleProviders != null) { + TableCellRenderer defaultRenderer = super.getCellRenderer(row, column); + return new StylingCellRenderer(defaultRenderer); + } else { + return super.getCellRenderer(row, column); + } + } + + @Override + public TableCellEditor getCellEditor(int row, int column) { + TableCellEditor cellEditor = getColumnEditor(column); + if (cellEditor != null) { + return cellEditor; + } + + return super.getCellEditor(row, column); + } + + @Override + public void setFont(Font font) { + super.setFont(font); + applyFont(this, font); + } + + @Override + public boolean isCellEditable(int row, int column) { + if (column < 0 || row < 0) { + return false; + } + + if (DesktopTreeTable.this.isCustomCellEditable(row, column)) { + return true; + } + + DesktopTreeTable treeTable = DesktopTreeTable.this; + Column editColumn = treeTable.getColumns().get(column); + return (treeTable.isEditable() && editColumn.isEditable()) + || tableModel.isGeneratedColumn(editColumn); + } + + /* Copies the JTable standard behaviour, that was overridden in JXTreeTable. + */ + @Override + public void setRowSorter(RowSorter sorter) { + setTableRowSorter(sorter); + } + + /** + * Default implementation uses row sorter to return rows count, + * but there is nonconformity in how RowSorterImpl and tree table wrapper counts rows. + * Absence of this method will lead to nontrivial NPE with obscure stack trace. + */ + @Override + public int getRowCount() { + if (datasource != null) { + CollectionDsHelper.autoRefreshInvalid(datasource, true); + } + + return getModel().getRowCount(); + } + + @Override + public void editingStopped(ChangeEvent e) { + TableCellEditor editor = getCellEditor(); + if (editor != null) { + Object value = editor.getCellEditorValue(); + DesktopTreeTable tableComponent = DesktopTreeTable.this; + Column editColumn = tableComponent.getColumns().get(editingColumn); + + if (!(editor instanceof DesktopAbstractTable.EditableColumnTableCellEditor)) { + if (tableComponent.isEditable() && editColumn.isEditable() && !tableModel.isGeneratedColumn(editColumn)) { + setValueAt(value, editingRow, editingColumn); + } + } + removeEditor(); + } + } + + @Override + protected void beforeDelayedStructureChange() { + ((com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter) tableModel).beforeDelayedStructureChange(); + } + + @Override + protected void afterDelayedStructureChange() { + ((com.haulmont.cuba.desktop.gui.data.TreeTableModelAdapter) tableModel).afterDelayedStructureChange(); + } + }; + + impl.addTreeExpansionListener(new TreeExpansionListener() { + @Override + public void treeExpanded(TreeExpansionEvent event) { + if (tableModel.hasGeneratedColumns()) + repaint(); + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + if (tableModel.hasGeneratedColumns()) + repaint(); + } + }); + impl.setRootVisible(false); + impl.setColumnControlVisible(true); + + // apply alternate row color + impl.setHighlighters(new AbstractHighlighter() { + @Override + protected Component doHighlight(Component component, ComponentAdapter adapter) { + if (adapter.isHierarchical()) { + if (adapter.isSelected()) { + component.setBackground(impl.getSelectionBackground()); + component.setForeground(impl.getSelectionForeground()); + } else { + component.setForeground(impl.getForeground()); + Color background = UIManager.getDefaults().getColor("Table:\"Table.cellRenderer\".background"); + if (adapter.row % 2 == 1) { + Color alternateColor = UIManager.getDefaults().getColor("Table.alternateRowColor"); + if (alternateColor != null) { + background = alternateColor; + } + } + component.setBackground(background); + } + } + return component; + } + }); + + initComponent(); + + tableSettings = new SwingXTableSettings(impl, columnsOrder); + } + + @Override + protected void initTableModel(CollectionDatasource datasource) { + tableModel = new TreeTableModelAdapter( + impl, + ((HierarchicalDatasource) datasource), + columnsOrder, + true + ); + impl.setTreeTableModel(((TreeTableModelAdapter) tableModel)); + } + + @Override + protected void initSelectionListener(final CollectionDatasource datasource) { + impl.getTreeSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() { + @Override + @SuppressWarnings("unchecked") + public void valueChanged(TreeSelectionEvent e) { + if (isAdjusting || datasource == null) { + return; + } + selectedItems = getSelected(); + + // noinspection unchecked + if (selectedItems.isEmpty()) { + datasource.setItem(null); + } else { + // reset selection and select new item + if (isMultiSelect()) + datasource.setItem(null); + datasource.setItem(selectedItems.iterator().next()); + } + + LookupSelectionChangeEvent selectionChangeEvent = + new LookupSelectionChangeEvent(DesktopTreeTable.this); + for (LookupSelectionChangeListener listener : lookupSelectionChangeListeners) { + listener.lookupValueChanged(selectionChangeEvent); + } + } + } + ); + } + + @Override + public String getHierarchyProperty() { + return hierarchyProperty; + } + + @Override + public void setDatasource(HierarchicalDatasource datasource) { + setDatasource((CollectionDatasource) datasource); + this.hierarchyProperty = datasource.getHierarchyPropertyName(); + } + + @Override + public void expandAll() { + TreeTableModelAdapter model = (TreeTableModelAdapter) tableModel; + if (!model.isLeaf(model.getRoot())) { + recursiveExpand(model.getRoot()); + } + readjustColumns(); + } + + private void recursiveExpand(Object node) { + TreeTableModelAdapter model = (TreeTableModelAdapter) tableModel; + impl.expandPath(model.getTreePath(node)); + for (int i = 0; i < model.getChildCount(node); i++) { + Object child = model.getChild(node, i); + if (!model.isLeaf(child)) { + impl.expandPath(model.getTreePath(child)); + recursiveExpand(child); + } + } + } + + @Override + public void expand(Object itemId) { + if (datasource == null) + return; + Entity item = datasource.getItem(itemId); + if (item == null) + return; + + impl.expandPath(((TreeTableModelAdapter) tableModel).getTreePath(item)); + } + + @Override + public void collapseAll() { + if (tableModel == null) + return; + + impl.collapsePath(new TreePath(((TreeTableModelAdapter) tableModel).getRoot())); + readjustColumns(); + } + + @Override + public void collapse(Object itemId) { + if (datasource == null) + return; + Entity item = datasource.getItem(itemId); + if (item == null) + return; + + impl.collapsePath(((TreeTableModelAdapter) tableModel).getTreePath(item)); + } + + @Override + public void expandUpTo(int level) { + if (getDatasource() == null) { + return; + } + + HierarchicalDatasource ds = getDatasource(); + java.util.List currentLevelItemIds = new ArrayList<>(ds.getRootItemIds()); + int i = 0; + while (i < level && !currentLevelItemIds.isEmpty()) { + for (Object itemId : new ArrayList<>(currentLevelItemIds)) { + Entity item = datasource.getItem(itemId); + impl.expandPath(((TreeTableModelAdapter) tableModel).getTreePath(item)); + + currentLevelItemIds.remove(itemId); + currentLevelItemIds.addAll(ds.getChildren(itemId)); + } + i++; + } + } + + @Override + public int getLevel(Object itemId) { + Object parentId; + if ((parentId = ((HierarchicalDatasource) datasource).getParent(itemId)) == null) { + return 0; + } + return getLevel(parentId) + 1; + } + + @Override + public boolean isExpanded(Object itemId) { + if (datasource == null) + return false; + Entity item = datasource.getItem(itemId); + if (item == null) + return false; + + return impl.isExpanded(((TreeTableModelAdapter) tableModel).getTreePath(item)); + } + + @SuppressWarnings("unchecked") + @Override + public Set getSelected() { + Set selected = new HashSet<>(); + TreePath[] selectionPaths = impl.getTreeSelectionModel().getSelectionPaths(); + if (selectionPaths != null) { + for (TreePath path : selectionPaths) { + Entity entity = ((TreeTableModelAdapter) tableModel).getEntity(path.getLastPathComponent()); + if (entity != null) + selected.add((E) entity); + } + } + return selected; + } + + @Override + public void setSelected(E item) { + if (item != null) { + setSelected(Collections.singleton(item)); + } else { + setSelected(Collections.emptySet()); + } + } + + @Override + public void setSelected(Collection items) { + if (items == null) { + items = Collections.emptySet(); + } + for (Entity item : items) { + // noinspection unchecked + if (!datasource.containsItem(item.getId())) { + throw new IllegalStateException("Datasource does not contain specified item: " + item.getId()); + } + } + impl.clearSelection(); + if (!items.isEmpty()) { + for (Entity item : items) { + TreePath treePath = ((TreeTableModelAdapter) tableModel).getTreePath(item); + impl.getTreeSelectionModel().addSelectionPath(treePath); + } + } + } + + @Override + public void packRows() { + if (!contentRepaintEnabled) + return; + + impl.setRowHeight(defaultRowHeight); + } + + @Override + protected void applyFont(JTable table, Font font) { + JXTreeTable treeTable = (JXTreeTable) table; + if (treeTable.getModel() != null && impl != null) { + int hierarchicalColumn = treeTable.getHierarchicalColumn(); + TableCellRenderer cellRenderer = treeTable.getCellRenderer(0, hierarchicalColumn); + if (cellRenderer instanceof DesktopAbstractTable.StylingCellRenderer) { + cellRenderer = ((DesktopAbstractTable.StylingCellRenderer) cellRenderer).getDelegate(); + } + if (cellRenderer instanceof JXTree) { + // default JXTreeTable renderer for hierarchical column is JXTree + ((JXTree) cellRenderer).setFont(font); + } + } + super.applyFont(table, font); + } + + @Override + public void setSortable(boolean sortable) { + super.setSortable(sortable); + impl.setSortable(sortable); + } + + @Override + public HierarchicalDatasource getDatasource() { + return (HierarchicalDatasource) super.getDatasource(); + } + + @Override + public void addGeneratedColumn(String columnId, ColumnGenerator generator, + Class componentClass) { + if (columnId == null) + throw new IllegalArgumentException("columnId is null"); + if (generator == null) + throw new IllegalArgumentException("generator is null"); + + Column col = getColumn(columnId); + + TableColumnModel columnModel = impl.getColumnModel(); + int columnIndex = columnModel.getColumnIndex(col); + if (columnIndex == 0) + throw new UnsupportedOperationException("Unable to add cell renderer for hierarchical column in TreeTable"); + + addGeneratedColumnInternal(columnId, generator, componentClass); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopVBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopVBox.java index 835652e1f8..86698c7805 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopVBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopVBox.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.gui.components.VBoxLayout; - -public class DesktopVBox extends DesktopAbstractBox implements AutoExpanding, VBoxLayout { - - public DesktopVBox() { - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - setWidth("100%"); // compatibility with web - } - - @Override - public boolean expandsWidth() { - return true; - } - - @Override - public boolean expandsHeight() { - return false; - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - layoutAdapter.setExpandLayout(!heightSize.isOwnSize()); - } - - @Override - public ExpandDirection getExpandDirection() { - return ExpandDirection.VERTICAL; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.gui.components.VBoxLayout; + +public class DesktopVBox extends DesktopAbstractBox implements AutoExpanding, VBoxLayout { + + public DesktopVBox() { + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + setWidth("100%"); // compatibility with web + } + + @Override + public boolean expandsWidth() { + return true; + } + + @Override + public boolean expandsHeight() { + return false; + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + layoutAdapter.setExpandLayout(!heightSize.isOwnSize()); + } + + @Override + public ExpandDirection getExpandDirection() { + return ExpandDirection.VERTICAL; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWidgetsTree.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWidgetsTree.java index 81109262f8..e19849a2be 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWidgetsTree.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWidgetsTree.java @@ -1,118 +1,118 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.WidgetsTree; - -import javax.swing.*; -import javax.swing.event.CellEditorListener; -import javax.swing.tree.TreeCellEditor; -import javax.swing.tree.TreeCellRenderer; -import java.util.EventObject; - -public class DesktopWidgetsTree - extends DesktopTree - implements WidgetsTree { - - @Override - public void setWidgetBuilder(final WidgetBuilder widgetBuilder) { - if (widgetBuilder == null) - return; - - impl.setEditable(true); - impl.setCellRenderer(new CellRenderer(widgetBuilder)); - impl.setCellEditor(new CellEditor(widgetBuilder)); - } - - private class CellEditor implements TreeCellEditor { - - private WidgetBuilder widgetBuilder; - - private CellEditor(WidgetBuilder widgetBuilder) { - this.widgetBuilder = widgetBuilder; - } - - @Override - public java.awt.Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, - boolean expanded, boolean leaf, int row) { - Component component = widgetBuilder.build( - datasource, - ((TreeModelAdapter.Node) value).getEntity().getId(), - leaf - ); - return DesktopComponentsHelper.getComposition(component); - } - - @Override - public Object getCellEditorValue() { - return null; - } - - @Override - public boolean isCellEditable(EventObject anEvent) { - return true; - } - - @Override - public boolean shouldSelectCell(EventObject anEvent) { - return true; - } - - @Override - public boolean stopCellEditing() { - return true; - } - - @Override - public void cancelCellEditing() { - } - - @Override - public void addCellEditorListener(CellEditorListener l) { - } - - @Override - public void removeCellEditorListener(CellEditorListener l) { - } - } - - private class CellRenderer implements TreeCellRenderer { - - private WidgetBuilder widgetBuilder; - - private CellRenderer(WidgetBuilder widgetBuilder) { - this.widgetBuilder = widgetBuilder; - } - - @Override - public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, - boolean selected, boolean expanded, - boolean leaf, int row, boolean hasFocus) - { - Component component = widgetBuilder.build( - datasource, - ((TreeModelAdapter.Node) value).getEntity().getId(), - leaf - ); - return DesktopComponentsHelper.getComposition(component); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.gui.data.TreeModelAdapter; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.WidgetsTree; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import java.util.EventObject; + +public class DesktopWidgetsTree + extends DesktopTree + implements WidgetsTree { + + @Override + public void setWidgetBuilder(final WidgetBuilder widgetBuilder) { + if (widgetBuilder == null) + return; + + impl.setEditable(true); + impl.setCellRenderer(new CellRenderer(widgetBuilder)); + impl.setCellEditor(new CellEditor(widgetBuilder)); + } + + private class CellEditor implements TreeCellEditor { + + private WidgetBuilder widgetBuilder; + + private CellEditor(WidgetBuilder widgetBuilder) { + this.widgetBuilder = widgetBuilder; + } + + @Override + public java.awt.Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, + boolean expanded, boolean leaf, int row) { + Component component = widgetBuilder.build( + datasource, + ((TreeModelAdapter.Node) value).getEntity().getId(), + leaf + ); + return DesktopComponentsHelper.getComposition(component); + } + + @Override + public Object getCellEditorValue() { + return null; + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + return true; + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) { + return true; + } + + @Override + public boolean stopCellEditing() { + return true; + } + + @Override + public void cancelCellEditing() { + } + + @Override + public void addCellEditorListener(CellEditorListener l) { + } + + @Override + public void removeCellEditorListener(CellEditorListener l) { + } + } + + private class CellRenderer implements TreeCellRenderer { + + private WidgetBuilder widgetBuilder; + + private CellRenderer(WidgetBuilder widgetBuilder) { + this.widgetBuilder = widgetBuilder; + } + + @Override + public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, + boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) + { + Component component = widgetBuilder.build( + datasource, + ((TreeModelAdapter.Node) value).getEntity().getId(), + leaf + ); + return DesktopComponentsHelper.getComposition(component); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWindow.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWindow.java index 31810b1ba7..b20432fc99 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWindow.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/DesktopWindow.java @@ -1,2003 +1,2003 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.google.common.collect.Iterables; -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.bali.events.EventRouter; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.desktop.gui.data.ComponentSize; -import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; -import com.haulmont.cuba.desktop.sys.DesktopWindowManager; -import com.haulmont.cuba.desktop.sys.DialogWindow; -import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; -import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; -import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; -import com.haulmont.cuba.gui.*; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Action.Status; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.DialogAction.Type; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.LookupComponent.LookupSelectionChangeNotifier; -import com.haulmont.cuba.gui.components.Timer; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.components.actions.BaseAction; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.DsContext; -import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import com.haulmont.cuba.gui.settings.Settings; -import net.miginfocom.layout.CC; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.util.*; -import java.util.List; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -public class DesktopWindow implements Window, Component.Disposable, - Component.Wrapper, Component.HasXmlDescriptor, Component.SecuredActionsHolder, WrappedWindow, DesktopContainer { - - protected static final Logger log = LoggerFactory.getLogger(DesktopWindow.class); - protected Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - - protected boolean disposed = false; - protected boolean responsive = false; - - protected BoxLayoutAdapter layoutAdapter; - protected JPanel panel; - - protected String id; - - protected Map componentByIds = new HashMap<>(); - protected Collection ownComponents = new LinkedHashSet<>(); - - protected Map allComponents = new HashMap<>(); - - protected DsContext dsContext; - protected WindowContext context; - protected String messagePack; - protected String focusComponentId; - protected Element xmlDescriptor; - protected String caption; - protected String description; - protected Component expandedComponent; - protected Map captions = new HashMap<>(); - protected Map> wrappers = new HashMap<>(); - - protected WindowDelegate delegate; - - protected DesktopFrameActionsHolder actionsHolder; - protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); - - protected List listeners = new ArrayList<>(); - - protected boolean forceClose; - protected Runnable doAfterClose; - - protected List timers = new ArrayList<>(); - - protected DesktopWindowManager windowManager; - - protected Configuration configuration = AppBeans.get(Configuration.NAME); - protected Messages messages = AppBeans.get(Messages.NAME); - - protected ComponentSize widthSize; - protected ComponentSize heightSize; - - protected boolean scheduledRepaint = false; - protected DialogOptions dialogOptions = new DesktopDialogOptions(); - protected String icon; - protected List styles; - - private EventRouter eventRouter; - protected ContentSwitchMode contentSwitchMode = ContentSwitchMode.DEFAULT; - - protected boolean isAttachedToRoot = false; - - public DesktopWindow() { - initLayout(); - delegate = createDelegate(); - actionsHolder = new DesktopFrameActionsHolder(this, panel); - - setWidth("100%"); - - panel.addAncestorListener(new AncestorListener() { - @Override - public void ancestorAdded(AncestorEvent event) { - SwingUtilities.invokeLater(() -> { - if (!isAttachedToRoot) { - if (SwingUtilities.getRoot(event.getComponent()) != null) { - enableEventListeners(); - isAttachedToRoot = true; - } - } - }); - } - - @Override - public void ancestorRemoved(AncestorEvent event) { - SwingUtilities.invokeLater(() -> { - if (isAttachedToRoot) { - if (SwingUtilities.getRoot(event.getComponent()) == null) { - disableEventListeners(); - isAttachedToRoot = false; - } - } - }); - } - - @Override - public void ancestorMoved(AncestorEvent event) { - // do nothing - } - }); - } - - protected void disableEventListeners() { - Frame wrapper = delegate.getWrapper(); - if (wrapper != null) { - List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); - if (uiEventListeners != null) { - for (ApplicationListener listener : uiEventListeners) { - UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); - multicaster.removeApplicationListener(listener); - } - } - } - } - - protected void enableEventListeners() { - Frame wrapper = delegate.getWrapper(); - if (wrapper != null) { - List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); - if (uiEventListeners != null) { - for (ApplicationListener listener : uiEventListeners) { - UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); - multicaster.addApplicationListener(listener); - } - } - } - } - - protected void initLayout() { - panel = new JPanel(); - layoutAdapter = BoxLayoutAdapter.create(panel); - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - layoutAdapter.setMargin(true); - } - - protected WindowDelegate createDelegate() { - return new WindowDelegate(this); - } - - @Nullable - protected DialogWindow asDialogWindow() { - java.awt.Component parent = getContainer(); - while (parent != null) { - if (parent instanceof DialogWindow) { - return (DialogWindow) parent; - } - - parent = parent.getParent(); - } - return null; - } - - @Override - public Element getXmlDescriptor() { - return xmlDescriptor; - } - - @Override - public void setXmlDescriptor(Element element) { - xmlDescriptor = element; - } - - @Override - public void addListener(CloseListener listener) { - addCloseListener(listener); - } - - @Override - public void removeListener(CloseListener listener) { - removeCloseListener(listener); - } - - @Override - public void addCloseListener(CloseListener listener) { - if (!listeners.contains(listener)) { - listeners.add(listener); - } - } - - @Override - public void removeCloseListener(CloseListener listener) { - listeners.remove(listener); - } - - @Override - public void addCloseWithCommitListener(CloseWithCommitListener listener) { - if (listeners == null) { - listeners = new LinkedList<>(); - } - - CloseListenerAdapter adapter = new CloseListenerAdapter(listener); - if (!listeners.contains(adapter)) { - listeners.add(adapter); - } - } - - @Override - public void removeCloseWithCommitListener(CloseWithCommitListener listener) { - if (listeners != null) { - listeners.remove(new CloseListenerAdapter(listener)); - } - } - - /** - * Use EventRouter for listeners instead of fields with listeners List. - * - * @return lazily initialized {@link EventRouter} instance. - * @see EventRouter - */ - protected EventRouter getEventRouter() { - if (eventRouter == null) { - eventRouter = new EventRouter(); - } - return eventRouter; - } - - @Override - public void addBeforeCloseWithShortcutListener(BeforeCloseWithShortcutListener listener) { - getEventRouter().addListener(BeforeCloseWithShortcutListener.class, listener); - } - - @Override - public void removeBeforeCloseWithShortcutListener(BeforeCloseWithShortcutListener listener) { - getEventRouter().removeListener(BeforeCloseWithShortcutListener.class, listener); - } - - public void fireBeforeCloseWithShortcut(BeforeCloseWithShortcutEvent event) { - getEventRouter().fireEvent(BeforeCloseWithShortcutListener.class, - BeforeCloseWithShortcutListener::beforeCloseWithShortcut, event); - } - - @Override - public void addBeforeCloseWithCloseButtonListener(BeforeCloseWithCloseButtonListener listener) { - getEventRouter().addListener(BeforeCloseWithCloseButtonListener.class, listener); - } - - @Override - public void removeBeforeCloseWithCloseButtonListener(BeforeCloseWithCloseButtonListener listener) { - getEventRouter().removeListener(BeforeCloseWithCloseButtonListener.class, listener); - } - - public void fireBeforeCloseWithCloseButton(BeforeCloseWithCloseButtonEvent event) { - getEventRouter().fireEvent(BeforeCloseWithCloseButtonListener.class, - BeforeCloseWithCloseButtonListener::beforeCloseWithCloseButton, event); - } - - @Override - public void applySettings(Settings settings) { - delegate.applySettings(settings); - } - - @Override - public void saveSettings() { - delegate.saveSettings(); - } - - @Override - public void deleteSettings() { - delegate.deleteSettings(); - } - - @Override - public void setFocusComponent(String componentId) { - this.focusComponentId = componentId; - if (componentId != null) { - Component component = getComponent(componentId); - if (component != null) { - component.requestFocus(); - } else { - log.error("Can't find focus component: " + componentId); - } - } else { - findAndFocusChildComponent(); - } - } - - public boolean findAndFocusChildComponent() { - final java.awt.Component focusComponent = getComponentToFocus(getContainer()); - if (focusComponent != null) { - SwingUtilities.invokeLater(() -> { - focusComponent.requestFocus(); - }); - - return true; - } - return false; - } - - protected java.awt.Component getComponentToFocus(java.awt.Container component) { - if (component.isFocusable() && component.isEnabled() - && DesktopComponentsHelper.isRecursivelyVisible(component)) { - if (component instanceof JComboBox - || component instanceof JCheckBox - || component instanceof JTable - || component instanceof JTree) { - return component; - } else if (component instanceof JTextComponent && ((JTextComponent) component).isEditable()) { - return component; - } - } - for (java.awt.Component child : component.getComponents()) { - if (child instanceof JTabbedPane) { - // #PL-3176 - // we don't know about selected tab after request - // may be focused component lays on not selected tab - continue; - } - if (child instanceof java.awt.Container) { - java.awt.Component result = getComponentToFocus((java.awt.Container) child); - if (result != null) { - return result; - } - } else { - return child; - } - } - return null; - } - - @Override - public String getFocusComponent() { - return focusComponentId; - } - - @Override - public Settings getSettings() { - return delegate.getSettings(); - } - - @Override - public boolean isResponsive() { - return responsive; - } - - @Override - public void setResponsive(boolean responsive) { - this.responsive = responsive; - } - - @Override - public boolean close(final String actionId) { - if (!forceClose) { - if (!delegate.preClose(actionId)) - return false; - } - - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - - if (!forceClose && isModified()) { - final Committable committable = (getWrapper() instanceof Committable) ? (Committable) getWrapper() : - (this instanceof Committable) ? (Committable) this : null; - if ((committable != null) && clientConfig.getUseSaveConfirmation()) { - windowManager.showOptionDialog( - messages.getMainMessage("closeUnsaved.caption"), - messages.getMainMessage("saveUnsaved"), - MessageType.WARNING, - new Action[]{ - new DialogAction(Type.OK, Status.PRIMARY) - .withCaption(messages.getMainMessage("closeUnsaved.save")) - .withHandler(event -> { - - committable.commitAndClose(); - }), - new BaseAction("discard") - .withIcon("icons/cancel.png") - .withCaption(messages.getMainMessage("closeUnsaved.discard")) - .withHandler(event -> { - - committable.close(actionId, true); - }), - new DialogAction(Type.CANCEL) - .withIcon(null) - .withHandler(event -> { - - doAfterClose = null; - }) - } - ); - } else { - windowManager.showOptionDialog( - messages.getMainMessage("closeUnsaved.caption"), - messages.getMainMessage("closeUnsaved"), - MessageType.WARNING, - new Action[]{ - new DialogAction(Type.YES).withHandler(event -> { - getWrapper().close(actionId, true); - }), - new DialogAction(Type.NO, Status.PRIMARY).withHandler(event -> { - doAfterClose = null; - }) - } - ); - } - return false; - } - - if (!clientConfig.getManualScreenSettingsSaving()) { - if (delegate.getWrapper() != null) { - delegate.getWrapper().saveSettings(); - } else { - saveSettings(); - } - } - - delegate.disposeComponents(); - - windowManager.close(this); - boolean res = onClose(actionId); - if (res && doAfterClose != null) { - doAfterClose.run(); - } - - stopTimers(); - - userActionsLog.trace("Window {} was closed", getId()); - - return res; - } - - public boolean isModified() { - return delegate.isModified(); - } - - private void stopTimers() { - // hard stop timers - for (Timer timer : timers) { - ((DesktopTimer)timer).disposeTimer(); - } - } - - @Override - public boolean close(String actionId, boolean force) { - forceClose = force; - return close(actionId); - } - - @Override - public void closeAndRun(String actionId, Runnable runnable) { - this.doAfterClose = runnable; - close(actionId); - } - - @Override - public void addTimer(Timer timer) { - if (timer instanceof DesktopTimer) { - timers.add(timer); - } - } - - @Override - public Timer getTimer(String id) { - if (id == null) - throw new IllegalArgumentException("id is null"); - - for (Timer timer : timers) { - if (id.equals(timer.getId())) - return timer; - } - return null; - } - - @Override - public void addAction(Action action) { - checkNotNullArgument(action, "action must be non null"); - - actionsHolder.addAction(action); - actionsPermissions.apply(action); - } - - @Override - public void addAction(Action action, int index) { - checkNotNullArgument(action, "action must be non null"); - - actionsHolder.addAction(action, index); - actionsPermissions.apply(action); - } - - @Override - public void removeAction(@Nullable Action action) { - actionsHolder.removeAction(action); - } - - @Override - public void removeAction(@Nullable String id) { - actionsHolder.removeAction(id); - } - - @Override - public void removeAllActions() { - actionsHolder.removeAllActions(); - } - - @Override - public Collection getActions() { - return actionsHolder.getActions(); - } - - @Override - @Nullable - public Action getAction(String id) { - return actionsHolder.getAction(id); - } - - @Nullable - protected JPanel asTabWindow() { - java.awt.Component parent = getContainer(); - while (parent != null) { - if (parent.getParent() instanceof JTabbedPaneExt) { - return (JPanel) parent; - } - parent = parent.getParent(); - } - - return null; - } - - @Nullable - protected JPanel asDetachedWindow() { - java.awt.Component parent = getContainer(); - while (parent != null) { - if (parent.getParent() != null && parent.getParent().getParent() != null) { - if (parent.getParent().getParent() instanceof JLayeredPane) { - return (JPanel) parent; - } - } - parent = parent.getParent(); - } - - return null; - } - - protected JTabbedPaneExt getJTabbedPaneExt() { - java.awt.Component parent = getContainer(); - while (parent != null) { - if (parent instanceof JTabbedPaneExt) { - return (JTabbedPaneExt) parent; - } - parent = parent.getParent(); - } - - return null; - } - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - dialogWindow.setTitle(caption); - } else { - JPanel tabWindow = asTabWindow(); - if (tabWindow != null) { - setTabCaptionAndDescription(tabWindow); - } else { - JPanel singleWindow = asDetachedWindow(); - if (singleWindow != null) { - ((TopLevelFrame) singleWindow.getParent().getParent().getParent().getParent()) - .setTitle(formatTabCaption(caption, description)); - windowManager.getBreadCrumbs(singleWindow).update(); - } - } - } - } - - @Override - public String getDescription() { - return description; - } - - @Override - public void setDescription(String description) { - this.description = description; - - JPanel tabWindow = asTabWindow(); - if (tabWindow != null) { - setTabCaptionAndDescription(tabWindow); - } else { - JPanel singleWindow = asDetachedWindow(); - if (singleWindow != null) { - ((TopLevelFrame) singleWindow.getParent().getParent().getParent().getParent()) - .setTitle(formatTabCaption(caption, description)); - } - } - } - - protected void setTabCaptionAndDescription(JComponent tabWindow) { - String formattedCaption = formatTabCaption(caption, description); - - JTabbedPaneExt jTabbedPaneExt = getJTabbedPaneExt(); - jTabbedPaneExt.setTitleAt(jTabbedPaneExt.getSelectedIndex(), formattedCaption); - windowManager.getBreadCrumbs(tabWindow).update(); - } - - protected String formatTabCaption(final String caption, final String description) { - DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); - String tabCaption = formatTabDescription(caption, description); - - int maxLength = desktopConfig.getMainTabCaptionLength(); - if (tabCaption.length() > maxLength) { - return tabCaption.substring(0, maxLength) + "..."; - } else { - return tabCaption; - } - } - - protected String formatTabDescription(final String caption, final String description) { - if (StringUtils.isNotEmpty(description)) { - return String.format("%s: %s", caption, description); - } else { - return caption; - } - } - - @Override - public WindowContext getContext() { - return context; - } - - @Override - public void setContext(FrameContext ctx) { - context = (WindowContext) ctx; - } - - @Override - public DsContext getDsContext() { - return dsContext; - } - - @Override - public void setDsContext(DsContext dsContext) { - this.dsContext = dsContext; - } - - @Override - public String getMessagesPack() { - return messagePack; - } - - @Override - public void setMessagesPack(String name) { - messagePack = name; - } - - @Override - public void registerComponent(Component component) { - if (component.getId() != null) { - allComponents.put(component.getId(), component); - } - } - - @Override - public void unregisterComponent(Component component) { - if (component.getId() != null) { - allComponents.remove(component.getId()); - } - } - - @Nullable - @Override - public Component getRegisteredComponent(String id) { - return allComponents.get(id); - } - - @Override - public boolean isValid() { - return delegate.isValid(); - } - - @Override - public void validate() throws ValidationException { - delegate.validate(); - } - - @Deprecated - @Override - public DialogParams getDialogParams() { - return getWindowManager().getDialogParams(); - } - - @Override - public Window openWindow(String windowAlias, WindowManager.OpenType openType, Map params) { - return delegate.openWindow(windowAlias, openType, params); - } - - @Override - public Window openWindow(String windowAlias, WindowManager.OpenType openType) { - return delegate.openWindow(windowAlias, openType); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType) { - return delegate.openEditor(item, openType); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params) { - return delegate.openEditor(item, openType, params); - } - - @Override - public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { - return delegate.openEditor(item, openType, params, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { - return delegate.openEditor(windowAlias, item, openType, params, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params) { - return delegate.openEditor(windowAlias, item, openType, params); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Datasource parentDs) { - return delegate.openEditor(windowAlias, item, openType, parentDs); - } - - @Override - public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType) { - return delegate.openEditor(windowAlias, item, openType); - } - - @Override - public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType) { - return delegate.openLookup(entityClass, handler, openType); - } - - @Override - public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { - return delegate.openLookup(entityClass, handler, openType, params); - } - - @Override - public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { - return delegate.openLookup(windowAlias, handler, openType, params); - } - - @Override - public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType) { - return delegate.openLookup(windowAlias, handler, openType); - } - - @Override - public Frame openFrame(Component parent, String windowAlias) { - return delegate.openFrame(parent, windowAlias); - } - - @Override - public Frame openFrame(Component parent, String windowAlias, Map params) { - return delegate.openFrame(parent, windowAlias, params); - } - - @Override - public DesktopWindowManager getWindowManager() { - return windowManager; - } - - @Override - public void setWindowManager(WindowManager windowManager) { - this.windowManager = (DesktopWindowManager) windowManager; - } - - @Override - public DialogOptions getDialogOptions() { - return dialogOptions; - } - - @Override - public void showMessageDialog(String title, String message, MessageType messageType) { - getWindowManager().showMessageDialog(title, message, messageType); - } - - @Override - public void showOptionDialog(String title, String message, MessageType messageType, Action[] actions) { - getWindowManager().showOptionDialog(title, message, messageType, actions); - } - - @Override - public void showOptionDialog(String title, String message, MessageType messageType, java.util.List actions) { - getWindowManager().showOptionDialog(title, message, messageType, actions.toArray(new Action[actions.size()])); - } - - @Override - public void showNotification(String caption) { - getWindowManager().showNotification(caption); - } - - @Override - public void showNotification(String caption, NotificationType type) { - getWindowManager().showNotification(caption, type); - } - - @Override - public void showNotification(String caption, String description, NotificationType type) { - getWindowManager().showNotification(caption, description, type); - } - - @Override - public void showWebPage(String url, @Nullable Map params) { - getWindowManager().showWebPage(url, params); - } - - @Override - public Frame getFrame() { - return this; - } - - @Override - public void setFrame(Frame frame) { - throw new UnsupportedOperationException(); - } - - @Override - public Component getParent() { - return null; - } - - @Override - public void setParent(Component parent) { - } - - @Override - public void expand(Component component, String height, String width) { - if (expandedComponent != null && expandedComponent instanceof DesktopComponent) { - ((DesktopComponent) expandedComponent).setExpanded(false); - } - - // only Y direction - if (StringUtils.isEmpty(height) || AUTO_SIZE.equals(height) || height.endsWith("%")) { - component.setHeight("100%"); - } - - JComponent expandingChild = DesktopComponentsHelper.getComposition(component); - - Pair wrapperInfo = wrappers.get(component); - if (wrapperInfo != null) { - expandingChild = wrapperInfo.getFirst(); - } - - layoutAdapter.expand(expandingChild, height, width); - - if (component instanceof DesktopComponent) { - ((DesktopComponent) component).setExpanded(true); - } - - expandedComponent = component; - } - - @Override - public void expand(Component component) { - expand(component, "", ""); - } - - @Override - public void resetExpanded() { - layoutAdapter.resetExpanded(); - expandedComponent = null; - } - - @Override - public boolean isExpanded(Component component) { - return expandedComponent == component; - } - - @Override - public ExpandDirection getExpandDirection() { - return ExpandDirection.VERTICAL; - } - - protected void requestRepaint() { - if (!scheduledRepaint) { - SwingUtilities.invokeLater(() -> { - getContainer().revalidate(); - getContainer().repaint(); - - java.awt.Container container = getContainer().getTopLevelAncestor(); - if (container instanceof DialogWindow) { - DialogWindow dialog = (DialogWindow) container; - if (!dialog.isResizable() && (getHeight() <= 0 || getWidth() <= 0)) { - dialog.pack(); - } - } - - scheduledRepaint = false; - }); - - scheduledRepaint = true; - } - } - - @Override - public void add(Component component) { - add(component, ownComponents.size()); - } - - @Override - public void add(Component component, int index) { - if (component.getParent() != null && component.getParent() != this) { - throw new IllegalStateException("Component already has parent"); - } - - if (ownComponents.contains(component)) { - int existingIndex = new ArrayList<>(ownComponents).indexOf(component); - if (index > existingIndex) { - index--; - } - - remove(component); - } - - int implIndex = getActualIndex(index); - - ComponentCaption caption = null; - boolean haveDescription = false; - if (DesktopContainerHelper.hasExternalCaption(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - getContainer().add(caption, layoutAdapter.getCaptionConstraints(component), implIndex); // CAUTION this dramatically wrong - implIndex++; - } else if (DesktopContainerHelper.hasExternalDescription(component)) { - caption = new ComponentCaption(component); - captions.put(component, caption); - haveDescription = true; - } - - JComponent composition = DesktopComponentsHelper.getComposition(component); - // if component have description without caption, we need to wrap - // component to view Description button horizontally after component - if (haveDescription) { - JPanel wrapper = new JPanel(); - BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); - adapter.setExpandLayout(true); - adapter.setSpacing(false); - adapter.setMargin(false); - wrapper.add(composition); - wrapper.add(caption, new CC().alignY("top")); - getContainer().add(wrapper, layoutAdapter.getConstraints(component), implIndex); - wrappers.put(component, new Pair<>(wrapper, adapter)); - } else { - getContainer().add(composition, layoutAdapter.getConstraints(component), implIndex); - } - if (component.getId() != null) { - componentByIds.put(component.getId(), component); - } - - if (component instanceof BelongToFrame - && ((BelongToFrame) component).getFrame() == null) { - ((BelongToFrame) component).setFrame(this); - } else { - registerComponent(component); - } - - if (index == ownComponents.size()) { - ownComponents.add(component); - } else { - List componentsTempList = new ArrayList<>(ownComponents); - componentsTempList.add(index, component); - - ownComponents.clear(); - ownComponents.addAll(componentsTempList); - } - - DesktopContainerHelper.assignContainer(component, this); - - if (component instanceof DesktopAbstractComponent && !isEnabled()) { - ((DesktopAbstractComponent) component).setParentEnabled(false); - } - - component.setParent(this); - - requestRepaint(); - } - - @Override - public int indexOf(Component component) { - return Iterables.indexOf(ownComponents, c -> c == component); - } - - @Nullable - @Override - public Component getComponent(int index) { - return Iterables.get(ownComponents, index); - } - - @Override - public void remove(Component component) { - if (wrappers.containsKey(component)) { - getContainer().remove(wrappers.get(component).getFirst()); - wrappers.remove(component); - } else { - getContainer().remove(DesktopComponentsHelper.getComposition(component)); - } - getContainer().validate(); - if (captions.containsKey(component)) { - getContainer().remove(captions.get(component)); - captions.remove(component); - } - if (component.getId() != null) { - componentByIds.remove(component.getId()); - } - ownComponents.remove(component); - - DesktopContainerHelper.assignContainer(component, null); - - if (component instanceof DesktopAbstractComponent && !isEnabled()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - if (expandedComponent == component) { - expandedComponent = null; - } - - component.setParent(null); - - requestRepaint(); - } - - @Override - public void removeAll() { - wrappers.clear(); - getContainer().removeAll(); - componentByIds.clear(); - captions.clear(); - - List components = new ArrayList<>(ownComponents); - ownComponents.clear(); - - for (Component component : components) { - if (component instanceof DesktopAbstractComponent && !isEnabled()) { - ((DesktopAbstractComponent) component).setParentEnabled(true); - } - - if (expandedComponent == component) { - expandedComponent = null; - } - - component.setParent(null); - - DesktopContainerHelper.assignContainer(component, null); - } - - requestRepaint(); - } - - protected int getActualIndex(int originalIndex) { - int index = originalIndex; - Object[] components = ownComponents.toArray(); - for (int i = 0; i < originalIndex; i++) { - if (DesktopContainerHelper.hasExternalCaption((Component) components[i])) { - index++; - } - } - return index; - } - - @Override - public Component getOwnComponent(String id) { - return componentByIds.get(id); - } - - @Override - public Component getComponent(String id) { - return ComponentsHelper.getWindowComponent(this, id); - } - - @Override - public Collection getOwnComponents() { - return Collections.unmodifiableCollection(ownComponents); - } - - @Override - public Collection getComponents() { - return ComponentsHelper.getComponents(this); - } - - @Override - public JComponent getComponent() { - return panel; - } - - @Override - public JComponent getComposition() { - return panel; - } - - @Override - public String getId() { - return id; - } - - @Override - public void setId(String id) { - this.id = id; - } - - @Override - public String getDebugId() { - return null; - } - - @Override - public void setDebugId(String id) { - } - - @Override - public boolean isEnabled() { - return panel.isEnabled(); - } - - @Override - public void setEnabled(boolean enabled) { - if (isEnabled() != enabled) { - panel.setEnabled(enabled); - - updateEnabled(); - } - } - - public void updateEnabled() { - for (Component component : ownComponents) { - if (component instanceof DesktopAbstractComponent) { - ((DesktopAbstractComponent) component).setParentEnabled(isEnabled()); - } - } - } - @Override - public boolean isVisible() { - return true; - } - - @Override - public void setVisible(boolean visible) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isVisibleItself() { - return true; - } - - @Override - public boolean isEnabledItself() { - return panel.isEnabled(); - } - - @Override - public void requestFocus() { - } - - @Override - public float getHeight() { - return heightSize != null ? heightSize.value : -1; - } - - @Override - public int getHeightUnits() { - return heightSize != null ? heightSize.unit : 0; - } - - @Override - public void setHeight(String height) { - heightSize = ComponentSize.parse(height); - } - - @Override - public float getWidth() { - return widthSize != null ? widthSize.value : -1; - } - - @Override - public int getWidthUnits() { - return widthSize != null ? widthSize.unit : 0; - } - - @Override - public void setWidth(String width) { - widthSize = ComponentSize.parse(width); - } - - @Override - public Alignment getAlignment() { - return null; - } - - @Override - public void setAlignment(Alignment alignment) { - } - - @Override - public String getStyleName() { - return String.join(" ", styles); - } - - @Override - public void setStyleName(String styleName) { - if (styles == null) - styles = new LinkedList<>(); - - styles.clear(); - - parseAndApplyTheme(styleName); - } - - @Override - public void addStyleName(String styleName) { - if (styles == null) - styles = new LinkedList<>(); - - if (StringUtils.isEmpty(styleName) || styles.contains(styleName)) - return; - - parseAndApplyTheme(styleName); - } - - protected void parseAndApplyTheme(String styleName) { - if (StringUtils.isNotEmpty(styleName)) { - StringTokenizer tokenizer = new StringTokenizer(styleName, " "); - while (tokenizer.hasMoreTokens()) { - String style = tokenizer.nextToken(); - if (!styles.contains(style)) - styles.add(style); - } - } - } - - @Override - public void removeStyleName(String styleName) { - if (StringUtils.isEmpty(styleName) || CollectionUtils.isEmpty(styles) || !styles.contains(styleName)) - return; - - StringTokenizer tokenizer = new StringTokenizer(styleName, " "); - while (tokenizer.hasMoreTokens()) { - styles.remove(tokenizer.nextToken()); - } - } - - @Override - public X unwrap(Class internalComponentClass) { - return (X) getComponent(); - } - - @Override - public X unwrapComposition(Class internalCompositionClass) { - return (X) getComposition(); - } - - @Override - public void setMargin(MarginInfo marginInfo) { - layoutAdapter.setMargin(marginInfo); - } - - @Override - public MarginInfo getMargin() { - return layoutAdapter.getMargin(); - } - - @Override - public void setSpacing(boolean enabled) { - layoutAdapter.setSpacing(enabled); - } - - @Override - public boolean getSpacing() { - return layoutAdapter.getSpacing(); - } - - @Override - public Window wrapBy(Class wrapperClass) { - return delegate.wrapBy(wrapperClass); - } - - @Override - public Window getWrapper() { - return delegate.getWrapper(); - } - - protected boolean onClose(String actionId) { - fireWindowClosed(actionId); - return true; - } - - protected void fireWindowClosed(String actionId) { - for (Object listener : listeners) { - if (listener instanceof CloseListener) { - ((CloseListener) listener).windowClosed(actionId); - } - } - } - - protected JComponent getContainer() { - return panel; - } - - @Override - public void updateComponent(Component child) { - boolean componentReAdded = false; - if (DesktopContainerHelper.mayHaveExternalCaption(child)) { - if (captions.containsKey(child) - && !DesktopContainerHelper.hasExternalCaption(child) - && !DesktopContainerHelper.hasExternalDescription(child)) { - reAddChild(child); - componentReAdded = true; - } else if (!captions.containsKey(child) - && (DesktopContainerHelper.hasExternalCaption(child) - || DesktopContainerHelper.hasExternalDescription(child))) { - reAddChild(child); - componentReAdded = true; - } else if (captions.containsKey(child)) { - ComponentCaption caption = captions.get(child); - caption.update(); - BoxLayoutAdapter adapterForCaption = layoutAdapter; - if (wrappers.containsKey(child)) { - adapterForCaption = wrappers.get(child).getSecond(); - } - adapterForCaption.updateConstraints(caption, adapterForCaption.getCaptionConstraints(child)); - } - } - - if (!componentReAdded) { - JComponent composition; - if (wrappers.containsKey(child)) { - composition = wrappers.get(child).getFirst(); - } else { - composition = DesktopComponentsHelper.getComposition(child); - } - layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); - } - - requestRepaint(); - } - - protected void reAddChild(Component child) { - int index = indexOf(child); - - boolean expanded = expandedComponent == child; - remove(child); - add(child, index); - - if (expanded) { - expand(child); - } - } - - @Override - public void dispose() { - // hard stop timers - stopTimers(); - disposed = true; - } - - @Override - public boolean isDisposed() { - return disposed; - } - - @Override - public boolean validate(List fields) { - ValidationErrors errors = new ValidationErrors(); - - for (Validatable field : fields) { - try { - field.validate(); - } catch (ValidationException e) { - if (log.isTraceEnabled()) - log.trace("Validation failed", e); - else if (log.isDebugEnabled()) - log.debug("Validation failed: " + e); - - ComponentsHelper.fillErrorMessages(field, e, errors); - } - } - - return handleValidationErrors(errors); - } - - @Override - public boolean validateAll() { - ValidationErrors errors = new ValidationErrors(); - - Collection components = ComponentsHelper.getComponents(this); - for (Component component : components) { - if (component instanceof Validatable) { - Validatable validatable = (Validatable) component; - if (validatable.isValidateOnCommit()) { - try { - validatable.validate(); - } catch (ValidationException e) { - if (log.isTraceEnabled()) - log.trace("Validation failed", e); - else if (log.isDebugEnabled()) - log.debug("Validation failed: " + e); - - ComponentsHelper.fillErrorMessages(validatable, e, errors); - } - } - } - } - - validateAdditionalRules(errors); - - return handleValidationErrors(errors); - } - - protected void validateAdditionalRules(ValidationErrors errors) { - } - - protected boolean handleValidationErrors(ValidationErrors errors) { - delegate.postValidate(errors); - - if (errors.isEmpty()) - return true; - - DesktopComponentsHelper.focusProblemComponent(errors); - - SwingUtilities.invokeLater(() -> { - delegate.showValidationErrors(errors); - }); - - return false; - } - - @Override - public ActionsPermissions getActionsPermissions() { - return actionsPermissions; - } - - @Override - public String getIcon() { - return icon; - } - - @Override - public void setIcon(String icon) { - this.icon = icon; - } - - @Override - public ContentSwitchMode getContentSwitchMode() { - return contentSwitchMode; - } - - @Override - public void setContentSwitchMode(ContentSwitchMode mode) { - Preconditions.checkNotNullArgument(mode, "Content switch mode can't be null. " + - "Use ContentSwitchMode.DEFAULT option instead"); - - this.contentSwitchMode = mode; - } - - protected class DesktopDialogOptions extends DialogOptions { - @Override - protected DialogOptions setWidth(Float width, SizeUnit unit) { - if (unit != null && unit != SizeUnit.PIXELS) { - throw new UnsupportedOperationException("Dialog size can be set only in pixels"); - } - - super.setWidth(width, unit); - - if (width != null) { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - int intWidth = width.intValue(); - dialogWindow.setFixedWidth(intWidth >= 0 ? intWidth : null); - - Dimension dim = new Dimension(); - if (dialogWindow.getFixedWidth() != null) { - dim.width = dialogWindow.getFixedWidth(); - } - if (dialogWindow.getFixedHeight() != null) { - dim.height = dialogWindow.getFixedHeight(); - } - dialogWindow.setMinimumSize(dim); - - dialogWindow.pack(); - } - } - - return this; - } - - @Override - public Boolean getCloseable() { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - return BooleanUtils.isNotFalse(super.getCloseable()); - } - - return super.getCloseable(); - } - - @Override - public Float getWidth() { - DialogWindow dialogWindow = asDialogWindow(); - - if (dialogWindow == null) { - return super.getWidth(); - } else { - return dialogWindow.getFixedWidth() != null ? dialogWindow.getFixedWidth() : -1.0f; - } - } - - @Override - protected DialogOptions setHeight(Float height, SizeUnit unit) { - if (unit != null && unit != SizeUnit.PIXELS) { - throw new UnsupportedOperationException("In the desktop module only pixels are allowed"); - } - - super.setHeight(height, unit); - - if (height != null) { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - int intHeight = height.intValue(); - dialogWindow.setFixedHeight(intHeight >= 0 ? intHeight : null); - - Dimension dim = new Dimension(); - if (dialogWindow.getFixedWidth() != null) { - dim.width = dialogWindow.getFixedWidth(); - } - if (dialogWindow.getFixedHeight() != null) { - dim.height = dialogWindow.getFixedHeight(); - } - dialogWindow.setMinimumSize(dim); - - dialogWindow.pack(); - } - } - - return this; - } - - @Override - public Float getHeight() { - DialogWindow dialogWindow = asDialogWindow(); - - if (dialogWindow == null) { - return super.getHeight(); - } else { - return dialogWindow.getFixedHeight() != null ? dialogWindow.getFixedHeight() : -1.0f; - } - } - - @Override - public Boolean getModal() { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - return dialogWindow.isSoftModal(); - } - - return super.getModal(); - } - - @Override - public DialogOptions setModal(Boolean modal) { - super.setModal(modal); - - if (asDialogWindow() != null) { - log.warn("Changing DesktopWindow modal at run time is not supported"); - } - - return this; - } - - @Override - public DialogOptions setResizable(Boolean resizable) { - super.setResizable(resizable); - - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - dialogWindow.setResizable(BooleanUtils.isTrue(resizable)); - } - - return this; - } - - @Override - public Boolean getResizable() { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - return dialogWindow.isResizable(); - } - - return super.getResizable(); - } - - @Override - public Integer getPositionX() { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - return dialogWindow.getLocation().x; - } - - return super.getPositionX(); - } - - @Override - public DialogOptions setPositionX(Integer positionX) { - super.setPositionX(positionX); - - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - Integer positionY = getPositionY(); - dialogWindow.setLocation(positionX != null ? positionX : 0, - positionY != null ? positionY : 0); - } - - return this; - } - - @Override - public Integer getPositionY() { - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - return dialogWindow.getLocation().y; - } - - return super.getPositionY(); - } - - @Override - public DialogOptions setPositionY(Integer positionY) { - super.setPositionY(positionY); - - DialogWindow dialogWindow = asDialogWindow(); - if (dialogWindow != null) { - Integer positionX = getPositionX(); - dialogWindow.setLocation(positionX != null ? positionX : 0, - positionY != null ? positionY : 0); - } - - return this; - } - } - - public static class Editor extends DesktopWindow implements Window.Editor { - - @Override - protected WindowDelegate createDelegate() { - return new EditorWindowDelegate(this); - } - - @Override - public Entity getItem() { - return ((EditorWindowDelegate) delegate).getItem(); - } - - @Override - public void setItem(Entity item) { - ((EditorWindowDelegate) delegate).setItem(item); - } - - @Override - public boolean onClose(String actionId) { - releaseLock(); - return super.onClose(actionId); - } - - public void releaseLock() { - ((EditorWindowDelegate) delegate).releaseLock(); - } - - @Nullable - @Override - public Datasource getParentDs() { - return ((EditorWindowDelegate) delegate).getParentDs(); - } - - @Override - public void setParentDs(Datasource parentDs) { - ((EditorWindowDelegate) delegate).setParentDs(parentDs); - } - - protected Datasource getDatasource() { - return delegate.getDatasource(); - } - - @Override - public boolean commit() { - return commit(true); - } - - @Override - public boolean commit(boolean validate) { - if (validate && !getWrapper().validateAll()) - return false; - - return ((EditorWindowDelegate) delegate).commit(false); - } - - @Override - public void commitAndClose() { - if (!getWrapper().validateAll()) - return; - - if (((EditorWindowDelegate) delegate).commit(true)) - close(COMMIT_ACTION_ID); - } - - @Override - public boolean isLocked() { - return ((EditorWindowDelegate) delegate).isLocked(); - } - - @Override - public boolean isCrossFieldValidate() { - return ((EditorWindowDelegate) delegate).isCrossFieldValidate(); - } - - @Override - public void setCrossFieldValidate(boolean crossFieldValidate) { - ((EditorWindowDelegate) delegate).setCrossFieldValidate(crossFieldValidate); - } - - @Override - protected void validateAdditionalRules(ValidationErrors errors) { - ((EditorWindowDelegate) delegate).validateAdditionalRules(errors); - } - } - - public static class Lookup extends DesktopWindow implements Window.Lookup, LookupComponent.LookupSelectionChangeListener { - - protected Component lookupComponent; - protected Handler handler; - protected Validator validator; - - protected JPanel container; - - public Lookup() { - addAction(new SelectAction(this)); - - addAction(new AbstractAction(WindowDelegate.LOOKUP_CANCEL_ACTION_ID) { - @Override - public void actionPerform(Component component) { - close("cancel"); - } - }); - } - - @Nullable - protected Action getSelectAction() { - return getAction(WindowDelegate.LOOKUP_SELECT_ACTION_ID); - } - - @Override - public Component getLookupComponent() { - return lookupComponent; - } - - @Override - public void setLookupComponent(Component lookupComponent) { - Action selectAction = getSelectAction(); - if (this.lookupComponent instanceof LookupSelectionChangeNotifier) { - LookupSelectionChangeNotifier selectionChangeNotifier = (LookupSelectionChangeNotifier) this.lookupComponent; - selectionChangeNotifier.removeLookupValueChangeListener(this); - - if (selectAction != null) - selectAction.setEnabled(true); - } - - this.lookupComponent = lookupComponent; - - if (lookupComponent instanceof LookupComponent) { - ((LookupComponent) lookupComponent).setLookupSelectHandler(() -> { - if (selectAction != null) - selectAction.actionPerform(null); - }); - - if (lookupComponent instanceof LookupSelectionChangeNotifier) { - LookupSelectionChangeNotifier selectionChangeNotifier = - (LookupSelectionChangeNotifier) lookupComponent; - selectionChangeNotifier.addLookupValueChangeListener(this); - - if (selectAction != null) - selectAction.setEnabled(!selectionChangeNotifier.getLookupSelectedItems().isEmpty()); - } - } - } - - @Override - public Handler getLookupHandler() { - return handler; - } - - @Override - public void setLookupHandler(Handler handler) { - this.handler = handler; - } - - @Override - public Validator getLookupValidator() { - return validator; - } - - @Override - public void setLookupValidator(Validator validator) { - this.validator = validator; - } - - @Override - public void initLookupLayout() { - Action selectAction = getAction(WindowDelegate.LOOKUP_SELECT_ACTION_ID); - if (selectAction == null || selectAction.getOwner() == null) { - Frame frame = openFrame(null, "lookupWindowActions"); - JPanel jPanel = frame.unwrapComposition(JPanel.class); - BoxLayoutAdapter layoutAdapter = BoxLayoutAdapter.create(jPanel); - layoutAdapter.setMargin(true); - panel.add(jPanel); - - if (App.getInstance().isTestMode()) { - Component selectButton = frame.getComponent("selectButton"); - if (selectButton instanceof com.haulmont.cuba.gui.components.Button) { - selectButton.unwrap(JButton.class).setName("selectButton"); - } - Component cancelButton = frame.getComponent("cancelButton"); - if (cancelButton instanceof com.haulmont.cuba.gui.components.Button) { - cancelButton.unwrap(JButton.class).setName("cancelButton"); - } - } - } - } - - @Override - protected void initLayout() { - panel = new JPanel(); - panel.setLayout( - new MigLayout( - "flowy, fillx, ins 0" + (LayoutAdapter.isDebug() ? ", debug" : ""), - "", - "[]0[]") - ); - - container = new JPanel(); - layoutAdapter = BoxLayoutAdapter.create(container); - layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); - layoutAdapter.setMargin(true); - - panel.add(container, "grow, height 100%, width 100%"); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - - updateContainerConstraints(); - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - - updateContainerConstraints(); - } - - protected void updateContainerConstraints() { - CC cc = new CC(); - - if (widthSize != null) { - MigLayoutHelper.applyWidth(cc, (int) widthSize.value, widthSize.unit, true); - } else { - MigLayoutHelper.applyWidth(cc, 100, UNITS_PERCENTAGE, true); - } - - if (heightSize != null) { - MigLayoutHelper.applyHeight(cc, (int) heightSize.value, heightSize.unit, true); - } else { - MigLayoutHelper.applyHeight(cc, 100, UNITS_PERCENTAGE, true); - } - - MigLayout migLayout = (MigLayout) panel.getLayout(); - migLayout.setComponentConstraints(container, cc); - } - - @Override - protected JComponent getContainer() { - return container; - } - - @Override - public void lookupValueChanged(LookupComponent.LookupSelectionChangeEvent event) { - Action selectAction = getSelectAction(); - if (selectAction != null) - selectAction.setEnabled(!event.getSource().getLookupSelectedItems().isEmpty()); - } - } - - protected static class CloseListenerAdapter implements CloseListener { - - protected CloseWithCommitListener closeWithCommitListener; - - public CloseListenerAdapter(CloseWithCommitListener closeWithCommitListener) { - this.closeWithCommitListener = closeWithCommitListener; - } - - @Override - public int hashCode() { - return closeWithCommitListener.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - CloseListenerAdapter wrapper = (CloseListenerAdapter) obj; - - return this.closeWithCommitListener.equals(wrapper.closeWithCommitListener); - } - - @Override - public void windowClosed(String actionId) { - if (COMMIT_ACTION_ID.equals(actionId)) { - closeWithCommitListener.windowClosedWithCommitAction(); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.google.common.collect.Iterables; +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.bali.events.EventRouter; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.desktop.gui.data.ComponentSize; +import com.haulmont.cuba.desktop.gui.data.DesktopContainerHelper; +import com.haulmont.cuba.desktop.sys.DesktopWindowManager; +import com.haulmont.cuba.desktop.sys.DialogWindow; +import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.LayoutAdapter; +import com.haulmont.cuba.desktop.sys.layout.MigLayoutHelper; +import com.haulmont.cuba.desktop.sys.vcl.JTabbedPaneExt; +import com.haulmont.cuba.gui.*; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Action.Status; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.DialogAction.Type; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.LookupComponent.LookupSelectionChangeNotifier; +import com.haulmont.cuba.gui.components.Timer; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.components.actions.BaseAction; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.DsContext; +import com.haulmont.cuba.gui.events.sys.UiEventsMulticaster; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import com.haulmont.cuba.gui.settings.Settings; +import net.miginfocom.layout.CC; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.util.*; +import java.util.List; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +public class DesktopWindow implements Window, Component.Disposable, + Component.Wrapper, Component.HasXmlDescriptor, Component.SecuredActionsHolder, WrappedWindow, DesktopContainer { + + protected static final Logger log = LoggerFactory.getLogger(DesktopWindow.class); + protected Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + + protected boolean disposed = false; + protected boolean responsive = false; + + protected BoxLayoutAdapter layoutAdapter; + protected JPanel panel; + + protected String id; + + protected Map componentByIds = new HashMap<>(); + protected Collection ownComponents = new LinkedHashSet<>(); + + protected Map allComponents = new HashMap<>(); + + protected DsContext dsContext; + protected WindowContext context; + protected String messagePack; + protected String focusComponentId; + protected Element xmlDescriptor; + protected String caption; + protected String description; + protected Component expandedComponent; + protected Map captions = new HashMap<>(); + protected Map> wrappers = new HashMap<>(); + + protected WindowDelegate delegate; + + protected DesktopFrameActionsHolder actionsHolder; + protected final ActionsPermissions actionsPermissions = new ActionsPermissions(this); + + protected List listeners = new ArrayList<>(); + + protected boolean forceClose; + protected Runnable doAfterClose; + + protected List timers = new ArrayList<>(); + + protected DesktopWindowManager windowManager; + + protected Configuration configuration = AppBeans.get(Configuration.NAME); + protected Messages messages = AppBeans.get(Messages.NAME); + + protected ComponentSize widthSize; + protected ComponentSize heightSize; + + protected boolean scheduledRepaint = false; + protected DialogOptions dialogOptions = new DesktopDialogOptions(); + protected String icon; + protected List styles; + + private EventRouter eventRouter; + protected ContentSwitchMode contentSwitchMode = ContentSwitchMode.DEFAULT; + + protected boolean isAttachedToRoot = false; + + public DesktopWindow() { + initLayout(); + delegate = createDelegate(); + actionsHolder = new DesktopFrameActionsHolder(this, panel); + + setWidth("100%"); + + panel.addAncestorListener(new AncestorListener() { + @Override + public void ancestorAdded(AncestorEvent event) { + SwingUtilities.invokeLater(() -> { + if (!isAttachedToRoot) { + if (SwingUtilities.getRoot(event.getComponent()) != null) { + enableEventListeners(); + isAttachedToRoot = true; + } + } + }); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + SwingUtilities.invokeLater(() -> { + if (isAttachedToRoot) { + if (SwingUtilities.getRoot(event.getComponent()) == null) { + disableEventListeners(); + isAttachedToRoot = false; + } + } + }); + } + + @Override + public void ancestorMoved(AncestorEvent event) { + // do nothing + } + }); + } + + protected void disableEventListeners() { + Frame wrapper = delegate.getWrapper(); + if (wrapper != null) { + List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); + if (uiEventListeners != null) { + for (ApplicationListener listener : uiEventListeners) { + UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); + multicaster.removeApplicationListener(listener); + } + } + } + } + + protected void enableEventListeners() { + Frame wrapper = delegate.getWrapper(); + if (wrapper != null) { + List uiEventListeners = ((AbstractFrame) wrapper).getUiEventListeners(); + if (uiEventListeners != null) { + for (ApplicationListener listener : uiEventListeners) { + UiEventsMulticaster multicaster = App.getInstance().getUiEventsMulticaster(); + multicaster.addApplicationListener(listener); + } + } + } + } + + protected void initLayout() { + panel = new JPanel(); + layoutAdapter = BoxLayoutAdapter.create(panel); + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + layoutAdapter.setMargin(true); + } + + protected WindowDelegate createDelegate() { + return new WindowDelegate(this); + } + + @Nullable + protected DialogWindow asDialogWindow() { + java.awt.Component parent = getContainer(); + while (parent != null) { + if (parent instanceof DialogWindow) { + return (DialogWindow) parent; + } + + parent = parent.getParent(); + } + return null; + } + + @Override + public Element getXmlDescriptor() { + return xmlDescriptor; + } + + @Override + public void setXmlDescriptor(Element element) { + xmlDescriptor = element; + } + + @Override + public void addListener(CloseListener listener) { + addCloseListener(listener); + } + + @Override + public void removeListener(CloseListener listener) { + removeCloseListener(listener); + } + + @Override + public void addCloseListener(CloseListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + @Override + public void removeCloseListener(CloseListener listener) { + listeners.remove(listener); + } + + @Override + public void addCloseWithCommitListener(CloseWithCommitListener listener) { + if (listeners == null) { + listeners = new LinkedList<>(); + } + + CloseListenerAdapter adapter = new CloseListenerAdapter(listener); + if (!listeners.contains(adapter)) { + listeners.add(adapter); + } + } + + @Override + public void removeCloseWithCommitListener(CloseWithCommitListener listener) { + if (listeners != null) { + listeners.remove(new CloseListenerAdapter(listener)); + } + } + + /** + * Use EventRouter for listeners instead of fields with listeners List. + * + * @return lazily initialized {@link EventRouter} instance. + * @see EventRouter + */ + protected EventRouter getEventRouter() { + if (eventRouter == null) { + eventRouter = new EventRouter(); + } + return eventRouter; + } + + @Override + public void addBeforeCloseWithShortcutListener(BeforeCloseWithShortcutListener listener) { + getEventRouter().addListener(BeforeCloseWithShortcutListener.class, listener); + } + + @Override + public void removeBeforeCloseWithShortcutListener(BeforeCloseWithShortcutListener listener) { + getEventRouter().removeListener(BeforeCloseWithShortcutListener.class, listener); + } + + public void fireBeforeCloseWithShortcut(BeforeCloseWithShortcutEvent event) { + getEventRouter().fireEvent(BeforeCloseWithShortcutListener.class, + BeforeCloseWithShortcutListener::beforeCloseWithShortcut, event); + } + + @Override + public void addBeforeCloseWithCloseButtonListener(BeforeCloseWithCloseButtonListener listener) { + getEventRouter().addListener(BeforeCloseWithCloseButtonListener.class, listener); + } + + @Override + public void removeBeforeCloseWithCloseButtonListener(BeforeCloseWithCloseButtonListener listener) { + getEventRouter().removeListener(BeforeCloseWithCloseButtonListener.class, listener); + } + + public void fireBeforeCloseWithCloseButton(BeforeCloseWithCloseButtonEvent event) { + getEventRouter().fireEvent(BeforeCloseWithCloseButtonListener.class, + BeforeCloseWithCloseButtonListener::beforeCloseWithCloseButton, event); + } + + @Override + public void applySettings(Settings settings) { + delegate.applySettings(settings); + } + + @Override + public void saveSettings() { + delegate.saveSettings(); + } + + @Override + public void deleteSettings() { + delegate.deleteSettings(); + } + + @Override + public void setFocusComponent(String componentId) { + this.focusComponentId = componentId; + if (componentId != null) { + Component component = getComponent(componentId); + if (component != null) { + component.requestFocus(); + } else { + log.error("Can't find focus component: " + componentId); + } + } else { + findAndFocusChildComponent(); + } + } + + public boolean findAndFocusChildComponent() { + final java.awt.Component focusComponent = getComponentToFocus(getContainer()); + if (focusComponent != null) { + SwingUtilities.invokeLater(() -> { + focusComponent.requestFocus(); + }); + + return true; + } + return false; + } + + protected java.awt.Component getComponentToFocus(java.awt.Container component) { + if (component.isFocusable() && component.isEnabled() + && DesktopComponentsHelper.isRecursivelyVisible(component)) { + if (component instanceof JComboBox + || component instanceof JCheckBox + || component instanceof JTable + || component instanceof JTree) { + return component; + } else if (component instanceof JTextComponent && ((JTextComponent) component).isEditable()) { + return component; + } + } + for (java.awt.Component child : component.getComponents()) { + if (child instanceof JTabbedPane) { + // #PL-3176 + // we don't know about selected tab after request + // may be focused component lays on not selected tab + continue; + } + if (child instanceof java.awt.Container) { + java.awt.Component result = getComponentToFocus((java.awt.Container) child); + if (result != null) { + return result; + } + } else { + return child; + } + } + return null; + } + + @Override + public String getFocusComponent() { + return focusComponentId; + } + + @Override + public Settings getSettings() { + return delegate.getSettings(); + } + + @Override + public boolean isResponsive() { + return responsive; + } + + @Override + public void setResponsive(boolean responsive) { + this.responsive = responsive; + } + + @Override + public boolean close(final String actionId) { + if (!forceClose) { + if (!delegate.preClose(actionId)) + return false; + } + + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + + if (!forceClose && isModified()) { + final Committable committable = (getWrapper() instanceof Committable) ? (Committable) getWrapper() : + (this instanceof Committable) ? (Committable) this : null; + if ((committable != null) && clientConfig.getUseSaveConfirmation()) { + windowManager.showOptionDialog( + messages.getMainMessage("closeUnsaved.caption"), + messages.getMainMessage("saveUnsaved"), + MessageType.WARNING, + new Action[]{ + new DialogAction(Type.OK, Status.PRIMARY) + .withCaption(messages.getMainMessage("closeUnsaved.save")) + .withHandler(event -> { + + committable.commitAndClose(); + }), + new BaseAction("discard") + .withIcon("icons/cancel.png") + .withCaption(messages.getMainMessage("closeUnsaved.discard")) + .withHandler(event -> { + + committable.close(actionId, true); + }), + new DialogAction(Type.CANCEL) + .withIcon(null) + .withHandler(event -> { + + doAfterClose = null; + }) + } + ); + } else { + windowManager.showOptionDialog( + messages.getMainMessage("closeUnsaved.caption"), + messages.getMainMessage("closeUnsaved"), + MessageType.WARNING, + new Action[]{ + new DialogAction(Type.YES).withHandler(event -> { + getWrapper().close(actionId, true); + }), + new DialogAction(Type.NO, Status.PRIMARY).withHandler(event -> { + doAfterClose = null; + }) + } + ); + } + return false; + } + + if (!clientConfig.getManualScreenSettingsSaving()) { + if (delegate.getWrapper() != null) { + delegate.getWrapper().saveSettings(); + } else { + saveSettings(); + } + } + + delegate.disposeComponents(); + + windowManager.close(this); + boolean res = onClose(actionId); + if (res && doAfterClose != null) { + doAfterClose.run(); + } + + stopTimers(); + + userActionsLog.trace("Window {} was closed", getId()); + + return res; + } + + public boolean isModified() { + return delegate.isModified(); + } + + private void stopTimers() { + // hard stop timers + for (Timer timer : timers) { + ((DesktopTimer)timer).disposeTimer(); + } + } + + @Override + public boolean close(String actionId, boolean force) { + forceClose = force; + return close(actionId); + } + + @Override + public void closeAndRun(String actionId, Runnable runnable) { + this.doAfterClose = runnable; + close(actionId); + } + + @Override + public void addTimer(Timer timer) { + if (timer instanceof DesktopTimer) { + timers.add(timer); + } + } + + @Override + public Timer getTimer(String id) { + if (id == null) + throw new IllegalArgumentException("id is null"); + + for (Timer timer : timers) { + if (id.equals(timer.getId())) + return timer; + } + return null; + } + + @Override + public void addAction(Action action) { + checkNotNullArgument(action, "action must be non null"); + + actionsHolder.addAction(action); + actionsPermissions.apply(action); + } + + @Override + public void addAction(Action action, int index) { + checkNotNullArgument(action, "action must be non null"); + + actionsHolder.addAction(action, index); + actionsPermissions.apply(action); + } + + @Override + public void removeAction(@Nullable Action action) { + actionsHolder.removeAction(action); + } + + @Override + public void removeAction(@Nullable String id) { + actionsHolder.removeAction(id); + } + + @Override + public void removeAllActions() { + actionsHolder.removeAllActions(); + } + + @Override + public Collection getActions() { + return actionsHolder.getActions(); + } + + @Override + @Nullable + public Action getAction(String id) { + return actionsHolder.getAction(id); + } + + @Nullable + protected JPanel asTabWindow() { + java.awt.Component parent = getContainer(); + while (parent != null) { + if (parent.getParent() instanceof JTabbedPaneExt) { + return (JPanel) parent; + } + parent = parent.getParent(); + } + + return null; + } + + @Nullable + protected JPanel asDetachedWindow() { + java.awt.Component parent = getContainer(); + while (parent != null) { + if (parent.getParent() != null && parent.getParent().getParent() != null) { + if (parent.getParent().getParent() instanceof JLayeredPane) { + return (JPanel) parent; + } + } + parent = parent.getParent(); + } + + return null; + } + + protected JTabbedPaneExt getJTabbedPaneExt() { + java.awt.Component parent = getContainer(); + while (parent != null) { + if (parent instanceof JTabbedPaneExt) { + return (JTabbedPaneExt) parent; + } + parent = parent.getParent(); + } + + return null; + } + + @Override + public String getCaption() { + return caption; + } + + @Override + public void setCaption(String caption) { + this.caption = caption; + + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + dialogWindow.setTitle(caption); + } else { + JPanel tabWindow = asTabWindow(); + if (tabWindow != null) { + setTabCaptionAndDescription(tabWindow); + } else { + JPanel singleWindow = asDetachedWindow(); + if (singleWindow != null) { + ((TopLevelFrame) singleWindow.getParent().getParent().getParent().getParent()) + .setTitle(formatTabCaption(caption, description)); + windowManager.getBreadCrumbs(singleWindow).update(); + } + } + } + } + + @Override + public String getDescription() { + return description; + } + + @Override + public void setDescription(String description) { + this.description = description; + + JPanel tabWindow = asTabWindow(); + if (tabWindow != null) { + setTabCaptionAndDescription(tabWindow); + } else { + JPanel singleWindow = asDetachedWindow(); + if (singleWindow != null) { + ((TopLevelFrame) singleWindow.getParent().getParent().getParent().getParent()) + .setTitle(formatTabCaption(caption, description)); + } + } + } + + protected void setTabCaptionAndDescription(JComponent tabWindow) { + String formattedCaption = formatTabCaption(caption, description); + + JTabbedPaneExt jTabbedPaneExt = getJTabbedPaneExt(); + jTabbedPaneExt.setTitleAt(jTabbedPaneExt.getSelectedIndex(), formattedCaption); + windowManager.getBreadCrumbs(tabWindow).update(); + } + + protected String formatTabCaption(final String caption, final String description) { + DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); + String tabCaption = formatTabDescription(caption, description); + + int maxLength = desktopConfig.getMainTabCaptionLength(); + if (tabCaption.length() > maxLength) { + return tabCaption.substring(0, maxLength) + "..."; + } else { + return tabCaption; + } + } + + protected String formatTabDescription(final String caption, final String description) { + if (StringUtils.isNotEmpty(description)) { + return String.format("%s: %s", caption, description); + } else { + return caption; + } + } + + @Override + public WindowContext getContext() { + return context; + } + + @Override + public void setContext(FrameContext ctx) { + context = (WindowContext) ctx; + } + + @Override + public DsContext getDsContext() { + return dsContext; + } + + @Override + public void setDsContext(DsContext dsContext) { + this.dsContext = dsContext; + } + + @Override + public String getMessagesPack() { + return messagePack; + } + + @Override + public void setMessagesPack(String name) { + messagePack = name; + } + + @Override + public void registerComponent(Component component) { + if (component.getId() != null) { + allComponents.put(component.getId(), component); + } + } + + @Override + public void unregisterComponent(Component component) { + if (component.getId() != null) { + allComponents.remove(component.getId()); + } + } + + @Nullable + @Override + public Component getRegisteredComponent(String id) { + return allComponents.get(id); + } + + @Override + public boolean isValid() { + return delegate.isValid(); + } + + @Override + public void validate() throws ValidationException { + delegate.validate(); + } + + @Deprecated + @Override + public DialogParams getDialogParams() { + return getWindowManager().getDialogParams(); + } + + @Override + public Window openWindow(String windowAlias, WindowManager.OpenType openType, Map params) { + return delegate.openWindow(windowAlias, openType, params); + } + + @Override + public Window openWindow(String windowAlias, WindowManager.OpenType openType) { + return delegate.openWindow(windowAlias, openType); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType) { + return delegate.openEditor(item, openType); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params) { + return delegate.openEditor(item, openType, params); + } + + @Override + public Window.Editor openEditor(Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { + return delegate.openEditor(item, openType, params, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params, Datasource parentDs) { + return delegate.openEditor(windowAlias, item, openType, params, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Map params) { + return delegate.openEditor(windowAlias, item, openType, params); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType, Datasource parentDs) { + return delegate.openEditor(windowAlias, item, openType, parentDs); + } + + @Override + public Window.Editor openEditor(String windowAlias, Entity item, WindowManager.OpenType openType) { + return delegate.openEditor(windowAlias, item, openType); + } + + @Override + public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType) { + return delegate.openLookup(entityClass, handler, openType); + } + + @Override + public Window.Lookup openLookup(Class entityClass, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { + return delegate.openLookup(entityClass, handler, openType, params); + } + + @Override + public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType, Map params) { + return delegate.openLookup(windowAlias, handler, openType, params); + } + + @Override + public Window.Lookup openLookup(String windowAlias, Window.Lookup.Handler handler, WindowManager.OpenType openType) { + return delegate.openLookup(windowAlias, handler, openType); + } + + @Override + public Frame openFrame(Component parent, String windowAlias) { + return delegate.openFrame(parent, windowAlias); + } + + @Override + public Frame openFrame(Component parent, String windowAlias, Map params) { + return delegate.openFrame(parent, windowAlias, params); + } + + @Override + public DesktopWindowManager getWindowManager() { + return windowManager; + } + + @Override + public void setWindowManager(WindowManager windowManager) { + this.windowManager = (DesktopWindowManager) windowManager; + } + + @Override + public DialogOptions getDialogOptions() { + return dialogOptions; + } + + @Override + public void showMessageDialog(String title, String message, MessageType messageType) { + getWindowManager().showMessageDialog(title, message, messageType); + } + + @Override + public void showOptionDialog(String title, String message, MessageType messageType, Action[] actions) { + getWindowManager().showOptionDialog(title, message, messageType, actions); + } + + @Override + public void showOptionDialog(String title, String message, MessageType messageType, java.util.List actions) { + getWindowManager().showOptionDialog(title, message, messageType, actions.toArray(new Action[actions.size()])); + } + + @Override + public void showNotification(String caption) { + getWindowManager().showNotification(caption); + } + + @Override + public void showNotification(String caption, NotificationType type) { + getWindowManager().showNotification(caption, type); + } + + @Override + public void showNotification(String caption, String description, NotificationType type) { + getWindowManager().showNotification(caption, description, type); + } + + @Override + public void showWebPage(String url, @Nullable Map params) { + getWindowManager().showWebPage(url, params); + } + + @Override + public Frame getFrame() { + return this; + } + + @Override + public void setFrame(Frame frame) { + throw new UnsupportedOperationException(); + } + + @Override + public Component getParent() { + return null; + } + + @Override + public void setParent(Component parent) { + } + + @Override + public void expand(Component component, String height, String width) { + if (expandedComponent != null && expandedComponent instanceof DesktopComponent) { + ((DesktopComponent) expandedComponent).setExpanded(false); + } + + // only Y direction + if (StringUtils.isEmpty(height) || AUTO_SIZE.equals(height) || height.endsWith("%")) { + component.setHeight("100%"); + } + + JComponent expandingChild = DesktopComponentsHelper.getComposition(component); + + Pair wrapperInfo = wrappers.get(component); + if (wrapperInfo != null) { + expandingChild = wrapperInfo.getFirst(); + } + + layoutAdapter.expand(expandingChild, height, width); + + if (component instanceof DesktopComponent) { + ((DesktopComponent) component).setExpanded(true); + } + + expandedComponent = component; + } + + @Override + public void expand(Component component) { + expand(component, "", ""); + } + + @Override + public void resetExpanded() { + layoutAdapter.resetExpanded(); + expandedComponent = null; + } + + @Override + public boolean isExpanded(Component component) { + return expandedComponent == component; + } + + @Override + public ExpandDirection getExpandDirection() { + return ExpandDirection.VERTICAL; + } + + protected void requestRepaint() { + if (!scheduledRepaint) { + SwingUtilities.invokeLater(() -> { + getContainer().revalidate(); + getContainer().repaint(); + + java.awt.Container container = getContainer().getTopLevelAncestor(); + if (container instanceof DialogWindow) { + DialogWindow dialog = (DialogWindow) container; + if (!dialog.isResizable() && (getHeight() <= 0 || getWidth() <= 0)) { + dialog.pack(); + } + } + + scheduledRepaint = false; + }); + + scheduledRepaint = true; + } + } + + @Override + public void add(Component component) { + add(component, ownComponents.size()); + } + + @Override + public void add(Component component, int index) { + if (component.getParent() != null && component.getParent() != this) { + throw new IllegalStateException("Component already has parent"); + } + + if (ownComponents.contains(component)) { + int existingIndex = new ArrayList<>(ownComponents).indexOf(component); + if (index > existingIndex) { + index--; + } + + remove(component); + } + + int implIndex = getActualIndex(index); + + ComponentCaption caption = null; + boolean haveDescription = false; + if (DesktopContainerHelper.hasExternalCaption(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + getContainer().add(caption, layoutAdapter.getCaptionConstraints(component), implIndex); // CAUTION this dramatically wrong + implIndex++; + } else if (DesktopContainerHelper.hasExternalDescription(component)) { + caption = new ComponentCaption(component); + captions.put(component, caption); + haveDescription = true; + } + + JComponent composition = DesktopComponentsHelper.getComposition(component); + // if component have description without caption, we need to wrap + // component to view Description button horizontally after component + if (haveDescription) { + JPanel wrapper = new JPanel(); + BoxLayoutAdapter adapter = BoxLayoutAdapter.create(wrapper); + adapter.setExpandLayout(true); + adapter.setSpacing(false); + adapter.setMargin(false); + wrapper.add(composition); + wrapper.add(caption, new CC().alignY("top")); + getContainer().add(wrapper, layoutAdapter.getConstraints(component), implIndex); + wrappers.put(component, new Pair<>(wrapper, adapter)); + } else { + getContainer().add(composition, layoutAdapter.getConstraints(component), implIndex); + } + if (component.getId() != null) { + componentByIds.put(component.getId(), component); + } + + if (component instanceof BelongToFrame + && ((BelongToFrame) component).getFrame() == null) { + ((BelongToFrame) component).setFrame(this); + } else { + registerComponent(component); + } + + if (index == ownComponents.size()) { + ownComponents.add(component); + } else { + List componentsTempList = new ArrayList<>(ownComponents); + componentsTempList.add(index, component); + + ownComponents.clear(); + ownComponents.addAll(componentsTempList); + } + + DesktopContainerHelper.assignContainer(component, this); + + if (component instanceof DesktopAbstractComponent && !isEnabled()) { + ((DesktopAbstractComponent) component).setParentEnabled(false); + } + + component.setParent(this); + + requestRepaint(); + } + + @Override + public int indexOf(Component component) { + return Iterables.indexOf(ownComponents, c -> c == component); + } + + @Nullable + @Override + public Component getComponent(int index) { + return Iterables.get(ownComponents, index); + } + + @Override + public void remove(Component component) { + if (wrappers.containsKey(component)) { + getContainer().remove(wrappers.get(component).getFirst()); + wrappers.remove(component); + } else { + getContainer().remove(DesktopComponentsHelper.getComposition(component)); + } + getContainer().validate(); + if (captions.containsKey(component)) { + getContainer().remove(captions.get(component)); + captions.remove(component); + } + if (component.getId() != null) { + componentByIds.remove(component.getId()); + } + ownComponents.remove(component); + + DesktopContainerHelper.assignContainer(component, null); + + if (component instanceof DesktopAbstractComponent && !isEnabled()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + if (expandedComponent == component) { + expandedComponent = null; + } + + component.setParent(null); + + requestRepaint(); + } + + @Override + public void removeAll() { + wrappers.clear(); + getContainer().removeAll(); + componentByIds.clear(); + captions.clear(); + + List components = new ArrayList<>(ownComponents); + ownComponents.clear(); + + for (Component component : components) { + if (component instanceof DesktopAbstractComponent && !isEnabled()) { + ((DesktopAbstractComponent) component).setParentEnabled(true); + } + + if (expandedComponent == component) { + expandedComponent = null; + } + + component.setParent(null); + + DesktopContainerHelper.assignContainer(component, null); + } + + requestRepaint(); + } + + protected int getActualIndex(int originalIndex) { + int index = originalIndex; + Object[] components = ownComponents.toArray(); + for (int i = 0; i < originalIndex; i++) { + if (DesktopContainerHelper.hasExternalCaption((Component) components[i])) { + index++; + } + } + return index; + } + + @Override + public Component getOwnComponent(String id) { + return componentByIds.get(id); + } + + @Override + public Component getComponent(String id) { + return ComponentsHelper.getWindowComponent(this, id); + } + + @Override + public Collection getOwnComponents() { + return Collections.unmodifiableCollection(ownComponents); + } + + @Override + public Collection getComponents() { + return ComponentsHelper.getComponents(this); + } + + @Override + public JComponent getComponent() { + return panel; + } + + @Override + public JComponent getComposition() { + return panel; + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getDebugId() { + return null; + } + + @Override + public void setDebugId(String id) { + } + + @Override + public boolean isEnabled() { + return panel.isEnabled(); + } + + @Override + public void setEnabled(boolean enabled) { + if (isEnabled() != enabled) { + panel.setEnabled(enabled); + + updateEnabled(); + } + } + + public void updateEnabled() { + for (Component component : ownComponents) { + if (component instanceof DesktopAbstractComponent) { + ((DesktopAbstractComponent) component).setParentEnabled(isEnabled()); + } + } + } + @Override + public boolean isVisible() { + return true; + } + + @Override + public void setVisible(boolean visible) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isVisibleItself() { + return true; + } + + @Override + public boolean isEnabledItself() { + return panel.isEnabled(); + } + + @Override + public void requestFocus() { + } + + @Override + public float getHeight() { + return heightSize != null ? heightSize.value : -1; + } + + @Override + public int getHeightUnits() { + return heightSize != null ? heightSize.unit : 0; + } + + @Override + public void setHeight(String height) { + heightSize = ComponentSize.parse(height); + } + + @Override + public float getWidth() { + return widthSize != null ? widthSize.value : -1; + } + + @Override + public int getWidthUnits() { + return widthSize != null ? widthSize.unit : 0; + } + + @Override + public void setWidth(String width) { + widthSize = ComponentSize.parse(width); + } + + @Override + public Alignment getAlignment() { + return null; + } + + @Override + public void setAlignment(Alignment alignment) { + } + + @Override + public String getStyleName() { + return String.join(" ", styles); + } + + @Override + public void setStyleName(String styleName) { + if (styles == null) + styles = new LinkedList<>(); + + styles.clear(); + + parseAndApplyTheme(styleName); + } + + @Override + public void addStyleName(String styleName) { + if (styles == null) + styles = new LinkedList<>(); + + if (StringUtils.isEmpty(styleName) || styles.contains(styleName)) + return; + + parseAndApplyTheme(styleName); + } + + protected void parseAndApplyTheme(String styleName) { + if (StringUtils.isNotEmpty(styleName)) { + StringTokenizer tokenizer = new StringTokenizer(styleName, " "); + while (tokenizer.hasMoreTokens()) { + String style = tokenizer.nextToken(); + if (!styles.contains(style)) + styles.add(style); + } + } + } + + @Override + public void removeStyleName(String styleName) { + if (StringUtils.isEmpty(styleName) || CollectionUtils.isEmpty(styles) || !styles.contains(styleName)) + return; + + StringTokenizer tokenizer = new StringTokenizer(styleName, " "); + while (tokenizer.hasMoreTokens()) { + styles.remove(tokenizer.nextToken()); + } + } + + @Override + public X unwrap(Class internalComponentClass) { + return (X) getComponent(); + } + + @Override + public X unwrapComposition(Class internalCompositionClass) { + return (X) getComposition(); + } + + @Override + public void setMargin(MarginInfo marginInfo) { + layoutAdapter.setMargin(marginInfo); + } + + @Override + public MarginInfo getMargin() { + return layoutAdapter.getMargin(); + } + + @Override + public void setSpacing(boolean enabled) { + layoutAdapter.setSpacing(enabled); + } + + @Override + public boolean getSpacing() { + return layoutAdapter.getSpacing(); + } + + @Override + public Window wrapBy(Class wrapperClass) { + return delegate.wrapBy(wrapperClass); + } + + @Override + public Window getWrapper() { + return delegate.getWrapper(); + } + + protected boolean onClose(String actionId) { + fireWindowClosed(actionId); + return true; + } + + protected void fireWindowClosed(String actionId) { + for (Object listener : listeners) { + if (listener instanceof CloseListener) { + ((CloseListener) listener).windowClosed(actionId); + } + } + } + + protected JComponent getContainer() { + return panel; + } + + @Override + public void updateComponent(Component child) { + boolean componentReAdded = false; + if (DesktopContainerHelper.mayHaveExternalCaption(child)) { + if (captions.containsKey(child) + && !DesktopContainerHelper.hasExternalCaption(child) + && !DesktopContainerHelper.hasExternalDescription(child)) { + reAddChild(child); + componentReAdded = true; + } else if (!captions.containsKey(child) + && (DesktopContainerHelper.hasExternalCaption(child) + || DesktopContainerHelper.hasExternalDescription(child))) { + reAddChild(child); + componentReAdded = true; + } else if (captions.containsKey(child)) { + ComponentCaption caption = captions.get(child); + caption.update(); + BoxLayoutAdapter adapterForCaption = layoutAdapter; + if (wrappers.containsKey(child)) { + adapterForCaption = wrappers.get(child).getSecond(); + } + adapterForCaption.updateConstraints(caption, adapterForCaption.getCaptionConstraints(child)); + } + } + + if (!componentReAdded) { + JComponent composition; + if (wrappers.containsKey(child)) { + composition = wrappers.get(child).getFirst(); + } else { + composition = DesktopComponentsHelper.getComposition(child); + } + layoutAdapter.updateConstraints(composition, layoutAdapter.getConstraints(child)); + } + + requestRepaint(); + } + + protected void reAddChild(Component child) { + int index = indexOf(child); + + boolean expanded = expandedComponent == child; + remove(child); + add(child, index); + + if (expanded) { + expand(child); + } + } + + @Override + public void dispose() { + // hard stop timers + stopTimers(); + disposed = true; + } + + @Override + public boolean isDisposed() { + return disposed; + } + + @Override + public boolean validate(List fields) { + ValidationErrors errors = new ValidationErrors(); + + for (Validatable field : fields) { + try { + field.validate(); + } catch (ValidationException e) { + if (log.isTraceEnabled()) + log.trace("Validation failed", e); + else if (log.isDebugEnabled()) + log.debug("Validation failed: " + e); + + ComponentsHelper.fillErrorMessages(field, e, errors); + } + } + + return handleValidationErrors(errors); + } + + @Override + public boolean validateAll() { + ValidationErrors errors = new ValidationErrors(); + + Collection components = ComponentsHelper.getComponents(this); + for (Component component : components) { + if (component instanceof Validatable) { + Validatable validatable = (Validatable) component; + if (validatable.isValidateOnCommit()) { + try { + validatable.validate(); + } catch (ValidationException e) { + if (log.isTraceEnabled()) + log.trace("Validation failed", e); + else if (log.isDebugEnabled()) + log.debug("Validation failed: " + e); + + ComponentsHelper.fillErrorMessages(validatable, e, errors); + } + } + } + } + + validateAdditionalRules(errors); + + return handleValidationErrors(errors); + } + + protected void validateAdditionalRules(ValidationErrors errors) { + } + + protected boolean handleValidationErrors(ValidationErrors errors) { + delegate.postValidate(errors); + + if (errors.isEmpty()) + return true; + + DesktopComponentsHelper.focusProblemComponent(errors); + + SwingUtilities.invokeLater(() -> { + delegate.showValidationErrors(errors); + }); + + return false; + } + + @Override + public ActionsPermissions getActionsPermissions() { + return actionsPermissions; + } + + @Override + public String getIcon() { + return icon; + } + + @Override + public void setIcon(String icon) { + this.icon = icon; + } + + @Override + public ContentSwitchMode getContentSwitchMode() { + return contentSwitchMode; + } + + @Override + public void setContentSwitchMode(ContentSwitchMode mode) { + Preconditions.checkNotNullArgument(mode, "Content switch mode can't be null. " + + "Use ContentSwitchMode.DEFAULT option instead"); + + this.contentSwitchMode = mode; + } + + protected class DesktopDialogOptions extends DialogOptions { + @Override + protected DialogOptions setWidth(Float width, SizeUnit unit) { + if (unit != null && unit != SizeUnit.PIXELS) { + throw new UnsupportedOperationException("Dialog size can be set only in pixels"); + } + + super.setWidth(width, unit); + + if (width != null) { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + int intWidth = width.intValue(); + dialogWindow.setFixedWidth(intWidth >= 0 ? intWidth : null); + + Dimension dim = new Dimension(); + if (dialogWindow.getFixedWidth() != null) { + dim.width = dialogWindow.getFixedWidth(); + } + if (dialogWindow.getFixedHeight() != null) { + dim.height = dialogWindow.getFixedHeight(); + } + dialogWindow.setMinimumSize(dim); + + dialogWindow.pack(); + } + } + + return this; + } + + @Override + public Boolean getCloseable() { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + return BooleanUtils.isNotFalse(super.getCloseable()); + } + + return super.getCloseable(); + } + + @Override + public Float getWidth() { + DialogWindow dialogWindow = asDialogWindow(); + + if (dialogWindow == null) { + return super.getWidth(); + } else { + return dialogWindow.getFixedWidth() != null ? dialogWindow.getFixedWidth() : -1.0f; + } + } + + @Override + protected DialogOptions setHeight(Float height, SizeUnit unit) { + if (unit != null && unit != SizeUnit.PIXELS) { + throw new UnsupportedOperationException("In the desktop module only pixels are allowed"); + } + + super.setHeight(height, unit); + + if (height != null) { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + int intHeight = height.intValue(); + dialogWindow.setFixedHeight(intHeight >= 0 ? intHeight : null); + + Dimension dim = new Dimension(); + if (dialogWindow.getFixedWidth() != null) { + dim.width = dialogWindow.getFixedWidth(); + } + if (dialogWindow.getFixedHeight() != null) { + dim.height = dialogWindow.getFixedHeight(); + } + dialogWindow.setMinimumSize(dim); + + dialogWindow.pack(); + } + } + + return this; + } + + @Override + public Float getHeight() { + DialogWindow dialogWindow = asDialogWindow(); + + if (dialogWindow == null) { + return super.getHeight(); + } else { + return dialogWindow.getFixedHeight() != null ? dialogWindow.getFixedHeight() : -1.0f; + } + } + + @Override + public Boolean getModal() { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + return dialogWindow.isSoftModal(); + } + + return super.getModal(); + } + + @Override + public DialogOptions setModal(Boolean modal) { + super.setModal(modal); + + if (asDialogWindow() != null) { + log.warn("Changing DesktopWindow modal at run time is not supported"); + } + + return this; + } + + @Override + public DialogOptions setResizable(Boolean resizable) { + super.setResizable(resizable); + + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + dialogWindow.setResizable(BooleanUtils.isTrue(resizable)); + } + + return this; + } + + @Override + public Boolean getResizable() { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + return dialogWindow.isResizable(); + } + + return super.getResizable(); + } + + @Override + public Integer getPositionX() { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + return dialogWindow.getLocation().x; + } + + return super.getPositionX(); + } + + @Override + public DialogOptions setPositionX(Integer positionX) { + super.setPositionX(positionX); + + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + Integer positionY = getPositionY(); + dialogWindow.setLocation(positionX != null ? positionX : 0, + positionY != null ? positionY : 0); + } + + return this; + } + + @Override + public Integer getPositionY() { + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + return dialogWindow.getLocation().y; + } + + return super.getPositionY(); + } + + @Override + public DialogOptions setPositionY(Integer positionY) { + super.setPositionY(positionY); + + DialogWindow dialogWindow = asDialogWindow(); + if (dialogWindow != null) { + Integer positionX = getPositionX(); + dialogWindow.setLocation(positionX != null ? positionX : 0, + positionY != null ? positionY : 0); + } + + return this; + } + } + + public static class Editor extends DesktopWindow implements Window.Editor { + + @Override + protected WindowDelegate createDelegate() { + return new EditorWindowDelegate(this); + } + + @Override + public Entity getItem() { + return ((EditorWindowDelegate) delegate).getItem(); + } + + @Override + public void setItem(Entity item) { + ((EditorWindowDelegate) delegate).setItem(item); + } + + @Override + public boolean onClose(String actionId) { + releaseLock(); + return super.onClose(actionId); + } + + public void releaseLock() { + ((EditorWindowDelegate) delegate).releaseLock(); + } + + @Nullable + @Override + public Datasource getParentDs() { + return ((EditorWindowDelegate) delegate).getParentDs(); + } + + @Override + public void setParentDs(Datasource parentDs) { + ((EditorWindowDelegate) delegate).setParentDs(parentDs); + } + + protected Datasource getDatasource() { + return delegate.getDatasource(); + } + + @Override + public boolean commit() { + return commit(true); + } + + @Override + public boolean commit(boolean validate) { + if (validate && !getWrapper().validateAll()) + return false; + + return ((EditorWindowDelegate) delegate).commit(false); + } + + @Override + public void commitAndClose() { + if (!getWrapper().validateAll()) + return; + + if (((EditorWindowDelegate) delegate).commit(true)) + close(COMMIT_ACTION_ID); + } + + @Override + public boolean isLocked() { + return ((EditorWindowDelegate) delegate).isLocked(); + } + + @Override + public boolean isCrossFieldValidate() { + return ((EditorWindowDelegate) delegate).isCrossFieldValidate(); + } + + @Override + public void setCrossFieldValidate(boolean crossFieldValidate) { + ((EditorWindowDelegate) delegate).setCrossFieldValidate(crossFieldValidate); + } + + @Override + protected void validateAdditionalRules(ValidationErrors errors) { + ((EditorWindowDelegate) delegate).validateAdditionalRules(errors); + } + } + + public static class Lookup extends DesktopWindow implements Window.Lookup, LookupComponent.LookupSelectionChangeListener { + + protected Component lookupComponent; + protected Handler handler; + protected Validator validator; + + protected JPanel container; + + public Lookup() { + addAction(new SelectAction(this)); + + addAction(new AbstractAction(WindowDelegate.LOOKUP_CANCEL_ACTION_ID) { + @Override + public void actionPerform(Component component) { + close("cancel"); + } + }); + } + + @Nullable + protected Action getSelectAction() { + return getAction(WindowDelegate.LOOKUP_SELECT_ACTION_ID); + } + + @Override + public Component getLookupComponent() { + return lookupComponent; + } + + @Override + public void setLookupComponent(Component lookupComponent) { + Action selectAction = getSelectAction(); + if (this.lookupComponent instanceof LookupSelectionChangeNotifier) { + LookupSelectionChangeNotifier selectionChangeNotifier = (LookupSelectionChangeNotifier) this.lookupComponent; + selectionChangeNotifier.removeLookupValueChangeListener(this); + + if (selectAction != null) + selectAction.setEnabled(true); + } + + this.lookupComponent = lookupComponent; + + if (lookupComponent instanceof LookupComponent) { + ((LookupComponent) lookupComponent).setLookupSelectHandler(() -> { + if (selectAction != null) + selectAction.actionPerform(null); + }); + + if (lookupComponent instanceof LookupSelectionChangeNotifier) { + LookupSelectionChangeNotifier selectionChangeNotifier = + (LookupSelectionChangeNotifier) lookupComponent; + selectionChangeNotifier.addLookupValueChangeListener(this); + + if (selectAction != null) + selectAction.setEnabled(!selectionChangeNotifier.getLookupSelectedItems().isEmpty()); + } + } + } + + @Override + public Handler getLookupHandler() { + return handler; + } + + @Override + public void setLookupHandler(Handler handler) { + this.handler = handler; + } + + @Override + public Validator getLookupValidator() { + return validator; + } + + @Override + public void setLookupValidator(Validator validator) { + this.validator = validator; + } + + @Override + public void initLookupLayout() { + Action selectAction = getAction(WindowDelegate.LOOKUP_SELECT_ACTION_ID); + if (selectAction == null || selectAction.getOwner() == null) { + Frame frame = openFrame(null, "lookupWindowActions"); + JPanel jPanel = frame.unwrapComposition(JPanel.class); + BoxLayoutAdapter layoutAdapter = BoxLayoutAdapter.create(jPanel); + layoutAdapter.setMargin(true); + panel.add(jPanel); + + if (App.getInstance().isTestMode()) { + Component selectButton = frame.getComponent("selectButton"); + if (selectButton instanceof com.haulmont.cuba.gui.components.Button) { + selectButton.unwrap(JButton.class).setName("selectButton"); + } + Component cancelButton = frame.getComponent("cancelButton"); + if (cancelButton instanceof com.haulmont.cuba.gui.components.Button) { + cancelButton.unwrap(JButton.class).setName("cancelButton"); + } + } + } + } + + @Override + protected void initLayout() { + panel = new JPanel(); + panel.setLayout( + new MigLayout( + "flowy, fillx, ins 0" + (LayoutAdapter.isDebug() ? ", debug" : ""), + "", + "[]0[]") + ); + + container = new JPanel(); + layoutAdapter = BoxLayoutAdapter.create(container); + layoutAdapter.setFlowDirection(BoxLayoutAdapter.FlowDirection.Y); + layoutAdapter.setMargin(true); + + panel.add(container, "grow, height 100%, width 100%"); + } + + @Override + public void setWidth(String width) { + super.setWidth(width); + + updateContainerConstraints(); + } + + @Override + public void setHeight(String height) { + super.setHeight(height); + + updateContainerConstraints(); + } + + protected void updateContainerConstraints() { + CC cc = new CC(); + + if (widthSize != null) { + MigLayoutHelper.applyWidth(cc, (int) widthSize.value, widthSize.unit, true); + } else { + MigLayoutHelper.applyWidth(cc, 100, UNITS_PERCENTAGE, true); + } + + if (heightSize != null) { + MigLayoutHelper.applyHeight(cc, (int) heightSize.value, heightSize.unit, true); + } else { + MigLayoutHelper.applyHeight(cc, 100, UNITS_PERCENTAGE, true); + } + + MigLayout migLayout = (MigLayout) panel.getLayout(); + migLayout.setComponentConstraints(container, cc); + } + + @Override + protected JComponent getContainer() { + return container; + } + + @Override + public void lookupValueChanged(LookupComponent.LookupSelectionChangeEvent event) { + Action selectAction = getSelectAction(); + if (selectAction != null) + selectAction.setEnabled(!event.getSource().getLookupSelectedItems().isEmpty()); + } + } + + protected static class CloseListenerAdapter implements CloseListener { + + protected CloseWithCommitListener closeWithCommitListener; + + public CloseListenerAdapter(CloseWithCommitListener closeWithCommitListener) { + this.closeWithCommitListener = closeWithCommitListener; + } + + @Override + public int hashCode() { + return closeWithCommitListener.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + CloseListenerAdapter wrapper = (CloseListenerAdapter) obj; + + return this.closeWithCommitListener.equals(wrapper.closeWithCommitListener); + } + + @Override + public void windowClosed(String actionId) { + if (COMMIT_ACTION_ID.equals(actionId)) { + closeWithCommitListener.windowClosedWithCommitAction(); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/SwingXTableSettings.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/SwingXTableSettings.java index 0bc1d2cb9d..772be91c75 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/SwingXTableSettings.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/SwingXTableSettings.java @@ -1,276 +1,276 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.gui.components.Table; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.table.TableColumnExt; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import javax.swing.table.TableColumn; -import java.awt.*; -import java.awt.font.TextAttribute; -import java.util.*; -import java.util.List; - -public class SwingXTableSettings implements TableSettings { - - private final Logger log = LoggerFactory.getLogger(SwingXTableSettings.class); - - protected JXTable table; - protected List columns; - - public SwingXTableSettings(JXTable table, List columns) { - this.table = table; - this.columns = columns; - } - - @Override - public boolean saveSettings(Element element) { - element.addAttribute("horizontalScroll", String.valueOf(table.isHorizontalScrollEnabled())); - - saveFontPreferences(element); - - Element columnsElem = element.element("columns"); - if (columnsElem != null) { - element.remove(columnsElem); - } - columnsElem = element.addElement("columns"); - - final List visibleTableColumns = table.getColumns(); - final List visibleColumns = new ArrayList<>(); - for (TableColumn tableColumn : visibleTableColumns) { - visibleColumns.add((Table.Column) tableColumn.getIdentifier()); - } - - List columns = table.getColumns(true); - Collections.sort( - columns, - new Comparator() { - @SuppressWarnings("SuspiciousMethodCalls") - @Override - public int compare(TableColumn col1, TableColumn col2) { - if (col1 instanceof TableColumnExt && !((TableColumnExt) col1).isVisible()) { - return 1; - } - if (col2 instanceof TableColumnExt && !((TableColumnExt) col2).isVisible()) { - return -1; - } - int i1 = visibleColumns.indexOf(col1.getIdentifier()); - int i2 = visibleColumns.indexOf(col2.getIdentifier()); - return Integer.compare(i1, i2); - } - } - ); - - for (TableColumn column : columns) { - Element colElem = columnsElem.addElement("column"); - colElem.addAttribute("id", column.getIdentifier().toString()); - - int width = column.getWidth(); - colElem.addAttribute("width", String.valueOf(width)); - - if (column instanceof TableColumnExt) { - Boolean visible = ((TableColumnExt) column).isVisible(); - colElem.addAttribute("visible", visible.toString()); - } - } - - if (table.getRowSorter() != null) { - TableColumn sortedColumn = table.getSortedColumn(); - List sortKeys = table.getRowSorter().getSortKeys(); - if (sortedColumn != null && !sortKeys.isEmpty()) { - columnsElem.addAttribute("sortColumn", String.valueOf(sortedColumn.getIdentifier())); - columnsElem.addAttribute("sortOrder", sortKeys.get(0).getSortOrder().toString()); - } - } - - return true; - } - - @Override - public void apply(Element element, boolean sortable) { - String horizontalScroll = element.attributeValue("horizontalScroll"); - if (!StringUtils.isBlank(horizontalScroll)) { - table.setHorizontalScrollEnabled(Boolean.valueOf(horizontalScroll)); - } - - loadFontPreferences(element); - - final Element columnsElem = element.element("columns"); - if (columnsElem == null) { - return; - } - - Collection modelIds = new LinkedList<>(); - for (TableColumn modelColumn : table.getColumns(true)) { - modelIds.add(String.valueOf(modelColumn.getIdentifier())); - } - - Collection loadedIds = new LinkedList<>(); - for (Element colElem : Dom4j.elements(columnsElem, "column")) { - String id = colElem.attributeValue("id"); - loadedIds.add(id); - } - - Configuration configuration = AppBeans.get(Configuration.NAME); - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - - if (clientConfig.getLoadObsoleteSettingsForTable() - || CollectionUtils.isEqualCollection(modelIds, loadedIds)) { - applyColumnSettings(element, sortable); - } - } - - protected void applyColumnSettings(Element element, boolean sortable) { - final Element columnsElem = element.element("columns"); - // do not allow duplicates - Collection sequence = new LinkedHashSet<>(); - - for (Element colElem : Dom4j.elements(columnsElem, "column")) { - String id = colElem.attributeValue("id"); - Table.Column column = getColumn(id); - if (column != null) { - sequence.add(column); - - TableColumnExt tableColumn = table.getColumnExt(column); - - if (tableColumn != null) { - String width = colElem.attributeValue("width"); - if (StringUtils.isNotEmpty(width)) { - tableColumn.setPreferredWidth(Integer.parseInt(width)); - } - - String visible = colElem.attributeValue("visible"); - if (StringUtils.isNotEmpty(visible)) { - tableColumn.setVisible(Boolean.valueOf(visible)); - } - } - } - } - table.setColumnSequence(sequence.toArray(new Object[sequence.size()])); - - if (sortable && table.getRowSorter() != null) { - String sortColumn = columnsElem.attributeValue("sortColumn"); - if (sortColumn != null) { - SortOrder sortOrder = SortOrder.valueOf(columnsElem.attributeValue("sortOrder")); - int sortColumnIndex = -1; - - if (!StringUtils.isNumeric(sortColumn)) { - Table.Column column = getColumn(sortColumn); - if (column != null) { - sortColumnIndex = columns.indexOf(column); - } - } else { - // backward compatibility - sortColumnIndex = Integer.parseInt(sortColumn); - } - - if (sortColumnIndex >= 0) { - table.getRowSorter().setSortKeys(Collections.singletonList(new RowSorter.SortKey(sortColumnIndex, sortOrder))); - } - } else { - table.getRowSorter().setSortKeys(null); - } - } - - table.revalidate(); - table.repaint(); - } - - protected void saveFontPreferences(Element element) { - if (table.getFont() != null) { - Font font = table.getFont(); - Map attributes = font.getAttributes(); - // save content font - element.addAttribute("fontFamily", font.getFamily()); - element.addAttribute("fontSize", Integer.toString(font.getSize())); - element.addAttribute("fontStyle", Integer.toString(font.getStyle())); - element.addAttribute("fontUnderline", - Boolean.toString(attributes.get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON)); - } - } - - protected void loadFontPreferences(Element element) { - // load font preferences - String fontFamily = element.attributeValue("fontFamily"); - String fontSize = element.attributeValue("fontSize"); - String fontStyle = element.attributeValue("fontStyle"); - String fontUnderline = element.attributeValue("fontUnderline"); - if (!StringUtils.isBlank(fontFamily) && - !StringUtils.isBlank(fontSize) && - !StringUtils.isBlank(fontUnderline) && - !StringUtils.isBlank(fontStyle)) { - - try { - int size = Integer.parseInt(fontSize); - int style = Integer.parseInt(fontStyle); - - String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getAvailableFontFamilyNames(); - int fontIndex = Arrays.asList(availableFonts).indexOf(fontFamily); - if (fontIndex < 0) { - log.debug("Unsupported font family, font settings not loaded"); - return; - } - - Configuration configuration = AppBeans.get(Configuration.NAME); - DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); - int sizeIndex = desktopConfig.getAvailableFontSizes().indexOf(size); - - if (sizeIndex < 0) { - log.debug("Unsupported font size, font settings not loaded"); - return; - } - - Boolean underline = BooleanUtils.toBooleanObject(fontUnderline); - - @SuppressWarnings("MagicConstant") - Font font = new Font(fontFamily, style, size); - if (underline != null && Boolean.TRUE.equals(underline)) { - Map attributes = new HashMap<>(); - attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); - font = font.deriveFont(attributes); - } - table.setFont(font); - } catch (NumberFormatException ex) { - log.debug("Broken font definition in user setting"); - } - } - } - - protected Table.Column getColumn(String id) { - for (Table.Column column : columns) { - if (column.getId().toString().equals(id)) { - return column; - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.gui.components.Table; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.table.TableColumnExt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.awt.font.TextAttribute; +import java.util.*; +import java.util.List; + +public class SwingXTableSettings implements TableSettings { + + private final Logger log = LoggerFactory.getLogger(SwingXTableSettings.class); + + protected JXTable table; + protected List columns; + + public SwingXTableSettings(JXTable table, List columns) { + this.table = table; + this.columns = columns; + } + + @Override + public boolean saveSettings(Element element) { + element.addAttribute("horizontalScroll", String.valueOf(table.isHorizontalScrollEnabled())); + + saveFontPreferences(element); + + Element columnsElem = element.element("columns"); + if (columnsElem != null) { + element.remove(columnsElem); + } + columnsElem = element.addElement("columns"); + + final List visibleTableColumns = table.getColumns(); + final List visibleColumns = new ArrayList<>(); + for (TableColumn tableColumn : visibleTableColumns) { + visibleColumns.add((Table.Column) tableColumn.getIdentifier()); + } + + List columns = table.getColumns(true); + Collections.sort( + columns, + new Comparator() { + @SuppressWarnings("SuspiciousMethodCalls") + @Override + public int compare(TableColumn col1, TableColumn col2) { + if (col1 instanceof TableColumnExt && !((TableColumnExt) col1).isVisible()) { + return 1; + } + if (col2 instanceof TableColumnExt && !((TableColumnExt) col2).isVisible()) { + return -1; + } + int i1 = visibleColumns.indexOf(col1.getIdentifier()); + int i2 = visibleColumns.indexOf(col2.getIdentifier()); + return Integer.compare(i1, i2); + } + } + ); + + for (TableColumn column : columns) { + Element colElem = columnsElem.addElement("column"); + colElem.addAttribute("id", column.getIdentifier().toString()); + + int width = column.getWidth(); + colElem.addAttribute("width", String.valueOf(width)); + + if (column instanceof TableColumnExt) { + Boolean visible = ((TableColumnExt) column).isVisible(); + colElem.addAttribute("visible", visible.toString()); + } + } + + if (table.getRowSorter() != null) { + TableColumn sortedColumn = table.getSortedColumn(); + List sortKeys = table.getRowSorter().getSortKeys(); + if (sortedColumn != null && !sortKeys.isEmpty()) { + columnsElem.addAttribute("sortColumn", String.valueOf(sortedColumn.getIdentifier())); + columnsElem.addAttribute("sortOrder", sortKeys.get(0).getSortOrder().toString()); + } + } + + return true; + } + + @Override + public void apply(Element element, boolean sortable) { + String horizontalScroll = element.attributeValue("horizontalScroll"); + if (!StringUtils.isBlank(horizontalScroll)) { + table.setHorizontalScrollEnabled(Boolean.valueOf(horizontalScroll)); + } + + loadFontPreferences(element); + + final Element columnsElem = element.element("columns"); + if (columnsElem == null) { + return; + } + + Collection modelIds = new LinkedList<>(); + for (TableColumn modelColumn : table.getColumns(true)) { + modelIds.add(String.valueOf(modelColumn.getIdentifier())); + } + + Collection loadedIds = new LinkedList<>(); + for (Element colElem : Dom4j.elements(columnsElem, "column")) { + String id = colElem.attributeValue("id"); + loadedIds.add(id); + } + + Configuration configuration = AppBeans.get(Configuration.NAME); + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + + if (clientConfig.getLoadObsoleteSettingsForTable() + || CollectionUtils.isEqualCollection(modelIds, loadedIds)) { + applyColumnSettings(element, sortable); + } + } + + protected void applyColumnSettings(Element element, boolean sortable) { + final Element columnsElem = element.element("columns"); + // do not allow duplicates + Collection sequence = new LinkedHashSet<>(); + + for (Element colElem : Dom4j.elements(columnsElem, "column")) { + String id = colElem.attributeValue("id"); + Table.Column column = getColumn(id); + if (column != null) { + sequence.add(column); + + TableColumnExt tableColumn = table.getColumnExt(column); + + if (tableColumn != null) { + String width = colElem.attributeValue("width"); + if (StringUtils.isNotEmpty(width)) { + tableColumn.setPreferredWidth(Integer.parseInt(width)); + } + + String visible = colElem.attributeValue("visible"); + if (StringUtils.isNotEmpty(visible)) { + tableColumn.setVisible(Boolean.valueOf(visible)); + } + } + } + } + table.setColumnSequence(sequence.toArray(new Object[sequence.size()])); + + if (sortable && table.getRowSorter() != null) { + String sortColumn = columnsElem.attributeValue("sortColumn"); + if (sortColumn != null) { + SortOrder sortOrder = SortOrder.valueOf(columnsElem.attributeValue("sortOrder")); + int sortColumnIndex = -1; + + if (!StringUtils.isNumeric(sortColumn)) { + Table.Column column = getColumn(sortColumn); + if (column != null) { + sortColumnIndex = columns.indexOf(column); + } + } else { + // backward compatibility + sortColumnIndex = Integer.parseInt(sortColumn); + } + + if (sortColumnIndex >= 0) { + table.getRowSorter().setSortKeys(Collections.singletonList(new RowSorter.SortKey(sortColumnIndex, sortOrder))); + } + } else { + table.getRowSorter().setSortKeys(null); + } + } + + table.revalidate(); + table.repaint(); + } + + protected void saveFontPreferences(Element element) { + if (table.getFont() != null) { + Font font = table.getFont(); + Map attributes = font.getAttributes(); + // save content font + element.addAttribute("fontFamily", font.getFamily()); + element.addAttribute("fontSize", Integer.toString(font.getSize())); + element.addAttribute("fontStyle", Integer.toString(font.getStyle())); + element.addAttribute("fontUnderline", + Boolean.toString(attributes.get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON)); + } + } + + protected void loadFontPreferences(Element element) { + // load font preferences + String fontFamily = element.attributeValue("fontFamily"); + String fontSize = element.attributeValue("fontSize"); + String fontStyle = element.attributeValue("fontStyle"); + String fontUnderline = element.attributeValue("fontUnderline"); + if (!StringUtils.isBlank(fontFamily) && + !StringUtils.isBlank(fontSize) && + !StringUtils.isBlank(fontUnderline) && + !StringUtils.isBlank(fontStyle)) { + + try { + int size = Integer.parseInt(fontSize); + int style = Integer.parseInt(fontStyle); + + String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getAvailableFontFamilyNames(); + int fontIndex = Arrays.asList(availableFonts).indexOf(fontFamily); + if (fontIndex < 0) { + log.debug("Unsupported font family, font settings not loaded"); + return; + } + + Configuration configuration = AppBeans.get(Configuration.NAME); + DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); + int sizeIndex = desktopConfig.getAvailableFontSizes().indexOf(size); + + if (sizeIndex < 0) { + log.debug("Unsupported font size, font settings not loaded"); + return; + } + + Boolean underline = BooleanUtils.toBooleanObject(fontUnderline); + + @SuppressWarnings("MagicConstant") + Font font = new Font(fontFamily, style, size); + if (underline != null && Boolean.TRUE.equals(underline)) { + Map attributes = new HashMap<>(); + attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); + font = font.deriveFont(attributes); + } + table.setFont(font); + } catch (NumberFormatException ex) { + log.debug("Broken font definition in user setting"); + } + } + } + + protected Table.Column getColumn(String id) { + for (Table.Column column : columns) { + if (column.getId().toString().equals(id)) { + return column; + } + } + return null; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TableSettings.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TableSettings.java index 49e74c5753..3e5bb21425 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TableSettings.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TableSettings.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import org.dom4j.Element; - -public interface TableSettings { - - boolean saveSettings(Element element); - - void apply(Element element, boolean sortable); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import org.dom4j.Element; + +public interface TableSettings { + + boolean saveSettings(Element element); + + void apply(Element element, boolean sortable); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TextComponentDocument.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TextComponentDocument.java index c9481eabbc..84c38226a4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TextComponentDocument.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/TextComponentDocument.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components; - -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.PlainDocument; - -public class TextComponentDocument extends PlainDocument { - - private static final long serialVersionUID = -3290292622981584624L; - - public static final int UNLIMITED_LENGTH = -1; - - private int maxLength = UNLIMITED_LENGTH; - - public int getMaxLength() { - return maxLength; - } - - public void setMaxLength(int maxLength) { - this.maxLength = maxLength; - } - - @Override - public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { - if (str == null) - return; - - if (maxLength == UNLIMITED_LENGTH || (getLength() + str.length()) <= maxLength) { - super.insertString(offs, str, a); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +public class TextComponentDocument extends PlainDocument { + + private static final long serialVersionUID = -3290292622981584624L; + + public static final int UNLIMITED_LENGTH = -1; + + private int maxLength = UNLIMITED_LENGTH; + + public int getMaxLength() { + return maxLength; + } + + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (str == null) + return; + + if (maxLength == UNLIMITED_LENGTH || (getLength() + str.length()) <= maxLength) { + super.insertString(offs, str, a); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/filter/edit/DesktopFilterEditorCompanion.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/filter/edit/DesktopFilterEditorCompanion.java index 0bb49aa769..2dae7ed1f3 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/filter/edit/DesktopFilterEditorCompanion.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/filter/edit/DesktopFilterEditorCompanion.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.components.filter.edit; - -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.filter.edit.FilterEditor; - -public class DesktopFilterEditorCompanion implements FilterEditor.Companion { - @Override - public void showComponentName(WindowManager windowManager, String title, String message) { - windowManager.showMessageDialog(title, - String.format("", message), - Frame.MessageType.CONFIRMATION_HTML); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.components.filter.edit; + +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.filter.edit.FilterEditor; + +public class DesktopFilterEditorCompanion implements FilterEditor.Companion { + @Override + public void showComponentName(WindowManager windowManager, String title, String message) { + windowManager.showMessageDialog(title, + String.format("", message), + Frame.MessageType.CONFIRMATION_HTML); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages.properties b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages.properties index a843000357..7ebacb36be 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages.properties @@ -1,26 +1,26 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -export.selectFile=Select file -export.saveFile=What do you want to do with this file: %s ? -export.saveError=Could not save file, I/O error -export.saveSuccess=File has been saved successfully -export.dataProviderError=Could not save file, data provider error -export.tempFileError=Could not create temp file for download -export.openError=Could not open file, please check your installed software -export.fileCaption=File +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +export.selectFile=Select file +export.saveFile=What do you want to do with this file: %s ? +export.saveError=Could not save file, I/O error +export.saveSuccess=File has been saved successfully +export.dataProviderError=Could not save file, data provider error +export.tempFileError=Could not create temp file for download +export.openError=Could not open file, please check your installed software +export.fileCaption=File upload.selectFiles=Upload \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages_ru.properties b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages_ru.properties index 69b9770bc9..9ca8c075c5 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages_ru.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/components/messages_ru.properties @@ -1,26 +1,26 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -export.selectFile=Выбрать файл -export.saveFile=Что вы хотите сделать с файлом: %s ? -export.fileCaption=Файл -export.openError=Невозможно открыть файл -export.saveSuccess=Файл успешно сохранён -export.saveError=Невозможно сохранить файл -export.dataProviderError=Невозможно сохранить файл, ошибка провайдера данных -export.tempFileError=Невозможно создать временный файл +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +export.selectFile=Выбрать файл +export.saveFile=Что вы хотите сделать с файлом: %s ? +export.fileCaption=Файл +export.openError=Невозможно открыть файл +export.saveSuccess=Файл успешно сохранён +export.saveError=Невозможно сохранить файл +export.dataProviderError=Невозможно сохранить файл, ошибка провайдера данных +export.tempFileError=Невозможно создать временный файл upload.selectFiles=Добавить \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/AnyTableModelAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/AnyTableModelAdapter.java index ac0f701653..04d9916ba6 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/AnyTableModelAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/AnyTableModelAdapter.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.gui.components.Table; - -import javax.swing.*; -import javax.swing.table.TableModel; -import java.util.List; - -public interface AnyTableModelAdapter extends TableModel { - - void sort(List sortKeys); - - Entity getItem(int rowIndex); - - int getRowIndex(Entity entity); - - void addGeneratedColumn(Table.Column column); - - void removeGeneratedColumn(Table.Column column); - - boolean isGeneratedColumn(Table.Column column); - - boolean hasGeneratedColumns(); - - void addColumn(Table.Column column); - - void removeColumn(Table.Column column); - - Table.Column getColumn(int index); - - void addChangeListener(DataChangeListener changeListener); - - void removeChangeListener(DataChangeListener changeListener); - - interface DataChangeListener { - void beforeChange(boolean structureChanged); - - void afterChange(boolean structureChanged); - - void dataSorted(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.gui.components.Table; + +import javax.swing.*; +import javax.swing.table.TableModel; +import java.util.List; + +public interface AnyTableModelAdapter extends TableModel { + + void sort(List sortKeys); + + Entity getItem(int rowIndex); + + int getRowIndex(Entity entity); + + void addGeneratedColumn(Table.Column column); + + void removeGeneratedColumn(Table.Column column); + + boolean isGeneratedColumn(Table.Column column); + + boolean hasGeneratedColumns(); + + void addColumn(Table.Column column); + + void removeColumn(Table.Column column); + + Table.Column getColumn(int index); + + void addChangeListener(DataChangeListener changeListener); + + void removeChangeListener(DataChangeListener changeListener); + + interface DataChangeListener { + void beforeChange(boolean structureChanged); + + void afterChange(boolean structureChanged); + + void dataSorted(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/ComponentSize.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/ComponentSize.java index 92027830f7..270a4e2c18 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/ComponentSize.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/ComponentSize.java @@ -1,74 +1,74 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.cuba.gui.components.Component; - -public class ComponentSize { - - private static final String PIXEL = "px"; - private static final String PERCENT = "%"; - - public final float value; - public final int unit; // Component.UNITS_PIXELS or Component.UNITS_PERCENTAGE - - public ComponentSize(float value, int unit) { - this.value = value; - this.unit = unit; - } - - public ComponentSize(float value) { - this(value, Component.UNITS_PIXELS); - } - - public boolean isOwnSize() { - return value == -1 && unit == Component.UNITS_PIXELS; - } - - public boolean inPixels() { - return unit == Component.UNITS_PIXELS && value != -1; - } - - public boolean inPercents() { - return unit == Component.UNITS_PERCENTAGE; - } - - public static final ComponentSize OWN_SIZE = new ComponentSize(-1); - - public static ComponentSize parse(String sizeString) throws IllegalArgumentException { - if (sizeString == null || sizeString.isEmpty()) { - return ComponentSize.OWN_SIZE; - } - try { - if (sizeString.endsWith(PIXEL)) { - String value = sizeString.substring(0, sizeString.length() - PIXEL.length()); - return new ComponentSize(Float.parseFloat(value), Component.UNITS_PIXELS); - } - else if (sizeString.endsWith(PERCENT)) { - String value = sizeString.substring(0, sizeString.length() - PERCENT.length()); - return new ComponentSize(Float.parseFloat(value), Component.UNITS_PERCENTAGE); - } - else { // default unit - return new ComponentSize(Float.parseFloat(sizeString), Component.UNITS_PIXELS); - } - } - catch (NumberFormatException e) { - throw new IllegalArgumentException("Unable to parse value: " + sizeString); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.cuba.gui.components.Component; + +public class ComponentSize { + + private static final String PIXEL = "px"; + private static final String PERCENT = "%"; + + public final float value; + public final int unit; // Component.UNITS_PIXELS or Component.UNITS_PERCENTAGE + + public ComponentSize(float value, int unit) { + this.value = value; + this.unit = unit; + } + + public ComponentSize(float value) { + this(value, Component.UNITS_PIXELS); + } + + public boolean isOwnSize() { + return value == -1 && unit == Component.UNITS_PIXELS; + } + + public boolean inPixels() { + return unit == Component.UNITS_PIXELS && value != -1; + } + + public boolean inPercents() { + return unit == Component.UNITS_PERCENTAGE; + } + + public static final ComponentSize OWN_SIZE = new ComponentSize(-1); + + public static ComponentSize parse(String sizeString) throws IllegalArgumentException { + if (sizeString == null || sizeString.isEmpty()) { + return ComponentSize.OWN_SIZE; + } + try { + if (sizeString.endsWith(PIXEL)) { + String value = sizeString.substring(0, sizeString.length() - PIXEL.length()); + return new ComponentSize(Float.parseFloat(value), Component.UNITS_PIXELS); + } + else if (sizeString.endsWith(PERCENT)) { + String value = sizeString.substring(0, sizeString.length() - PERCENT.length()); + return new ComponentSize(Float.parseFloat(value), Component.UNITS_PERCENTAGE); + } + else { // default unit + return new ComponentSize(Float.parseFloat(sizeString), Component.UNITS_PIXELS); + } + } + catch (NumberFormatException e) { + throw new IllegalArgumentException("Unable to parse value: " + sizeString); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/DesktopContainerHelper.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/DesktopContainerHelper.java index 9753843c48..00ed87a09e 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/DesktopContainerHelper.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/DesktopContainerHelper.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.cuba.desktop.gui.components.DesktopCheckBox; -import com.haulmont.cuba.desktop.gui.components.DesktopComponent; -import com.haulmont.cuba.desktop.gui.components.DesktopContainer; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Field; -import org.apache.commons.lang.StringUtils; - -public class DesktopContainerHelper { - - public static boolean mayHaveExternalCaption(Component component) { - return (component instanceof Field && !(component instanceof DesktopCheckBox)); - } - - public static boolean hasExternalCaption(Component component) { - if (component instanceof Field && !(component instanceof DesktopCheckBox)) { - final String caption = ((Field) component).getCaption(); - if (StringUtils.isNotEmpty(caption)) { - return true; - } - } - return false; - } - - /** - * Checks for the presence of component description - * - * @param component component to check - * @return true if the component has a description, and false otherwise - */ - public static boolean hasExternalDescription(Component component) { - if (component instanceof Field && !(component instanceof DesktopCheckBox)) { - final String description = ((Field) component).getDescription(); - if (StringUtils.isNotEmpty(description)) { - return true; - } - } - return false; - } - - public static void assignContainer(Component component, DesktopContainer container) { - if (component instanceof DesktopComponent) { - ((DesktopComponent) component).setContainer(container); - } else if (component instanceof Component.Wrapper) { // for frame wrappers - Object wrapped = ((Component.Wrapper) component).getComposition(); - if (wrapped instanceof DesktopComponent) { - ((DesktopComponent) wrapped).setContainer(container); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.cuba.desktop.gui.components.DesktopCheckBox; +import com.haulmont.cuba.desktop.gui.components.DesktopComponent; +import com.haulmont.cuba.desktop.gui.components.DesktopContainer; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Field; +import org.apache.commons.lang.StringUtils; + +public class DesktopContainerHelper { + + public static boolean mayHaveExternalCaption(Component component) { + return (component instanceof Field && !(component instanceof DesktopCheckBox)); + } + + public static boolean hasExternalCaption(Component component) { + if (component instanceof Field && !(component instanceof DesktopCheckBox)) { + final String caption = ((Field) component).getCaption(); + if (StringUtils.isNotEmpty(caption)) { + return true; + } + } + return false; + } + + /** + * Checks for the presence of component description + * + * @param component component to check + * @return true if the component has a description, and false otherwise + */ + public static boolean hasExternalDescription(Component component) { + if (component instanceof Field && !(component instanceof DesktopCheckBox)) { + final String description = ((Field) component).getDescription(); + if (StringUtils.isNotEmpty(description)) { + return true; + } + } + return false; + } + + public static void assignContainer(Component component, DesktopContainer container) { + if (component instanceof DesktopComponent) { + ((DesktopComponent) component).setContainer(container); + } else if (component instanceof Component.Wrapper) { // for frame wrappers + Object wrapped = ((Component.Wrapper) component).getComposition(); + if (wrapped instanceof DesktopComponent) { + ((DesktopComponent) wrapped).setContainer(container); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/RowSorterImpl.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/RowSorterImpl.java index 47d31f85e1..5d7f51b66f 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/RowSorterImpl.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/RowSorterImpl.java @@ -1,139 +1,139 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.gui.components.Table; - -import javax.swing.*; -import java.util.Collections; -import java.util.List; - -public class RowSorterImpl extends RowSorter { - - private AnyTableModelAdapter model; - private SortKey sortKey; - - public RowSorterImpl(AnyTableModelAdapter model) { - this.model = model; - } - - @Override - public AnyTableModelAdapter getModel() { - return model; - } - - @Override - public void toggleSortOrder(int column) { - Table.Column modelColumn = model.getColumn(column); - if (model.isGeneratedColumn(modelColumn)) { - if (!(modelColumn.getId() instanceof MetaPropertyPath)) { - return; - } - } - - SortKey key; - if (sortKey != null && sortKey.getColumn() == column) { - if (sortKey.getSortOrder() == SortOrder.ASCENDING) { - key = new SortKey(sortKey.getColumn(), SortOrder.DESCENDING); - } else { - key = null; - } - } else { - key = new SortKey(column, SortOrder.ASCENDING); - } - if (key == null) - setSortKeys(Collections.emptyList()); - else - setSortKeys(Collections.singletonList(key)); - } - - @Override - public int convertRowIndexToModel(int index) { - return index; - } - - @Override - public int convertRowIndexToView(int index) { - return index; - } - - @Override - public void setSortKeys(List keys) { - if (keys != null && keys.size() > 0) { - int max = model.getColumnCount(); - for (SortKey key : keys) { - if (key == null || key.getColumn() < 0 || key.getColumn() >= max) { - throw new IllegalArgumentException("Invalid SortKey"); - } - - if (!(model.getColumn(key.getColumn()).getId() instanceof MetaPropertyPath)) { - // do not sort by generated columns - return; - } - } - this.sortKey = keys.get(0); - } else { - this.sortKey = null; - } - if (sortKey != null) - model.sort(Collections.singletonList(sortKey)); - } - - @Override - public List getSortKeys() { - if (sortKey == null) - return Collections.emptyList(); - else - return Collections.singletonList(sortKey); - } - - @Override - public int getViewRowCount() { - return model.getRowCount(); - } - - @Override - public int getModelRowCount() { - return model.getRowCount(); - } - - @Override - public void modelStructureChanged() { - } - - @Override - public void allRowsChanged() { - } - - @Override - public void rowsInserted(int firstRow, int endRow) { - } - - @Override - public void rowsDeleted(int firstRow, int endRow) { - } - - @Override - public void rowsUpdated(int firstRow, int endRow) { - } - - @Override - public void rowsUpdated(int firstRow, int endRow, int column) { - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.gui.components.Table; + +import javax.swing.*; +import java.util.Collections; +import java.util.List; + +public class RowSorterImpl extends RowSorter { + + private AnyTableModelAdapter model; + private SortKey sortKey; + + public RowSorterImpl(AnyTableModelAdapter model) { + this.model = model; + } + + @Override + public AnyTableModelAdapter getModel() { + return model; + } + + @Override + public void toggleSortOrder(int column) { + Table.Column modelColumn = model.getColumn(column); + if (model.isGeneratedColumn(modelColumn)) { + if (!(modelColumn.getId() instanceof MetaPropertyPath)) { + return; + } + } + + SortKey key; + if (sortKey != null && sortKey.getColumn() == column) { + if (sortKey.getSortOrder() == SortOrder.ASCENDING) { + key = new SortKey(sortKey.getColumn(), SortOrder.DESCENDING); + } else { + key = null; + } + } else { + key = new SortKey(column, SortOrder.ASCENDING); + } + if (key == null) + setSortKeys(Collections.emptyList()); + else + setSortKeys(Collections.singletonList(key)); + } + + @Override + public int convertRowIndexToModel(int index) { + return index; + } + + @Override + public int convertRowIndexToView(int index) { + return index; + } + + @Override + public void setSortKeys(List keys) { + if (keys != null && keys.size() > 0) { + int max = model.getColumnCount(); + for (SortKey key : keys) { + if (key == null || key.getColumn() < 0 || key.getColumn() >= max) { + throw new IllegalArgumentException("Invalid SortKey"); + } + + if (!(model.getColumn(key.getColumn()).getId() instanceof MetaPropertyPath)) { + // do not sort by generated columns + return; + } + } + this.sortKey = keys.get(0); + } else { + this.sortKey = null; + } + if (sortKey != null) + model.sort(Collections.singletonList(sortKey)); + } + + @Override + public List getSortKeys() { + if (sortKey == null) + return Collections.emptyList(); + else + return Collections.singletonList(sortKey); + } + + @Override + public int getViewRowCount() { + return model.getRowCount(); + } + + @Override + public int getModelRowCount() { + return model.getRowCount(); + } + + @Override + public void modelStructureChanged() { + } + + @Override + public void allRowsChanged() { + } + + @Override + public void rowsInserted(int firstRow, int endRow) { + } + + @Override + public void rowsDeleted(int firstRow, int endRow) { + } + + @Override + public void rowsUpdated(int firstRow, int endRow) { + } + + @Override + public void rowsUpdated(int firstRow, int endRow, int column) { + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TableModelAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TableModelAdapter.java index 3119410d30..a5a2f1dd0b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TableModelAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TableModelAdapter.java @@ -1,406 +1,406 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class TableModelAdapter extends AbstractTableModel implements AnyTableModelAdapter { - - private static final long serialVersionUID = -3892470031734710618L; - - protected CollectionDatasource, Object> datasource; - protected List properties = new ArrayList<>(); - protected List columns; - protected List generatedColumns = new ArrayList<>(); - protected boolean autoRefresh; - protected List changeListeners = new ArrayList<>(); - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; - - protected MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); - protected boolean ignoreUnfetchedAttributes = false; - - public TableModelAdapter(CollectionDatasource datasource, List columns, boolean autoRefresh) { - this.datasource = datasource; - this.columns = columns; - this.autoRefresh = autoRefresh; - - final View view = datasource.getView(); - final MetaClass metaClass = datasource.getMetaClass(); - - if (columns == null) { - createProperties(view, metaClass); - } else { - for (Table.Column column : columns) { - if (column.getId() instanceof MetaPropertyPath) - properties.add((MetaPropertyPath) column.getId()); - } - } - - collectionChangeListener = e -> { - switch (e.getOperation()) { - case ADD: - fireBeforeChangeListeners(true); - for (Object entity : e.getItems()) { - int rowIndex = getRowIndex((Entity) entity); - if (rowIndex >= 0) { - fireTableRowsInserted(rowIndex, rowIndex); - } - } - fireAfterChangeListeners(true); - break; - - case UPDATE: - fireBeforeChangeListeners(false); - for (Object entity : e.getItems()) { - int rowIndex = getRowIndex((Entity) entity); - if (rowIndex >= 0) { - fireTableRowsUpdated(rowIndex, rowIndex); - } - } - fireAfterChangeListeners(false); - break; - - case REMOVE: - case CLEAR: - case REFRESH: - fireBeforeChangeListeners(true); - fireTableDataChanged(); - fireAfterChangeListeners(true); - break; - } - }; - //noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - - itemPropertyChangeListener = e -> { - int rowIndex = getRowIndex(e.getItem()); - - if (rowIndex >= 0) { - fireBeforeChangeListeners(false); - fireTableRowsUpdated(rowIndex, rowIndex); - fireAfterChangeListeners(false); - } - }; - //noinspection unchecked - datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); - - Configuration configuration = AppBeans.get(Configuration.NAME); - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - ignoreUnfetchedAttributes = clientConfig.getIgnoreUnfetchedAttributesInTable(); - } - - protected void fireBeforeChangeListeners(boolean structureChanged) { - for (DataChangeListener changeListener : changeListeners) - changeListener.beforeChange(structureChanged); - } - - protected void fireAfterChangeListeners(boolean structureChanged) { - for (DataChangeListener changeListener : changeListeners) - changeListener.afterChange(structureChanged); - } - - protected void createProperties(View view, MetaClass metaClass) { - properties.addAll(CollectionDsHelper.createProperties(view, metaClass)); - } - - @Override - public int getRowCount() { - CollectionDsHelper.autoRefreshInvalid(datasource, autoRefresh); - return datasource.size(); - } - - @Override - public int getColumnCount() { - return columns.size(); - } - - @Override - public String getColumnName(int column) { - Table.Column c = columns.get(column); - return c.getCaption(); - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - Object id = getItemId(rowIndex); - - Entity item = datasource.getItem(id); - return getValueAt(item, columnIndex); - } - - @SuppressWarnings("unchecked") - public Object getValueAt(Entity item, int columnIndex) { - Table.Column column = columns.get(columnIndex); - if (column.getId() instanceof MetaPropertyPath) { - String property = column.getId().toString(); - - Object value; - if (ignoreUnfetchedAttributes) { - value = getValueExIgnoreUnfetched(item, InstanceUtils.parseValuePath(property)); - } else { - value = item.getValueEx(property); - } - - if (column.getFormatter() != null) { - return column.getFormatter().format(value); - } - - MetaPropertyPath metaProperty = ((MetaPropertyPath) column.getId()); - - boolean isDataType = (metaProperty.getRange().isDatatype()); - if (isDataType && hasDefaultFormatting(metaProperty.getRangeJavaClass())) { - if (value != null) - return value; - else - return getDefaultValue(metaProperty.getRangeJavaClass()); - } else { - if (value == null) - return null; - - return metadataTools.format(value, ((MetaPropertyPath) column.getId()).getMetaProperty()); - } - } else { - return null; - } - } - - protected Object getValueExIgnoreUnfetched(Instance instance, String[] properties) { - Object currentValue = null; - Instance currentInstance = instance; - for (String property : properties) { - if (currentInstance == null) { - break; - } - - if (!PersistenceHelper.isLoaded(currentInstance, property)) { - LoggerFactory.getLogger(TableModelAdapter.class) - .warn("Ignored unfetched attribute {} of instance {} in Table cell", - property, currentInstance); - return null; - } - - currentValue = currentInstance.getValue(property); - if (currentValue == null) { - break; - } - - currentInstance = currentValue instanceof Instance ? (Instance) currentValue : null; - } - return currentValue; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - if (columnIndex == -1) - return false; - Table.Column column = columns.get(columnIndex); - if (column.isEditable() || generatedColumns.contains(column)) - return true; - else - return false; - } - - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - Table.Column column = columns.get(columnIndex); - if (!column.isEditable()) - return; - if (generatedColumns.contains(column)) - return; - - Object id = getItemId(rowIndex); - Entity item = datasource.getItem(id); - - if (column.getId() instanceof MetaPropertyPath) { - String property = column.getId().toString(); - item.setValueEx(property, aValue); - } - } - - public Object getItemId(int rowIndex) { - Object id = null; - if (datasource instanceof CollectionDatasource.Ordered) { - int idx = 0; - id = ((CollectionDatasource.Ordered) datasource).firstItemId(); - while (++idx <= rowIndex) { - id = ((CollectionDatasource.Ordered) datasource).nextItemId(id); - } - } else { - Collection itemIds = datasource.getItemIds(); - int idx = 0; - for (Object itemId : itemIds) { - id = itemId; - if (idx++ == rowIndex) - break; - } - } - return id; - } - - @Override - public Entity getItem(int rowIndex) { - Object itemId = getItemId(rowIndex); - return datasource.getItem(itemId); - } - - @Override - public int getRowIndex(Entity entity) { - int idx = 0; - if (entity != null) { - if (datasource instanceof CollectionDatasource.Ordered) { - Object id = ((CollectionDatasource.Ordered) datasource).firstItemId(); - while (id != null) { - if (entity.equals(datasource.getItem(id))) - return idx; - id = ((CollectionDatasource.Ordered) datasource).nextItemId(id); - idx++; - } - } else { - for (Entity item : datasource.getItems()) { - if (entity.equals(item)) - return idx; - idx++; - } - } - } - return -1; - } - - @Override - public void addGeneratedColumn(Table.Column column) { - generatedColumns.add(column); - } - - @Override - public void removeGeneratedColumn(Table.Column column) { - generatedColumns.remove(column); - } - - @Override - public boolean isGeneratedColumn(Table.Column column) { - return generatedColumns.contains(column); - } - - @Override - public boolean hasGeneratedColumns() { - return !generatedColumns.isEmpty(); - } - - @Override - public void addColumn(Table.Column column) { - columns.add(column); - if (column.getId() instanceof MetaPropertyPath) - properties.add((MetaPropertyPath) column.getId()); - - fireTableStructureChanged(); - } - - @Override - public void removeColumn(Table.Column column) { - columns.remove(column); - if (column.getId() instanceof MetaPropertyPath) - properties.remove((MetaPropertyPath) column.getId()); - - fireTableStructureChanged(); - } - - @Override - public Table.Column getColumn(int index) { - return columns.get(index); - } - - @Override - public void addChangeListener(DataChangeListener changeListener) { - changeListeners.add(changeListener); - } - - @Override - public void removeChangeListener(DataChangeListener changeListener) { - changeListeners.remove(changeListener); - } - - @Override - public void sort(List sortKeys) { - if (!(datasource instanceof CollectionDatasource.Sortable) || sortKeys == null) - return; - - List sortInfos = new ArrayList<>(); - for (RowSorter.SortKey sortKey : sortKeys) { - if (!sortKey.getSortOrder().equals(SortOrder.UNSORTED)) { - Table.Column c = columns.get(sortKey.getColumn()); - CollectionDatasource.Sortable.SortInfo sortInfo = new CollectionDatasource.Sortable.SortInfo<>(); - sortInfo.setPropertyPath(c.getId()); - sortInfo.setOrder(sortKey.getSortOrder().equals(SortOrder.ASCENDING) - ? CollectionDatasource.Sortable.Order.ASC - : CollectionDatasource.Sortable.Order.DESC); - sortInfos.add(sortInfo); - } - } - ((CollectionDatasource.Sortable) datasource).sort( - sortInfos.toArray(new CollectionDatasource.Sortable.SortInfo[sortInfos.size()])); - - fireBeforeChangeListeners(true); - fireTableDataChanged(); - fireAfterChangeListeners(true); - - for (DataChangeListener changeListener : changeListeners) { - changeListener.dataSorted(); - } - } - - @Override - public Class getColumnClass(int columnIndex) { - Table.Column column = columns.get(columnIndex); - Class columnType = column.getType(); - - if (hasDefaultFormatting(columnType)) - return columnType; - return super.getColumnClass(columnIndex); - } - - private boolean hasDefaultFormatting(Class valueClass) { - return Boolean.class.equals(valueClass); - } - - private Object getDefaultValue(Class valueClass) { - if (Boolean.class.equals(valueClass)) - return Boolean.FALSE; - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class TableModelAdapter extends AbstractTableModel implements AnyTableModelAdapter { + + private static final long serialVersionUID = -3892470031734710618L; + + protected CollectionDatasource, Object> datasource; + protected List properties = new ArrayList<>(); + protected List columns; + protected List generatedColumns = new ArrayList<>(); + protected boolean autoRefresh; + protected List changeListeners = new ArrayList<>(); + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener; + + protected MetadataTools metadataTools = AppBeans.get(MetadataTools.NAME); + protected boolean ignoreUnfetchedAttributes = false; + + public TableModelAdapter(CollectionDatasource datasource, List columns, boolean autoRefresh) { + this.datasource = datasource; + this.columns = columns; + this.autoRefresh = autoRefresh; + + final View view = datasource.getView(); + final MetaClass metaClass = datasource.getMetaClass(); + + if (columns == null) { + createProperties(view, metaClass); + } else { + for (Table.Column column : columns) { + if (column.getId() instanceof MetaPropertyPath) + properties.add((MetaPropertyPath) column.getId()); + } + } + + collectionChangeListener = e -> { + switch (e.getOperation()) { + case ADD: + fireBeforeChangeListeners(true); + for (Object entity : e.getItems()) { + int rowIndex = getRowIndex((Entity) entity); + if (rowIndex >= 0) { + fireTableRowsInserted(rowIndex, rowIndex); + } + } + fireAfterChangeListeners(true); + break; + + case UPDATE: + fireBeforeChangeListeners(false); + for (Object entity : e.getItems()) { + int rowIndex = getRowIndex((Entity) entity); + if (rowIndex >= 0) { + fireTableRowsUpdated(rowIndex, rowIndex); + } + } + fireAfterChangeListeners(false); + break; + + case REMOVE: + case CLEAR: + case REFRESH: + fireBeforeChangeListeners(true); + fireTableDataChanged(); + fireAfterChangeListeners(true); + break; + } + }; + //noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + + itemPropertyChangeListener = e -> { + int rowIndex = getRowIndex(e.getItem()); + + if (rowIndex >= 0) { + fireBeforeChangeListeners(false); + fireTableRowsUpdated(rowIndex, rowIndex); + fireAfterChangeListeners(false); + } + }; + //noinspection unchecked + datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener)); + + Configuration configuration = AppBeans.get(Configuration.NAME); + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + ignoreUnfetchedAttributes = clientConfig.getIgnoreUnfetchedAttributesInTable(); + } + + protected void fireBeforeChangeListeners(boolean structureChanged) { + for (DataChangeListener changeListener : changeListeners) + changeListener.beforeChange(structureChanged); + } + + protected void fireAfterChangeListeners(boolean structureChanged) { + for (DataChangeListener changeListener : changeListeners) + changeListener.afterChange(structureChanged); + } + + protected void createProperties(View view, MetaClass metaClass) { + properties.addAll(CollectionDsHelper.createProperties(view, metaClass)); + } + + @Override + public int getRowCount() { + CollectionDsHelper.autoRefreshInvalid(datasource, autoRefresh); + return datasource.size(); + } + + @Override + public int getColumnCount() { + return columns.size(); + } + + @Override + public String getColumnName(int column) { + Table.Column c = columns.get(column); + return c.getCaption(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + Object id = getItemId(rowIndex); + + Entity item = datasource.getItem(id); + return getValueAt(item, columnIndex); + } + + @SuppressWarnings("unchecked") + public Object getValueAt(Entity item, int columnIndex) { + Table.Column column = columns.get(columnIndex); + if (column.getId() instanceof MetaPropertyPath) { + String property = column.getId().toString(); + + Object value; + if (ignoreUnfetchedAttributes) { + value = getValueExIgnoreUnfetched(item, InstanceUtils.parseValuePath(property)); + } else { + value = item.getValueEx(property); + } + + if (column.getFormatter() != null) { + return column.getFormatter().format(value); + } + + MetaPropertyPath metaProperty = ((MetaPropertyPath) column.getId()); + + boolean isDataType = (metaProperty.getRange().isDatatype()); + if (isDataType && hasDefaultFormatting(metaProperty.getRangeJavaClass())) { + if (value != null) + return value; + else + return getDefaultValue(metaProperty.getRangeJavaClass()); + } else { + if (value == null) + return null; + + return metadataTools.format(value, ((MetaPropertyPath) column.getId()).getMetaProperty()); + } + } else { + return null; + } + } + + protected Object getValueExIgnoreUnfetched(Instance instance, String[] properties) { + Object currentValue = null; + Instance currentInstance = instance; + for (String property : properties) { + if (currentInstance == null) { + break; + } + + if (!PersistenceHelper.isLoaded(currentInstance, property)) { + LoggerFactory.getLogger(TableModelAdapter.class) + .warn("Ignored unfetched attribute {} of instance {} in Table cell", + property, currentInstance); + return null; + } + + currentValue = currentInstance.getValue(property); + if (currentValue == null) { + break; + } + + currentInstance = currentValue instanceof Instance ? (Instance) currentValue : null; + } + return currentValue; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + if (columnIndex == -1) + return false; + Table.Column column = columns.get(columnIndex); + if (column.isEditable() || generatedColumns.contains(column)) + return true; + else + return false; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + Table.Column column = columns.get(columnIndex); + if (!column.isEditable()) + return; + if (generatedColumns.contains(column)) + return; + + Object id = getItemId(rowIndex); + Entity item = datasource.getItem(id); + + if (column.getId() instanceof MetaPropertyPath) { + String property = column.getId().toString(); + item.setValueEx(property, aValue); + } + } + + public Object getItemId(int rowIndex) { + Object id = null; + if (datasource instanceof CollectionDatasource.Ordered) { + int idx = 0; + id = ((CollectionDatasource.Ordered) datasource).firstItemId(); + while (++idx <= rowIndex) { + id = ((CollectionDatasource.Ordered) datasource).nextItemId(id); + } + } else { + Collection itemIds = datasource.getItemIds(); + int idx = 0; + for (Object itemId : itemIds) { + id = itemId; + if (idx++ == rowIndex) + break; + } + } + return id; + } + + @Override + public Entity getItem(int rowIndex) { + Object itemId = getItemId(rowIndex); + return datasource.getItem(itemId); + } + + @Override + public int getRowIndex(Entity entity) { + int idx = 0; + if (entity != null) { + if (datasource instanceof CollectionDatasource.Ordered) { + Object id = ((CollectionDatasource.Ordered) datasource).firstItemId(); + while (id != null) { + if (entity.equals(datasource.getItem(id))) + return idx; + id = ((CollectionDatasource.Ordered) datasource).nextItemId(id); + idx++; + } + } else { + for (Entity item : datasource.getItems()) { + if (entity.equals(item)) + return idx; + idx++; + } + } + } + return -1; + } + + @Override + public void addGeneratedColumn(Table.Column column) { + generatedColumns.add(column); + } + + @Override + public void removeGeneratedColumn(Table.Column column) { + generatedColumns.remove(column); + } + + @Override + public boolean isGeneratedColumn(Table.Column column) { + return generatedColumns.contains(column); + } + + @Override + public boolean hasGeneratedColumns() { + return !generatedColumns.isEmpty(); + } + + @Override + public void addColumn(Table.Column column) { + columns.add(column); + if (column.getId() instanceof MetaPropertyPath) + properties.add((MetaPropertyPath) column.getId()); + + fireTableStructureChanged(); + } + + @Override + public void removeColumn(Table.Column column) { + columns.remove(column); + if (column.getId() instanceof MetaPropertyPath) + properties.remove((MetaPropertyPath) column.getId()); + + fireTableStructureChanged(); + } + + @Override + public Table.Column getColumn(int index) { + return columns.get(index); + } + + @Override + public void addChangeListener(DataChangeListener changeListener) { + changeListeners.add(changeListener); + } + + @Override + public void removeChangeListener(DataChangeListener changeListener) { + changeListeners.remove(changeListener); + } + + @Override + public void sort(List sortKeys) { + if (!(datasource instanceof CollectionDatasource.Sortable) || sortKeys == null) + return; + + List sortInfos = new ArrayList<>(); + for (RowSorter.SortKey sortKey : sortKeys) { + if (!sortKey.getSortOrder().equals(SortOrder.UNSORTED)) { + Table.Column c = columns.get(sortKey.getColumn()); + CollectionDatasource.Sortable.SortInfo sortInfo = new CollectionDatasource.Sortable.SortInfo<>(); + sortInfo.setPropertyPath(c.getId()); + sortInfo.setOrder(sortKey.getSortOrder().equals(SortOrder.ASCENDING) + ? CollectionDatasource.Sortable.Order.ASC + : CollectionDatasource.Sortable.Order.DESC); + sortInfos.add(sortInfo); + } + } + ((CollectionDatasource.Sortable) datasource).sort( + sortInfos.toArray(new CollectionDatasource.Sortable.SortInfo[sortInfos.size()])); + + fireBeforeChangeListeners(true); + fireTableDataChanged(); + fireAfterChangeListeners(true); + + for (DataChangeListener changeListener : changeListeners) { + changeListener.dataSorted(); + } + } + + @Override + public Class getColumnClass(int columnIndex) { + Table.Column column = columns.get(columnIndex); + Class columnType = column.getType(); + + if (hasDefaultFormatting(columnType)) + return columnType; + return super.getColumnClass(columnIndex); + } + + private boolean hasDefaultFormatting(Class valueClass) { + return Boolean.class.equals(valueClass); + } + + private Object getDefaultValue(Class valueClass) { + if (Boolean.class.equals(valueClass)) + return Boolean.FALSE; + return null; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeModelAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeModelAdapter.java index 8cbc61c868..f9606a8c0b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeModelAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeModelAdapter.java @@ -1,319 +1,319 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.google.common.collect.Iterables; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.gui.components.CaptionMode; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.HierarchicalDatasource; -import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import org.apache.commons.lang.ObjectUtils; - -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreeModel; -import javax.swing.tree.TreePath; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -public class TreeModelAdapter implements TreeModel { - - protected HierarchicalDatasource, Object> datasource; - - protected Object rootNode = "Root"; - - protected List treeModelListeners = new ArrayList<>(); - - protected CaptionMode captionMode; - protected String captionProperty; - - protected boolean autoRefresh; - - protected MetadataTools metadataTools; - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - public TreeModelAdapter(HierarchicalDatasource datasource, CaptionMode captionMode, String captionProperty, - boolean autoRefresh) { - - this.datasource = datasource; - this.captionMode = captionMode; - - setCaptionProperty(captionProperty); - - this.autoRefresh = autoRefresh; - - this.metadataTools = AppBeans.get(MetadataTools.NAME); - - collectionChangeListener = e -> { - switch (e.getOperation()) { - case CLEAR: - case REFRESH: - case ADD: - case REMOVE: - Object[] path = {getRoot()}; - for (TreeModelListener listener : treeModelListeners) { - TreeModelEvent ev = new TreeModelEvent(this, path); - listener.treeStructureChanged(ev); - } - break; - - case UPDATE: - for (Object item : e.getItems()) { - TreePath treePath = getTreePath(item); - for (TreeModelListener listener : treeModelListeners) { - TreeModelEvent ev = new TreeModelEvent(this, treePath.getPath()); - listener.treeNodesChanged(ev); - } - } - break; - } - }; - //noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - } - - @Override - public Object getRoot() { - CollectionDsHelper.autoRefreshInvalid(datasource, autoRefresh); - return rootNode; - } - - @Override - public Object getChild(Object parent, int index) { - Collection childrenIds; - if (parent == rootNode) { - childrenIds = datasource.getRootItemIds(); - } else { - childrenIds = datasource.getChildren(((Node) parent).getEntity().getId()); - } - Object id = Iterables.get(childrenIds, index); - return new Node(parent, datasource.getItem(id)); - } - - @Override - public int getChildCount(Object parent) { - if (parent == rootNode) { - return datasource.getRootItemIds().size(); - } else { - Entity entity = ((Node) parent).getEntity(); - Collection childrenIds = datasource.getChildren(entity.getId()); - return childrenIds.size(); - } - } - - @Override - public boolean isLeaf(Object node) { - if (node == rootNode) { - return false; - } else { - Entity entity = ((Node) node).getEntity(); - Collection childrenIds = datasource.getChildren(entity.getId()); - return childrenIds.size() == 0; - } - } - - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - if (parent == null || child == null) - return -1; - - Collection childrenIds; - if (parent == rootNode) { - childrenIds = datasource.getRootItemIds(); - } else { - Entity entity = ((Node) parent).getEntity(); - childrenIds = datasource.getChildren(entity.getId()); - } - final Entity childEntity = ((Node) child).getEntity(); - return Iterables.indexOf(childrenIds, id -> childEntity.getId().equals(id)); - } - - @Override - public void addTreeModelListener(TreeModelListener l) { - if (!treeModelListeners.contains(l)) - treeModelListeners.add(l); - } - - @Override - public void removeTreeModelListener(TreeModelListener l) { - treeModelListeners.remove(l); - } - - public void setCaptionMode(CaptionMode captionMode) { - this.captionMode = captionMode; - } - - public void setCaptionProperty(String captionProperty) { - this.captionProperty = captionProperty; - - if (captionProperty != null) { - setCaptionMode(CaptionMode.PROPERTY); - } else { - setCaptionMode(CaptionMode.ITEM); - } - } - - public Node createNode(Entity entity) { - return new Node(entity); - } - - public Entity getEntity(Object object) { - if (object instanceof Entity) { - return (Entity) object; - } else if (object instanceof Node) { - return ((Node) object).getEntity(); - } else - return null; - } - - public TreePath getTreePath(Object object) { - List list = new ArrayList<>(); - if (object instanceof Entity) { - Node node = createNode((Entity) object); - list.add(node); - if (datasource.getHierarchyPropertyName() != null) { - Entity entity = (Entity) object; - while (entity.getValue(datasource.getHierarchyPropertyName()) != null) { - Entity parent = entity.getValue(datasource.getHierarchyPropertyName()); - // noinspection ConstantConditions - if (!datasource.containsItem(parent.getId())) { - break; // Child entities with removed parent are happen to be thrown to tree root. - } - entity = datasource.getItemNN(parent.getId()); - - Node parentNode = createNode(entity); - list.add(0, parentNode); - node.setParent(parentNode); - node = parentNode; - } - } else { - List treePath = getTreePath(getRoot(), (Entity) object); - if (treePath != null) { - treePath.add(0, rootNode); - return new TreePath(treePath.toArray()); - } - } - list.add(0, rootNode); - node.setParent(rootNode); - } else if (object instanceof Node) { - list.add(object); - Node n = (Node) object; - while (n.getParent() != null) { - Object parent = n.getParent(); - list.add(0, parent); - if (!(parent instanceof Node)) - break; - else - n = (Node) parent; - } - } else { - list.add(object); - } - return new TreePath(list.toArray(new Object[list.size()])); - } - - public List getTreePath(Object node, Entity entity) { - for (int i = 0; i < getChildCount(node); i++) { - Node child = (Node) getChild(node, i); - if (ObjectUtils.equals(entity, child.entity)) { - List list = new LinkedList<>(); - list.add(createNode(entity)); - return list; - } else { - List path = getTreePath(child, entity); - if (path != null) { - path.add(0, child); - return path; - } - } - } - return null; - } - - public class Node { - private Entity entity; - private Object parent; - - public Node(Entity entity) { - this(null, entity); - } - - public Node(Object parent, Entity entity) { - if (entity == null) - throw new IllegalArgumentException("item must not be null"); - this.parent = parent; - this.entity = entity; - } - - public Entity getEntity() { - return entity; - } - - public Object getParent() { - return parent; - } - - public void setParent(Object parent) { - this.parent = parent; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Node node = (Node) o; - - return entity.equals(node.entity); - - } - - @Override - public int hashCode() { - return entity.hashCode(); - } - - @Override - public String toString() { - String value; - if (captionMode.equals(CaptionMode.ITEM)) { - value = entity.getInstanceName(); - } else { - MetaPropertyPath propertyPath = entity.getMetaClass().getPropertyPath(captionProperty); - if (propertyPath != null) { - return metadataTools.format(entity.getValueEx(captionProperty), propertyPath.getMetaProperty()); - } else { - throw new IllegalArgumentException(String.format("Can't find property for given caption property: %s", captionProperty)); - } - } - return value; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.google.common.collect.Iterables; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.gui.components.CaptionMode; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.HierarchicalDatasource; +import com.haulmont.cuba.gui.data.impl.CollectionDsHelper; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import org.apache.commons.lang.ObjectUtils; + +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public class TreeModelAdapter implements TreeModel { + + protected HierarchicalDatasource, Object> datasource; + + protected Object rootNode = "Root"; + + protected List treeModelListeners = new ArrayList<>(); + + protected CaptionMode captionMode; + protected String captionProperty; + + protected boolean autoRefresh; + + protected MetadataTools metadataTools; + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + public TreeModelAdapter(HierarchicalDatasource datasource, CaptionMode captionMode, String captionProperty, + boolean autoRefresh) { + + this.datasource = datasource; + this.captionMode = captionMode; + + setCaptionProperty(captionProperty); + + this.autoRefresh = autoRefresh; + + this.metadataTools = AppBeans.get(MetadataTools.NAME); + + collectionChangeListener = e -> { + switch (e.getOperation()) { + case CLEAR: + case REFRESH: + case ADD: + case REMOVE: + Object[] path = {getRoot()}; + for (TreeModelListener listener : treeModelListeners) { + TreeModelEvent ev = new TreeModelEvent(this, path); + listener.treeStructureChanged(ev); + } + break; + + case UPDATE: + for (Object item : e.getItems()) { + TreePath treePath = getTreePath(item); + for (TreeModelListener listener : treeModelListeners) { + TreeModelEvent ev = new TreeModelEvent(this, treePath.getPath()); + listener.treeNodesChanged(ev); + } + } + break; + } + }; + //noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + } + + @Override + public Object getRoot() { + CollectionDsHelper.autoRefreshInvalid(datasource, autoRefresh); + return rootNode; + } + + @Override + public Object getChild(Object parent, int index) { + Collection childrenIds; + if (parent == rootNode) { + childrenIds = datasource.getRootItemIds(); + } else { + childrenIds = datasource.getChildren(((Node) parent).getEntity().getId()); + } + Object id = Iterables.get(childrenIds, index); + return new Node(parent, datasource.getItem(id)); + } + + @Override + public int getChildCount(Object parent) { + if (parent == rootNode) { + return datasource.getRootItemIds().size(); + } else { + Entity entity = ((Node) parent).getEntity(); + Collection childrenIds = datasource.getChildren(entity.getId()); + return childrenIds.size(); + } + } + + @Override + public boolean isLeaf(Object node) { + if (node == rootNode) { + return false; + } else { + Entity entity = ((Node) node).getEntity(); + Collection childrenIds = datasource.getChildren(entity.getId()); + return childrenIds.size() == 0; + } + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + if (parent == null || child == null) + return -1; + + Collection childrenIds; + if (parent == rootNode) { + childrenIds = datasource.getRootItemIds(); + } else { + Entity entity = ((Node) parent).getEntity(); + childrenIds = datasource.getChildren(entity.getId()); + } + final Entity childEntity = ((Node) child).getEntity(); + return Iterables.indexOf(childrenIds, id -> childEntity.getId().equals(id)); + } + + @Override + public void addTreeModelListener(TreeModelListener l) { + if (!treeModelListeners.contains(l)) + treeModelListeners.add(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + treeModelListeners.remove(l); + } + + public void setCaptionMode(CaptionMode captionMode) { + this.captionMode = captionMode; + } + + public void setCaptionProperty(String captionProperty) { + this.captionProperty = captionProperty; + + if (captionProperty != null) { + setCaptionMode(CaptionMode.PROPERTY); + } else { + setCaptionMode(CaptionMode.ITEM); + } + } + + public Node createNode(Entity entity) { + return new Node(entity); + } + + public Entity getEntity(Object object) { + if (object instanceof Entity) { + return (Entity) object; + } else if (object instanceof Node) { + return ((Node) object).getEntity(); + } else + return null; + } + + public TreePath getTreePath(Object object) { + List list = new ArrayList<>(); + if (object instanceof Entity) { + Node node = createNode((Entity) object); + list.add(node); + if (datasource.getHierarchyPropertyName() != null) { + Entity entity = (Entity) object; + while (entity.getValue(datasource.getHierarchyPropertyName()) != null) { + Entity parent = entity.getValue(datasource.getHierarchyPropertyName()); + // noinspection ConstantConditions + if (!datasource.containsItem(parent.getId())) { + break; // Child entities with removed parent are happen to be thrown to tree root. + } + entity = datasource.getItemNN(parent.getId()); + + Node parentNode = createNode(entity); + list.add(0, parentNode); + node.setParent(parentNode); + node = parentNode; + } + } else { + List treePath = getTreePath(getRoot(), (Entity) object); + if (treePath != null) { + treePath.add(0, rootNode); + return new TreePath(treePath.toArray()); + } + } + list.add(0, rootNode); + node.setParent(rootNode); + } else if (object instanceof Node) { + list.add(object); + Node n = (Node) object; + while (n.getParent() != null) { + Object parent = n.getParent(); + list.add(0, parent); + if (!(parent instanceof Node)) + break; + else + n = (Node) parent; + } + } else { + list.add(object); + } + return new TreePath(list.toArray(new Object[list.size()])); + } + + public List getTreePath(Object node, Entity entity) { + for (int i = 0; i < getChildCount(node); i++) { + Node child = (Node) getChild(node, i); + if (ObjectUtils.equals(entity, child.entity)) { + List list = new LinkedList<>(); + list.add(createNode(entity)); + return list; + } else { + List path = getTreePath(child, entity); + if (path != null) { + path.add(0, child); + return path; + } + } + } + return null; + } + + public class Node { + private Entity entity; + private Object parent; + + public Node(Entity entity) { + this(null, entity); + } + + public Node(Object parent, Entity entity) { + if (entity == null) + throw new IllegalArgumentException("item must not be null"); + this.parent = parent; + this.entity = entity; + } + + public Entity getEntity() { + return entity; + } + + public Object getParent() { + return parent; + } + + public void setParent(Object parent) { + this.parent = parent; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Node node = (Node) o; + + return entity.equals(node.entity); + + } + + @Override + public int hashCode() { + return entity.hashCode(); + } + + @Override + public String toString() { + String value; + if (captionMode.equals(CaptionMode.ITEM)) { + value = entity.getInstanceName(); + } else { + MetaPropertyPath propertyPath = entity.getMetaClass().getPropertyPath(captionProperty); + if (propertyPath != null) { + return metadataTools.format(entity.getValueEx(captionProperty), propertyPath.getMetaProperty()); + } else { + throw new IllegalArgumentException(String.format("Can't find property for given caption property: %s", captionProperty)); + } + } + return value; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeTableModelAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeTableModelAdapter.java index 55917d54f8..33e4774817 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeTableModelAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/data/TreeTableModelAdapter.java @@ -1,232 +1,232 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.data; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.desktop.sys.vcl.JXTreeTableExt; -import com.haulmont.cuba.gui.components.CaptionMode; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.HierarchicalDatasource; -import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; -import org.jdesktop.swingx.JXTreeTable; -import org.jdesktop.swingx.treetable.AbstractTreeTableModel; - -import javax.swing.*; -import javax.swing.event.TableModelListener; -import javax.swing.tree.TreePath; -import java.util.ArrayList; -import java.util.List; - -public class TreeTableModelAdapter extends AbstractTreeTableModel implements AnyTableModelAdapter { - - protected JXTreeTable treeTable; - protected TreeModelAdapter treeDelegate; - protected TableModelAdapter tableDelegate; - - protected List changeListeners = new ArrayList<>(); - - protected CollectionDatasource.CollectionChangeListener collectionChangeListener; - - public TreeTableModelAdapter(JXTreeTable treeTable, HierarchicalDatasource datasource, List columns, - boolean autoRefresh) { - - this.treeTable = treeTable; - this.treeDelegate = createTreeModelAdapter(datasource, autoRefresh); - this.tableDelegate = new TableModelAdapter(datasource, columns, autoRefresh); - - collectionChangeListener = e -> { - Object root1 = getRoot(); - // Fixes #1160 - JXTreeTableExt impl = (JXTreeTableExt) TreeTableModelAdapter.this.treeTable; - impl.setAutoCreateColumnsFromModel(false); - impl.backupExpandedNodes(); - - for (DataChangeListener changeListener : changeListeners) { - changeListener.beforeChange(true); - } - - modelSupport.fireTreeStructureChanged(root1 == null ? null : new TreePath(root1)); - }; - //noinspection unchecked - datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); - } - - protected TreeModelAdapter createTreeModelAdapter(HierarchicalDatasource datasource, boolean autoRefresh) { - return new TreeModelAdapter(datasource, CaptionMode.ITEM, null, autoRefresh); - } - - @Override - public int getColumnCount() { - return tableDelegate.getColumnCount(); - } - - @Override - public String getColumnName(int column) { - return tableDelegate.getColumnName(column); - } - - @Override - public boolean isCellEditable(Object node, int column) { - return tableDelegate.isCellEditable(0, column); - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return tableDelegate.isCellEditable(rowIndex, columnIndex); - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return tableDelegate.getValueAt(rowIndex, columnIndex); - } - - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - tableDelegate.setValueAt(aValue, rowIndex, columnIndex); - } - - @Override - public void addTableModelListener(TableModelListener l) { - tableDelegate.addTableModelListener(l); - } - - @Override - public void removeTableModelListener(TableModelListener l) { - tableDelegate.removeTableModelListener(l); - } - - @Override - public void sort(List sortKeys) { - tableDelegate.sort(sortKeys); - } - - @Override - public int getRowCount() { - return tableDelegate.getRowCount(); - } - - @Override - public Entity getItem(int rowIndex) { - TreePath treePath = treeTable.getPathForRow(rowIndex); - return treeDelegate.getEntity(treePath.getLastPathComponent()); - } - - @Override - public int getRowIndex(Entity entity) { - TreePath treePath = getTreePath(entity); - return treeTable.getRowForPath(treePath); - } - - @Override - public void addGeneratedColumn(Table.Column column) { - tableDelegate.addGeneratedColumn(column); - } - - @Override - public void removeGeneratedColumn(Table.Column column) { - tableDelegate.removeGeneratedColumn(column); - } - - @Override - public boolean isGeneratedColumn(Table.Column column) { - return tableDelegate.isGeneratedColumn(column); - } - - @Override - public boolean hasGeneratedColumns() { - return tableDelegate.hasGeneratedColumns(); - } - - @Override - public void addColumn(Table.Column column) { - } - - @Override - public void removeColumn(Table.Column column) { - } - - @Override - public Table.Column getColumn(int index) { - return tableDelegate.getColumn(index); - } - - @Override - public void addChangeListener(DataChangeListener changeListener) { - changeListeners.add(changeListener); - } - - @Override - public void removeChangeListener(DataChangeListener changeListener) { - changeListeners.remove(changeListener); - } - - @Override - public Object getValueAt(Object node, int column) { - Entity entity = treeDelegate.getEntity(node); - if (entity == null) { - return column == 0 ? node : null; - } - return tableDelegate.getValueAt(entity, column); - } - - @Override - public Object getRoot() { - return treeDelegate.getRoot(); - } - - @Override - public Object getChild(Object parent, int index) { - return treeDelegate.getChild(parent, index); - } - - @Override - public int getChildCount(Object parent) { - return treeDelegate.getChildCount(parent); - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - return treeDelegate.getIndexOfChild(parent, child); - } - - public TreePath getTreePath(Object object) { - return treeDelegate.getTreePath(object); - } - - public Entity getEntity(Object object) { - return treeDelegate.getEntity(object); - } - - @Override - public Class getColumnClass(int column) { - return tableDelegate.getColumnClass(column); - } - - public void beforeDelayedStructureChange() { - } - - public void afterDelayedStructureChange() { - JXTreeTableExt impl = (JXTreeTableExt) TreeTableModelAdapter.this.treeTable; - impl.restoreExpandedNodes(); - - for (DataChangeListener changeListener : changeListeners) { - changeListener.afterChange(true); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.data; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.desktop.sys.vcl.JXTreeTableExt; +import com.haulmont.cuba.gui.components.CaptionMode; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.HierarchicalDatasource; +import com.haulmont.cuba.gui.data.impl.WeakCollectionChangeListener; +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.treetable.AbstractTreeTableModel; + +import javax.swing.*; +import javax.swing.event.TableModelListener; +import javax.swing.tree.TreePath; +import java.util.ArrayList; +import java.util.List; + +public class TreeTableModelAdapter extends AbstractTreeTableModel implements AnyTableModelAdapter { + + protected JXTreeTable treeTable; + protected TreeModelAdapter treeDelegate; + protected TableModelAdapter tableDelegate; + + protected List changeListeners = new ArrayList<>(); + + protected CollectionDatasource.CollectionChangeListener collectionChangeListener; + + public TreeTableModelAdapter(JXTreeTable treeTable, HierarchicalDatasource datasource, List columns, + boolean autoRefresh) { + + this.treeTable = treeTable; + this.treeDelegate = createTreeModelAdapter(datasource, autoRefresh); + this.tableDelegate = new TableModelAdapter(datasource, columns, autoRefresh); + + collectionChangeListener = e -> { + Object root1 = getRoot(); + // Fixes #1160 + JXTreeTableExt impl = (JXTreeTableExt) TreeTableModelAdapter.this.treeTable; + impl.setAutoCreateColumnsFromModel(false); + impl.backupExpandedNodes(); + + for (DataChangeListener changeListener : changeListeners) { + changeListener.beforeChange(true); + } + + modelSupport.fireTreeStructureChanged(root1 == null ? null : new TreePath(root1)); + }; + //noinspection unchecked + datasource.addCollectionChangeListener(new WeakCollectionChangeListener(datasource, collectionChangeListener)); + } + + protected TreeModelAdapter createTreeModelAdapter(HierarchicalDatasource datasource, boolean autoRefresh) { + return new TreeModelAdapter(datasource, CaptionMode.ITEM, null, autoRefresh); + } + + @Override + public int getColumnCount() { + return tableDelegate.getColumnCount(); + } + + @Override + public String getColumnName(int column) { + return tableDelegate.getColumnName(column); + } + + @Override + public boolean isCellEditable(Object node, int column) { + return tableDelegate.isCellEditable(0, column); + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return tableDelegate.isCellEditable(rowIndex, columnIndex); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return tableDelegate.getValueAt(rowIndex, columnIndex); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + tableDelegate.setValueAt(aValue, rowIndex, columnIndex); + } + + @Override + public void addTableModelListener(TableModelListener l) { + tableDelegate.addTableModelListener(l); + } + + @Override + public void removeTableModelListener(TableModelListener l) { + tableDelegate.removeTableModelListener(l); + } + + @Override + public void sort(List sortKeys) { + tableDelegate.sort(sortKeys); + } + + @Override + public int getRowCount() { + return tableDelegate.getRowCount(); + } + + @Override + public Entity getItem(int rowIndex) { + TreePath treePath = treeTable.getPathForRow(rowIndex); + return treeDelegate.getEntity(treePath.getLastPathComponent()); + } + + @Override + public int getRowIndex(Entity entity) { + TreePath treePath = getTreePath(entity); + return treeTable.getRowForPath(treePath); + } + + @Override + public void addGeneratedColumn(Table.Column column) { + tableDelegate.addGeneratedColumn(column); + } + + @Override + public void removeGeneratedColumn(Table.Column column) { + tableDelegate.removeGeneratedColumn(column); + } + + @Override + public boolean isGeneratedColumn(Table.Column column) { + return tableDelegate.isGeneratedColumn(column); + } + + @Override + public boolean hasGeneratedColumns() { + return tableDelegate.hasGeneratedColumns(); + } + + @Override + public void addColumn(Table.Column column) { + } + + @Override + public void removeColumn(Table.Column column) { + } + + @Override + public Table.Column getColumn(int index) { + return tableDelegate.getColumn(index); + } + + @Override + public void addChangeListener(DataChangeListener changeListener) { + changeListeners.add(changeListener); + } + + @Override + public void removeChangeListener(DataChangeListener changeListener) { + changeListeners.remove(changeListener); + } + + @Override + public Object getValueAt(Object node, int column) { + Entity entity = treeDelegate.getEntity(node); + if (entity == null) { + return column == 0 ? node : null; + } + return tableDelegate.getValueAt(entity, column); + } + + @Override + public Object getRoot() { + return treeDelegate.getRoot(); + } + + @Override + public Object getChild(Object parent, int index) { + return treeDelegate.getChild(parent, index); + } + + @Override + public int getChildCount(Object parent) { + return treeDelegate.getChildCount(parent); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return treeDelegate.getIndexOfChild(parent, child); + } + + public TreePath getTreePath(Object object) { + return treeDelegate.getTreePath(object); + } + + public Entity getEntity(Object object) { + return treeDelegate.getEntity(object); + } + + @Override + public Class getColumnClass(int column) { + return tableDelegate.getColumnClass(column); + } + + public void beforeDelayedStructureChange() { + } + + public void afterDelayedStructureChange() { + JXTreeTableExt impl = (JXTreeTableExt) TreeTableModelAdapter.this.treeTable; + impl.restoreExpandedNodes(); + + for (DataChangeListener changeListener : changeListeners) { + changeListener.afterChange(true); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopBackgroundWorker.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopBackgroundWorker.java index dc01288b40..48a4e2f2aa 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopBackgroundWorker.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopBackgroundWorker.java @@ -1,316 +1,316 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.executors.impl; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Events; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.gui.event.BackgroundTaskUnhandledExceptionEvent; -import com.haulmont.cuba.gui.executors.*; -import com.haulmont.cuba.gui.executors.impl.TaskExecutor; -import com.haulmont.cuba.gui.executors.impl.TaskHandlerImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nonnull; -import javax.inject.Inject; -import javax.swing.*; -import java.lang.reflect.InvocationTargetException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Desktop implementation of {@link BackgroundWorker} - */ -@Component(BackgroundWorker.NAME) -public class DesktopBackgroundWorker implements BackgroundWorker { - - private Logger log = LoggerFactory.getLogger(DesktopBackgroundWorker.class); - - private WatchDog watchDog; - - @Inject - private Events events; - - @Inject - public DesktopBackgroundWorker(WatchDog watchDog) { - this.watchDog = watchDog; - } - - @Override - public BackgroundTaskHandler handle(BackgroundTask task) { - checkNotNull(task); - checkUIAccess(); - - // create task handler - DesktopTaskExecutor taskExecutor = new DesktopTaskExecutor<>(task); - TaskHandlerImpl taskHandler = new TaskHandlerImpl<>(getUIAccessor(), taskExecutor, watchDog); - - taskExecutor.setTaskHandler(taskHandler); - - return taskHandler; - } - - @Override - public UIAccessor getUIAccessor() { - checkUIAccess(); - - return new DesktopUIAccessor(); - } - - @Override - public void checkUIAccess() { - if (!SwingUtilities.isEventDispatchThread()) { - throw new IllegalConcurrentAccessException(); - } - } - - public static void checkSwingUIAccess() { - if (!SwingUtilities.isEventDispatchThread()) { - throw new IllegalConcurrentAccessException(); - } - } - - /** - * Task runner - */ - private class DesktopTaskExecutor extends SwingWorker implements TaskExecutor { - - private BackgroundTask runnableTask; - private Runnable finalizer; - - private volatile V result; - private volatile Exception taskException = null; - - private UUID userId; - - private volatile boolean isClosed = false; - private volatile boolean doneHandled = false; - - private Map params; - private TaskHandlerImpl taskHandler; - - private DesktopTaskExecutor(BackgroundTask runnableTask) { - this.runnableTask = runnableTask; - - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - this.userId = sessionSource.getUserSession().getId(); - - this.params = runnableTask.getParams() != null ? - Collections.unmodifiableMap(runnableTask.getParams()) : - Collections.emptyMap(); - } - - @Override - protected final V doInBackground() throws Exception { - Thread.currentThread().setName(String.format("BackgroundTaskThread-%s", - System.identityHashCode(Thread.currentThread()))); - try { - if (!Thread.currentThread().isInterrupted()) { - // do not run any activity if canceled before start - result = runnableTask.run(new TaskLifeCycle() { - @SafeVarargs - @Override - public final void publish(T... changes) throws InterruptedException { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException("Task is interrupted and is trying to publish changes"); - } - - handleProgress(changes); - } - - @Override - public boolean isInterrupted() { - return Thread.currentThread().isInterrupted(); - } - - @Override - @Nonnull - public Map getParams() { - return params; - } - }); - } - } catch (Exception ex) { - // do not call log.error, exception may be handled later - log.debug("Exception occurred in background task. Task: {}", runnableTask, ex); - if (!(ex instanceof InterruptedException) && !isCancelled()) { - taskException = ex; - } - } finally { - watchDog.removeTask(taskHandler); - } - - return result; - } - - @Override - protected final void process(List chunks) { - runnableTask.progress(chunks); - // Notify listeners - for (BackgroundTask.ProgressListener listener : runnableTask.getProgressListeners()) { - listener.onProgress(chunks); - } - } - - @Override - protected final void done() { - if (isCancelled()) { - // handle cancel from edt before execution start - log.trace("Done statement is not processed because it is canceled task. Task: {}", runnableTask); - return; - } - - if (isClosed) { - log.trace("Done statement is not processed because it is already closed. Task: {}", runnableTask); - return; - } - - log.debug("Done task: {}. User: {}", runnableTask, userId); - - try { - if (this.taskException == null) { - runnableTask.done(result); - // Notify listeners - for (BackgroundTask.ProgressListener listener : runnableTask.getProgressListeners()) { - listener.onDone(result); - } - } else { - boolean handled = runnableTask.handleException(taskException); - if (!handled) { - log.error("Unhandled exception in background task. Task: {}", runnableTask, taskException); - events.publish(new BackgroundTaskUnhandledExceptionEvent(this, runnableTask, taskException)); - } - } - - log.trace("Task finished correctly. Task: {}", runnableTask); - } finally { - if (finalizer != null) { - finalizer.run(); - finalizer = null; - } - - isClosed = true; - doneHandled = true; - } - } - - @Override - public final void startExecution() { - execute(); - } - - @Override - public final boolean cancelExecution() { - if (isClosed) { - log.trace("Cancel will not be processed because it is already closed. Task: {}", runnableTask); - return false; - } - - log.debug("Cancel task. Task: {}. User: {}", runnableTask, userId); - - boolean isCanceledNow = cancel(true); - - if (isCanceledNow) { - log.trace("Task was cancelled. Task: {}. User: {}", runnableTask, userId); - } else { - log.trace("Cancellation of task isn't processed. Task: {}. User: {}", runnableTask, userId); - } - - if (!doneHandled) { - log.trace("Done was not handled. Return 'true' as canceled status. Task: {}. User: {}", - runnableTask, userId); - - this.isClosed = true; - return true; - } - - return isCanceledNow; - } - - @Override - public final V getResult() { - V result; - try { - result = get(); - } catch (InterruptedException | ExecutionException | CancellationException e) { - log.debug("{} exception in background task: {}", e.getClass().getName(), - runnableTask, e); - return null; - } - - this.done(); - - return result; - } - - @Override - public final BackgroundTask getTask() { - return runnableTask; - } - - @Override - public final boolean inProgress() { - return !isClosed; - } - - @Override - public final void setFinalizer(Runnable finalizer) { - this.finalizer = finalizer; - } - - @Override - public final Runnable getFinalizer() { - return finalizer; - } - - @SafeVarargs - @Override - public final void handleProgress(T... changes) { - publish(changes); - } - - public void setTaskHandler(TaskHandlerImpl taskHandler) { - this.taskHandler = taskHandler; - } - } - - private static class DesktopUIAccessor implements UIAccessor { - @Override - public void access(Runnable runnable) { - SwingUtilities.invokeLater(runnable); - } - - @Override - public void accessSynchronously(Runnable runnable) { - try { - SwingUtilities.invokeAndWait(runnable); - } catch (InterruptedException | InvocationTargetException e) { - throw new RuntimeException("Exception on access to UI from background thread", e); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.executors.impl; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Events; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.gui.event.BackgroundTaskUnhandledExceptionEvent; +import com.haulmont.cuba.gui.executors.*; +import com.haulmont.cuba.gui.executors.impl.TaskExecutor; +import com.haulmont.cuba.gui.executors.impl.TaskHandlerImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nonnull; +import javax.inject.Inject; +import javax.swing.*; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Desktop implementation of {@link BackgroundWorker} + */ +@Component(BackgroundWorker.NAME) +public class DesktopBackgroundWorker implements BackgroundWorker { + + private Logger log = LoggerFactory.getLogger(DesktopBackgroundWorker.class); + + private WatchDog watchDog; + + @Inject + private Events events; + + @Inject + public DesktopBackgroundWorker(WatchDog watchDog) { + this.watchDog = watchDog; + } + + @Override + public BackgroundTaskHandler handle(BackgroundTask task) { + checkNotNull(task); + checkUIAccess(); + + // create task handler + DesktopTaskExecutor taskExecutor = new DesktopTaskExecutor<>(task); + TaskHandlerImpl taskHandler = new TaskHandlerImpl<>(getUIAccessor(), taskExecutor, watchDog); + + taskExecutor.setTaskHandler(taskHandler); + + return taskHandler; + } + + @Override + public UIAccessor getUIAccessor() { + checkUIAccess(); + + return new DesktopUIAccessor(); + } + + @Override + public void checkUIAccess() { + if (!SwingUtilities.isEventDispatchThread()) { + throw new IllegalConcurrentAccessException(); + } + } + + public static void checkSwingUIAccess() { + if (!SwingUtilities.isEventDispatchThread()) { + throw new IllegalConcurrentAccessException(); + } + } + + /** + * Task runner + */ + private class DesktopTaskExecutor extends SwingWorker implements TaskExecutor { + + private BackgroundTask runnableTask; + private Runnable finalizer; + + private volatile V result; + private volatile Exception taskException = null; + + private UUID userId; + + private volatile boolean isClosed = false; + private volatile boolean doneHandled = false; + + private Map params; + private TaskHandlerImpl taskHandler; + + private DesktopTaskExecutor(BackgroundTask runnableTask) { + this.runnableTask = runnableTask; + + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + this.userId = sessionSource.getUserSession().getId(); + + this.params = runnableTask.getParams() != null ? + Collections.unmodifiableMap(runnableTask.getParams()) : + Collections.emptyMap(); + } + + @Override + protected final V doInBackground() throws Exception { + Thread.currentThread().setName(String.format("BackgroundTaskThread-%s", + System.identityHashCode(Thread.currentThread()))); + try { + if (!Thread.currentThread().isInterrupted()) { + // do not run any activity if canceled before start + result = runnableTask.run(new TaskLifeCycle() { + @SafeVarargs + @Override + public final void publish(T... changes) throws InterruptedException { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException("Task is interrupted and is trying to publish changes"); + } + + handleProgress(changes); + } + + @Override + public boolean isInterrupted() { + return Thread.currentThread().isInterrupted(); + } + + @Override + @Nonnull + public Map getParams() { + return params; + } + }); + } + } catch (Exception ex) { + // do not call log.error, exception may be handled later + log.debug("Exception occurred in background task. Task: {}", runnableTask, ex); + if (!(ex instanceof InterruptedException) && !isCancelled()) { + taskException = ex; + } + } finally { + watchDog.removeTask(taskHandler); + } + + return result; + } + + @Override + protected final void process(List chunks) { + runnableTask.progress(chunks); + // Notify listeners + for (BackgroundTask.ProgressListener listener : runnableTask.getProgressListeners()) { + listener.onProgress(chunks); + } + } + + @Override + protected final void done() { + if (isCancelled()) { + // handle cancel from edt before execution start + log.trace("Done statement is not processed because it is canceled task. Task: {}", runnableTask); + return; + } + + if (isClosed) { + log.trace("Done statement is not processed because it is already closed. Task: {}", runnableTask); + return; + } + + log.debug("Done task: {}. User: {}", runnableTask, userId); + + try { + if (this.taskException == null) { + runnableTask.done(result); + // Notify listeners + for (BackgroundTask.ProgressListener listener : runnableTask.getProgressListeners()) { + listener.onDone(result); + } + } else { + boolean handled = runnableTask.handleException(taskException); + if (!handled) { + log.error("Unhandled exception in background task. Task: {}", runnableTask, taskException); + events.publish(new BackgroundTaskUnhandledExceptionEvent(this, runnableTask, taskException)); + } + } + + log.trace("Task finished correctly. Task: {}", runnableTask); + } finally { + if (finalizer != null) { + finalizer.run(); + finalizer = null; + } + + isClosed = true; + doneHandled = true; + } + } + + @Override + public final void startExecution() { + execute(); + } + + @Override + public final boolean cancelExecution() { + if (isClosed) { + log.trace("Cancel will not be processed because it is already closed. Task: {}", runnableTask); + return false; + } + + log.debug("Cancel task. Task: {}. User: {}", runnableTask, userId); + + boolean isCanceledNow = cancel(true); + + if (isCanceledNow) { + log.trace("Task was cancelled. Task: {}. User: {}", runnableTask, userId); + } else { + log.trace("Cancellation of task isn't processed. Task: {}. User: {}", runnableTask, userId); + } + + if (!doneHandled) { + log.trace("Done was not handled. Return 'true' as canceled status. Task: {}. User: {}", + runnableTask, userId); + + this.isClosed = true; + return true; + } + + return isCanceledNow; + } + + @Override + public final V getResult() { + V result; + try { + result = get(); + } catch (InterruptedException | ExecutionException | CancellationException e) { + log.debug("{} exception in background task: {}", e.getClass().getName(), + runnableTask, e); + return null; + } + + this.done(); + + return result; + } + + @Override + public final BackgroundTask getTask() { + return runnableTask; + } + + @Override + public final boolean inProgress() { + return !isClosed; + } + + @Override + public final void setFinalizer(Runnable finalizer) { + this.finalizer = finalizer; + } + + @Override + public final Runnable getFinalizer() { + return finalizer; + } + + @SafeVarargs + @Override + public final void handleProgress(T... changes) { + publish(changes); + } + + public void setTaskHandler(TaskHandlerImpl taskHandler) { + this.taskHandler = taskHandler; + } + } + + private static class DesktopUIAccessor implements UIAccessor { + @Override + public void access(Runnable runnable) { + SwingUtilities.invokeLater(runnable); + } + + @Override + public void accessSynchronously(Runnable runnable) { + try { + SwingUtilities.invokeAndWait(runnable); + } catch (InterruptedException | InvocationTargetException e) { + throw new RuntimeException("Exception on access to UI from background thread", e); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopTasksWatchDog.java b/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopTasksWatchDog.java index 6c4d755803..da077c3980 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopTasksWatchDog.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/gui/executors/impl/DesktopTasksWatchDog.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.gui.executors.impl; - -import com.haulmont.cuba.gui.executors.impl.TaskHandlerImpl; -import com.haulmont.cuba.gui.executors.impl.TasksWatchDog; -import org.springframework.stereotype.Component; - -@Component(TasksWatchDog.NAME) -public class DesktopTasksWatchDog extends TasksWatchDog { - - @Override - protected synchronized ExecutionStatus getExecutionStatus(long actualTimeMs, TaskHandlerImpl taskHandler) { - long timeout = taskHandler.getTimeoutMs(); - - if (timeout > 0 && (actualTimeMs - taskHandler.getStartTimeStamp()) > timeout) { - return ExecutionStatus.TIMEOUT_EXCEEDED; - } - - // do not kill tasks on desktop, just cancel with timeoutExceeded event - return ExecutionStatus.NORMAL; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.gui.executors.impl; + +import com.haulmont.cuba.gui.executors.impl.TaskHandlerImpl; +import com.haulmont.cuba.gui.executors.impl.TasksWatchDog; +import org.springframework.stereotype.Component; + +@Component(TasksWatchDog.NAME) +public class DesktopTasksWatchDog extends TasksWatchDog { + + @Override + protected synchronized ExecutionStatus getExecutionStatus(long actualTimeMs, TaskHandlerImpl taskHandler) { + long timeout = taskHandler.getTimeoutMs(); + + if (timeout > 0 && (actualTimeMs - taskHandler.getStartTimeStamp()) > timeout) { + return ExecutionStatus.TIMEOUT_EXCEEDED; + } + + // do not kill tasks on desktop, just cancel with timeoutExceeded event + return ExecutionStatus.NORMAL; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/messages.properties b/modules/desktop/src/com/haulmont/cuba/desktop/messages.properties index c7e402209b..f3b21c8717 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/messages.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/messages.properties @@ -1,78 +1,78 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -@include=com.haulmont.cuba.gui - -menu-config.sec$User.changePasswordLauncher=Change Password -mainMenu.file=File -mainMenu.connect=Connect -mainMenu.disconnect=Disconnect -mainMenu.exit=Exit - -closeTabToolTip=Close this tab - -errorPane.title=Unexpected error -errorPane.copingSuccessful=Copied to Clipboard -errorPane.emailSent=Email has been sent -errorPane.emailSendingErr=Error while sending email -JXErrorPane.details_expand_text=Details >> -JXErrorPane.details_contract_text=Details << -JXErrorPane.ok_button_text=Close -JXErrorPane.fatal_button_text=Exit Application -JXErrorPane.report_button_text=Report Error -JXErrorPane.copy_to_clipboard_button_text=Copy to Clipboard -exceptionDialog.contactAdmin=Please contact system administrator - -unexpectedCloseException.message=Unable to close application correctly -connectException.message=Server connection error -entitySerializationException.title = Desktop application restart required -entitySerializationException.description = Launched desktop application is outdated, which led to data communication error.
Please restart the application using a link provided by IT administrator. -connectException.description=Cause: %s - -action.saveFile=Save -action.openFile=Open -action.cancel=Cancel - -noUserSession.exit=Exit - -statusBar.connected=Connected to %s -statusBar.user = User: %s [%s] -statusBar.timeZone = Time zone: %s - -DatePicker.linkFormat=Today is {0,date} -DesktopTable.configureFontsLabel=Configure Fonts -DesktopTable.resetSettings=Reset preferences -DesktopTable.packAll = Pack all columns -DesktopTable.packSelected = Pack selected column -DesktopTable.horizontalScroll = Horizontal Scroll - -notification.title.ERROR = Error -notification.title.ERROR_HTML = Error -notification.title.WARNING = Warning -notification.title.WARNING_HTML = Warning -notification.title.TRAY = -notification.title.TRAY_HTML = -notification.title.HUMANIZED = Information -notification.title.HUMANIZED_HTML = Information - -sessionMessageDialog.caption = Message from administrator - -dateField.dateOutOfRangeMessage = Date out of range - -FileUploadField.fileNotSelected = File is not selected -FileUploadField.clearButtonCaption = Clear +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +@include=com.haulmont.cuba.gui + +menu-config.sec$User.changePasswordLauncher=Change Password +mainMenu.file=File +mainMenu.connect=Connect +mainMenu.disconnect=Disconnect +mainMenu.exit=Exit + +closeTabToolTip=Close this tab + +errorPane.title=Unexpected error +errorPane.copingSuccessful=Copied to Clipboard +errorPane.emailSent=Email has been sent +errorPane.emailSendingErr=Error while sending email +JXErrorPane.details_expand_text=Details >> +JXErrorPane.details_contract_text=Details << +JXErrorPane.ok_button_text=Close +JXErrorPane.fatal_button_text=Exit Application +JXErrorPane.report_button_text=Report Error +JXErrorPane.copy_to_clipboard_button_text=Copy to Clipboard +exceptionDialog.contactAdmin=Please contact system administrator + +unexpectedCloseException.message=Unable to close application correctly +connectException.message=Server connection error +entitySerializationException.title = Desktop application restart required +entitySerializationException.description = Launched desktop application is outdated, which led to data communication error.
Please restart the application using a link provided by IT administrator. +connectException.description=Cause: %s + +action.saveFile=Save +action.openFile=Open +action.cancel=Cancel + +noUserSession.exit=Exit + +statusBar.connected=Connected to %s +statusBar.user = User: %s [%s] +statusBar.timeZone = Time zone: %s + +DatePicker.linkFormat=Today is {0,date} +DesktopTable.configureFontsLabel=Configure Fonts +DesktopTable.resetSettings=Reset preferences +DesktopTable.packAll = Pack all columns +DesktopTable.packSelected = Pack selected column +DesktopTable.horizontalScroll = Horizontal Scroll + +notification.title.ERROR = Error +notification.title.ERROR_HTML = Error +notification.title.WARNING = Warning +notification.title.WARNING_HTML = Warning +notification.title.TRAY = +notification.title.TRAY_HTML = +notification.title.HUMANIZED = Information +notification.title.HUMANIZED_HTML = Information + +sessionMessageDialog.caption = Message from administrator + +dateField.dateOutOfRangeMessage = Date out of range + +FileUploadField.fileNotSelected = File is not selected +FileUploadField.clearButtonCaption = Clear FileUploadField.uploadingFile = Uploading file \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/messages_en_US.properties b/modules/desktop/src/com/haulmont/cuba/desktop/messages_en_US.properties index e05e4e8335..2b89ec7289 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/messages_en_US.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/messages_en_US.properties @@ -1,18 +1,18 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -@include=com.haulmont.cuba.gui +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +@include=com.haulmont.cuba.gui diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/messages_ru.properties b/modules/desktop/src/com/haulmont/cuba/desktop/messages_ru.properties index 79a37556d8..6bce407c9c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/messages_ru.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/messages_ru.properties @@ -1,76 +1,76 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -@include=com.haulmont.cuba.gui - -menu-config.sec$User.changePasswordLauncher=Сменить пароль -mainMenu.file=Файл -mainMenu.connect=Подключиться -mainMenu.disconnect=Отключиться -mainMenu.exit=Выход - -closeTabToolTip=Закрыть вкладку - -errorPane.title=Непредвиденная ошибка -errorPane.copingSuccessful=Скопировано в буфер обмена -errorPane.emailSent=Письмо отправлено -errorPane.emailSendingErr=При отправке письма произошла ошибка -JXErrorPane.details_expand_text=Подробнее >> -JXErrorPane.details_contract_text=Подробнее << -JXErrorPane.ok_button_text=Закрыть -JXErrorPane.fatal_button_text=Выход из приложения -JXErrorPane.report_button_text=Сообщить об ошибке -JXErrorPane.copy_to_clipboard_button_text=Копировать в буфер обмена -exceptionDialog.contactAdmin=Пожалуйста, свяжитесь с администратором системы - -unexpectedCloseException.message=Ошибка завершения работы приложения -connectException.message=Ошибка соединения с сервером -connectException.description=Причина: %s -entitySerializationException.title = Требуется перезапустить десктоп-приложение -entitySerializationException.description = Запущенная версия десктоп-приложения устарела, что привело к ошибке передачи данных.
Пожалуйста перезапустите ваше десктоп-приложение, используя ссылку, предоставленную ИТ-администратором. - -action.saveFile=Сохранить -action.openFile=Открыть -action.cancel=Cancel - -noUserSession.exit=Выход - -statusBar.connected=Подключено к %s -statusBar.user = Пользователь: %s [%s] - -DatePicker.linkFormat=Сегодня {0,date} -DesktopTable.configureFontsLabel=Настроить шрифт -DesktopTable.resetSettings=Сбросить настройки -DesktopTable.packAll = Упаковать все колонки -DesktopTable.packSelected = Упаковать выбранные колонки -DesktopTable.horizontalScroll = Горизонтальная прокрутка - -notification.title.ERROR = Ошибка -notification.title.ERROR_HTML = Ошибка -notification.title.WARNING = Внимание -notification.title.WARNING_HTML = Внимание -notification.title.TRAY = -notification.title.TRAY_HTML = -notification.title.HUMANIZED = Информация -notification.title.HUMANIZED_HTML = Информация - -sessionMessageDialog.caption = Сообщение от администратора -dateField.dateOutOfRangeMessage = Выбранная дата находится за пределами допустимых значений - -FileUploadField.fileNotSelected = Файл не выбран -FileUploadField.clearButtonCaption = Очистить +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +@include=com.haulmont.cuba.gui + +menu-config.sec$User.changePasswordLauncher=Сменить пароль +mainMenu.file=Файл +mainMenu.connect=Подключиться +mainMenu.disconnect=Отключиться +mainMenu.exit=Выход + +closeTabToolTip=Закрыть вкладку + +errorPane.title=Непредвиденная ошибка +errorPane.copingSuccessful=Скопировано в буфер обмена +errorPane.emailSent=Письмо отправлено +errorPane.emailSendingErr=При отправке письма произошла ошибка +JXErrorPane.details_expand_text=Подробнее >> +JXErrorPane.details_contract_text=Подробнее << +JXErrorPane.ok_button_text=Закрыть +JXErrorPane.fatal_button_text=Выход из приложения +JXErrorPane.report_button_text=Сообщить об ошибке +JXErrorPane.copy_to_clipboard_button_text=Копировать в буфер обмена +exceptionDialog.contactAdmin=Пожалуйста, свяжитесь с администратором системы + +unexpectedCloseException.message=Ошибка завершения работы приложения +connectException.message=Ошибка соединения с сервером +connectException.description=Причина: %s +entitySerializationException.title = Требуется перезапустить десктоп-приложение +entitySerializationException.description = Запущенная версия десктоп-приложения устарела, что привело к ошибке передачи данных.
Пожалуйста перезапустите ваше десктоп-приложение, используя ссылку, предоставленную ИТ-администратором. + +action.saveFile=Сохранить +action.openFile=Открыть +action.cancel=Cancel + +noUserSession.exit=Выход + +statusBar.connected=Подключено к %s +statusBar.user = Пользователь: %s [%s] + +DatePicker.linkFormat=Сегодня {0,date} +DesktopTable.configureFontsLabel=Настроить шрифт +DesktopTable.resetSettings=Сбросить настройки +DesktopTable.packAll = Упаковать все колонки +DesktopTable.packSelected = Упаковать выбранные колонки +DesktopTable.horizontalScroll = Горизонтальная прокрутка + +notification.title.ERROR = Ошибка +notification.title.ERROR_HTML = Ошибка +notification.title.WARNING = Внимание +notification.title.WARNING_HTML = Внимание +notification.title.TRAY = +notification.title.TRAY_HTML = +notification.title.HUMANIZED = Информация +notification.title.HUMANIZED_HTML = Информация + +sessionMessageDialog.caption = Сообщение от администратора +dateField.dateOutOfRangeMessage = Выбранная дата находится за пределами допустимых значений + +FileUploadField.fileNotSelected = Файл не выбран +FileUploadField.clearButtonCaption = Очистить FileUploadField.uploadingFile = Загрузка файла \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/BaseMandatoryRegionPainter.java b/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/BaseMandatoryRegionPainter.java index 5b83432e07..84189eee58 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/BaseMandatoryRegionPainter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/BaseMandatoryRegionPainter.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.plaf.nimbus; - -import javax.swing.plaf.nimbus.AbstractRegionPainter; -import java.awt.*; - -public abstract class BaseMandatoryRegionPainter extends AbstractRegionPainter { - - /** - * The only reason to have this is to access AbstractRegionPainter.PaintContextCacheMode which has protected access. - */ - public static class AbstractRegionPainterPaintContext extends PaintContext { - public AbstractRegionPainterPaintContext(Insets insets, Dimension canvasSize, - boolean inverted, String cacheMode, double maxH, double maxV) { - super(insets, canvasSize, inverted, CacheMode.valueOf(cacheMode), maxH, maxV); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.plaf.nimbus; + +import javax.swing.plaf.nimbus.AbstractRegionPainter; +import java.awt.*; + +public abstract class BaseMandatoryRegionPainter extends AbstractRegionPainter { + + /** + * The only reason to have this is to access AbstractRegionPainter.PaintContextCacheMode which has protected access. + */ + public static class AbstractRegionPainterPaintContext extends PaintContext { + public AbstractRegionPainterPaintContext(Insets insets, Dimension canvasSize, + boolean inverted, String cacheMode, double maxH, double maxV) { + super(insets, canvasSize, inverted, CacheMode.valueOf(cacheMode), maxH, maxV); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/MandatoryComboBoxTextFieldPainter.java b/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/MandatoryComboBoxTextFieldPainter.java index 961bea404c..40783affcb 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/MandatoryComboBoxTextFieldPainter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/plaf/nimbus/MandatoryComboBoxTextFieldPainter.java @@ -1,298 +1,298 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.plaf.nimbus; - -import com.haulmont.cuba.desktop.sys.vcl.SearchComboBox; - -import javax.swing.*; -import java.awt.*; -import java.awt.geom.Rectangle2D; - -/** - * Default "ComboBoxTextFieldPainter" painter class does not support background color overriding.
- * Allows draw combobox without button for SearchComboBox. - */ -public class MandatoryComboBoxTextFieldPainter extends BaseMandatoryRegionPainter { - //package private integers representing the available states that - //this painter will paint. These are used when creating a new instance - //of ComboBoxTextFieldPainter to determine which region/state is being painted - //by that instance. - static final int BACKGROUND_DISABLED = 1; - static final int BACKGROUND_ENABLED = 2; - static final int BACKGROUND_SELECTED = 3; - - private int state; //refers to one of the static final ints above - private PaintContext ctx; - - private boolean drawButtonBorder = true; - - //the following 4 variables are reused during the painting code of the layers -// private Path2D path = new Path2D.Float(); - private Rectangle2D rect = new Rectangle2D.Float(0, 0, 0, 0); -// private RoundRectangle2D roundRect = new RoundRectangle2D.Float(0, 0, 0, 0, 0, 0); -// private Ellipse2D ellipse = new Ellipse2D.Float(0, 0, 0, 0); - - //All Colors used for painting are stored here. Ideally, only those colors being used - //by a particular instance of ComboBoxTextFieldPainter would be created. For the moment at least, - //however, all are created for each instance. - private Color color1 = decodeColor("nimbusBlueGrey", -0.6111111f, -0.110526316f, -0.74509805f, -237); - private Color color2 = decodeColor("nimbusBlueGrey", -0.006944418f, -0.07187897f, 0.06666666f, 0); - private Color color3 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07703349f, 0.0745098f, 0); - private Color color4 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07968931f, 0.14509803f, 0); - private Color color5 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07856284f, 0.11372548f, 0); - private Color color6 = decodeColor("nimbusBase", 0.040395975f, -0.60315615f, 0.29411763f, 0); - private Color color7 = decodeColor("nimbusBase", 0.016586483f, -0.6051466f, 0.3490196f, 0); - private Color color8 = decodeColor("nimbusBlueGrey", -0.027777791f, -0.0965403f, -0.18431371f, 0); - private Color color9 = decodeColor("nimbusBlueGrey", 0.055555582f, -0.1048766f, -0.05098039f, 0); - private Color color10 = decodeColor("nimbusLightBackground", 0.6666667f, 0.004901961f, -0.19999999f, 0); - private Color color11 = decodeColor("nimbusLightBackground", 0.0f, 0.0f, 0.0f, 0); - private Color color12 = decodeColor("nimbusBlueGrey", 0.055555582f, -0.105344966f, 0.011764705f, 0); - - //Array of current component colors, updated in each paint call - private Object[] componentColors; - - public MandatoryComboBoxTextFieldPainter(PaintContext ctx, int state) { - this.ctx = ctx; - this.state = state; - } - - public static MandatoryComboBoxTextFieldPainter backgroundEnabledPainter() { - return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), - new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_ENABLED); - } - - public static MandatoryComboBoxTextFieldPainter backgroundDisabledPainter() { - return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), - new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_DISABLED); - } - - public static MandatoryComboBoxTextFieldPainter backgroundSelectedPainter() { - return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), - new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_SELECTED); - } - - @Override - protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { - drawButtonBorder = !(c.getParent() instanceof SearchComboBox); - - //populate componentColors array with colors calculated in getExtendedCacheKeys call - componentColors = extendedCacheKeys; - //generate this entire method. Each state/bg/fg/border combo that has - //been painted gets its own KEY and paint method. - switch(state) { - case BACKGROUND_DISABLED: paintBackgroundDisabled(g); break; - case BACKGROUND_ENABLED: paintBackgroundEnabled(g); break; - case BACKGROUND_SELECTED: paintBackgroundSelected(g); break; - } - } - - // todo changes here and where "(Color) componentColors[0]" appear - @Override - protected Object[] getExtendedCacheKeys(JComponent c) { - Object[] extendedCacheKeys; - extendedCacheKeys = new Object[] { - getComponentColor(c, "background", color11, 0.0f, 0.0f, 0)}; - return extendedCacheKeys; - } - - @Override - protected final PaintContext getPaintContext() { - return ctx; - } - - private void paintBackgroundDisabled(Graphics2D g) { - rect = decodeRect1(); - g.setPaint(color1); - g.fill(rect); - rect = decodeRect2(); - g.setPaint(decodeGradient1(rect)); - g.fill(rect); - rect = decodeRect3(); - g.setPaint(decodeGradient2(rect)); - g.fill(rect); - rect = decodeRect4(); - g.setPaint(color6); - g.fill(rect); - rect = decodeRect5(); - g.setPaint(color7); - g.fill(rect); - } - - private void paintBackgroundEnabled(Graphics2D g) { - rect = decodeRect1(); - g.setPaint(color1); - g.fill(rect); - rect = decodeRect2(); - g.setPaint(decodeGradient3(rect)); - g.fill(rect); - rect = decodeRect3(); - g.setPaint(decodeGradient4(rect)); - g.fill(rect); - rect = decodeRect4(); - g.setPaint(color12); - g.fill(rect); - rect = decodeRect5(); - g.setPaint((Color) componentColors[0]); - g.fill(rect); - } - - private void paintBackgroundSelected(Graphics2D g) { - rect = decodeRect1(); - g.setPaint(color1); - g.fill(rect); - rect = decodeRect2(); - g.setPaint(decodeGradient3(rect)); - g.fill(rect); - rect = decodeRect3(); - g.setPaint(decodeGradient4(rect)); - g.fill(rect); - rect = decodeRect4(); - g.setPaint(color12); - g.fill(rect); - rect = decodeRect5(); - g.setPaint((Color) componentColors[0]); - g.fill(rect); - } - - private Rectangle2D decodeRect1() { - if (drawButtonBorder) { - rect.setRect(decodeX(0.6666667f), //x - decodeY(2.3333333f), //y - decodeX(3.0f) - decodeX(0.6666667f), //width - decodeY(2.6666667f) - decodeY(2.3333333f)); //height - } else { - rect.setRect(decodeX(0.6666667f), //x - decodeY(2.3333333f), //y - decodeX(3.0f) - 2 * decodeX(0.6666667f), //width - decodeY(2.6666667f) - decodeY(2.3333333f)); //height - } - return rect; - } - - private Rectangle2D decodeRect2() { - if (drawButtonBorder) { - rect.setRect(decodeX(0.6666667f), //x - decodeY(0.4f), //y - decodeX(3.0f) - decodeX(0.6666667f), //width - decodeY(1.0f) - decodeY(0.4f)); //height - } else { - rect.setRect(decodeX(0.6666667f), //x - decodeY(0.4f), //y - decodeX(3.0f) - 2 * decodeX(0.6666667f), //width - decodeY(1.0f) - decodeY(0.4f)); //height - } - return rect; - } - - private Rectangle2D decodeRect3() { - if (drawButtonBorder) { - rect.setRect(decodeX(1.0f), //x - decodeY(0.6f), //y - decodeX(3.0f) - decodeX(1.0f), //width - decodeY(1.0f) - decodeY(0.6f)); //height - } else { - rect.setRect(decodeX(1.0f), //x - decodeY(0.6f), //y - decodeX(3.0f) - 2 * decodeX(1.0f), //width - decodeY(1.0f) - decodeY(0.6f)); //height - } - return rect; - } - - private Rectangle2D decodeRect4() { - if (drawButtonBorder) { - rect.setRect(decodeX(0.6666667f), //x - decodeY(1.0f), //y - decodeX(3.0f) - decodeX(0.6666667f), //width - decodeY(2.3333333f) - decodeY(1.0f)); //height - } else { - rect.setRect(decodeX(0.6666667f), //x - decodeY(1.0f), //y - decodeX(3.0f) - 2 * decodeX(0.6666667f), //width - decodeY(2.3333333f) - decodeY(1.0f)); //height - } - return rect; - } - - private Rectangle2D decodeRect5() { - if (drawButtonBorder) { - rect.setRect(decodeX(1.0f), //x - decodeY(1.0f), //y - decodeX(3.0f) - decodeX(1.0f), //width - decodeY(2.0f) - decodeY(1.0f)); //height - } else { - rect.setRect(decodeX(1.0f), //x - decodeY(1.0f), //y - decodeX(3.0f) - 2 * decodeX(1.0f), //width - decodeY(2.0f) - decodeY(1.0f)); //height - } - return rect; - } - - private Paint decodeGradient1(Shape s) { - Rectangle2D bounds = s.getBounds2D(); - float x = (float)bounds.getX(); - float y = (float)bounds.getY(); - float w = (float)bounds.getWidth(); - float h = (float)bounds.getHeight(); - return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, - new float[] { 0.0f,0.5f,1.0f }, - new Color[] { color2, - decodeColor(color2,color3,0.5f), - color3}); - } - - private Paint decodeGradient2(Shape s) { - Rectangle2D bounds = s.getBounds2D(); - float x = (float)bounds.getX(); - float y = (float)bounds.getY(); - float w = (float)bounds.getWidth(); - float h = (float)bounds.getHeight(); - return decodeGradient((0.5f * w) + x, (1.0f * h) + y, (0.5f * w) + x, (0.0f * h) + y, - new float[] { 0.0f,0.5f,1.0f }, - new Color[] { color4, - decodeColor(color4,color5,0.5f), - color5}); - } - - private Paint decodeGradient3(Shape s) { - Rectangle2D bounds = s.getBounds2D(); - float x = (float)bounds.getX(); - float y = (float)bounds.getY(); - float w = (float)bounds.getWidth(); - float h = (float)bounds.getHeight(); - return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, - new float[] { 0.0f,0.49573863f,0.99147725f }, - new Color[] { color8, - decodeColor(color8,color9,0.5f), - color9}); - } - - private Paint decodeGradient4(Shape s) { - Rectangle2D bounds = s.getBounds2D(); - float x = (float)bounds.getX(); - float y = (float)bounds.getY(); - float w = (float)bounds.getWidth(); - float h = (float)bounds.getHeight(); - return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, - new float[] { 0.1f,0.49999997f,0.9f }, - new Color[] { color10, - decodeColor(color10,(Color) componentColors[0],0.5f), - (Color) componentColors[0]}); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.plaf.nimbus; + +import com.haulmont.cuba.desktop.sys.vcl.SearchComboBox; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Rectangle2D; + +/** + * Default "ComboBoxTextFieldPainter" painter class does not support background color overriding.
+ * Allows draw combobox without button for SearchComboBox. + */ +public class MandatoryComboBoxTextFieldPainter extends BaseMandatoryRegionPainter { + //package private integers representing the available states that + //this painter will paint. These are used when creating a new instance + //of ComboBoxTextFieldPainter to determine which region/state is being painted + //by that instance. + static final int BACKGROUND_DISABLED = 1; + static final int BACKGROUND_ENABLED = 2; + static final int BACKGROUND_SELECTED = 3; + + private int state; //refers to one of the static final ints above + private PaintContext ctx; + + private boolean drawButtonBorder = true; + + //the following 4 variables are reused during the painting code of the layers +// private Path2D path = new Path2D.Float(); + private Rectangle2D rect = new Rectangle2D.Float(0, 0, 0, 0); +// private RoundRectangle2D roundRect = new RoundRectangle2D.Float(0, 0, 0, 0, 0, 0); +// private Ellipse2D ellipse = new Ellipse2D.Float(0, 0, 0, 0); + + //All Colors used for painting are stored here. Ideally, only those colors being used + //by a particular instance of ComboBoxTextFieldPainter would be created. For the moment at least, + //however, all are created for each instance. + private Color color1 = decodeColor("nimbusBlueGrey", -0.6111111f, -0.110526316f, -0.74509805f, -237); + private Color color2 = decodeColor("nimbusBlueGrey", -0.006944418f, -0.07187897f, 0.06666666f, 0); + private Color color3 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07703349f, 0.0745098f, 0); + private Color color4 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07968931f, 0.14509803f, 0); + private Color color5 = decodeColor("nimbusBlueGrey", 0.007936537f, -0.07856284f, 0.11372548f, 0); + private Color color6 = decodeColor("nimbusBase", 0.040395975f, -0.60315615f, 0.29411763f, 0); + private Color color7 = decodeColor("nimbusBase", 0.016586483f, -0.6051466f, 0.3490196f, 0); + private Color color8 = decodeColor("nimbusBlueGrey", -0.027777791f, -0.0965403f, -0.18431371f, 0); + private Color color9 = decodeColor("nimbusBlueGrey", 0.055555582f, -0.1048766f, -0.05098039f, 0); + private Color color10 = decodeColor("nimbusLightBackground", 0.6666667f, 0.004901961f, -0.19999999f, 0); + private Color color11 = decodeColor("nimbusLightBackground", 0.0f, 0.0f, 0.0f, 0); + private Color color12 = decodeColor("nimbusBlueGrey", 0.055555582f, -0.105344966f, 0.011764705f, 0); + + //Array of current component colors, updated in each paint call + private Object[] componentColors; + + public MandatoryComboBoxTextFieldPainter(PaintContext ctx, int state) { + this.ctx = ctx; + this.state = state; + } + + public static MandatoryComboBoxTextFieldPainter backgroundEnabledPainter() { + return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), + new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_ENABLED); + } + + public static MandatoryComboBoxTextFieldPainter backgroundDisabledPainter() { + return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), + new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_DISABLED); + } + + public static MandatoryComboBoxTextFieldPainter backgroundSelectedPainter() { + return new MandatoryComboBoxTextFieldPainter(new AbstractRegionPainterPaintContext(new Insets(5, 3, 3, 5), + new Dimension(64, 24), false, "NINE_SQUARE_SCALE", Double.POSITIVE_INFINITY, 2.0), BACKGROUND_SELECTED); + } + + @Override + protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { + drawButtonBorder = !(c.getParent() instanceof SearchComboBox); + + //populate componentColors array with colors calculated in getExtendedCacheKeys call + componentColors = extendedCacheKeys; + //generate this entire method. Each state/bg/fg/border combo that has + //been painted gets its own KEY and paint method. + switch(state) { + case BACKGROUND_DISABLED: paintBackgroundDisabled(g); break; + case BACKGROUND_ENABLED: paintBackgroundEnabled(g); break; + case BACKGROUND_SELECTED: paintBackgroundSelected(g); break; + } + } + + // todo changes here and where "(Color) componentColors[0]" appear + @Override + protected Object[] getExtendedCacheKeys(JComponent c) { + Object[] extendedCacheKeys; + extendedCacheKeys = new Object[] { + getComponentColor(c, "background", color11, 0.0f, 0.0f, 0)}; + return extendedCacheKeys; + } + + @Override + protected final PaintContext getPaintContext() { + return ctx; + } + + private void paintBackgroundDisabled(Graphics2D g) { + rect = decodeRect1(); + g.setPaint(color1); + g.fill(rect); + rect = decodeRect2(); + g.setPaint(decodeGradient1(rect)); + g.fill(rect); + rect = decodeRect3(); + g.setPaint(decodeGradient2(rect)); + g.fill(rect); + rect = decodeRect4(); + g.setPaint(color6); + g.fill(rect); + rect = decodeRect5(); + g.setPaint(color7); + g.fill(rect); + } + + private void paintBackgroundEnabled(Graphics2D g) { + rect = decodeRect1(); + g.setPaint(color1); + g.fill(rect); + rect = decodeRect2(); + g.setPaint(decodeGradient3(rect)); + g.fill(rect); + rect = decodeRect3(); + g.setPaint(decodeGradient4(rect)); + g.fill(rect); + rect = decodeRect4(); + g.setPaint(color12); + g.fill(rect); + rect = decodeRect5(); + g.setPaint((Color) componentColors[0]); + g.fill(rect); + } + + private void paintBackgroundSelected(Graphics2D g) { + rect = decodeRect1(); + g.setPaint(color1); + g.fill(rect); + rect = decodeRect2(); + g.setPaint(decodeGradient3(rect)); + g.fill(rect); + rect = decodeRect3(); + g.setPaint(decodeGradient4(rect)); + g.fill(rect); + rect = decodeRect4(); + g.setPaint(color12); + g.fill(rect); + rect = decodeRect5(); + g.setPaint((Color) componentColors[0]); + g.fill(rect); + } + + private Rectangle2D decodeRect1() { + if (drawButtonBorder) { + rect.setRect(decodeX(0.6666667f), //x + decodeY(2.3333333f), //y + decodeX(3.0f) - decodeX(0.6666667f), //width + decodeY(2.6666667f) - decodeY(2.3333333f)); //height + } else { + rect.setRect(decodeX(0.6666667f), //x + decodeY(2.3333333f), //y + decodeX(3.0f) - 2 * decodeX(0.6666667f), //width + decodeY(2.6666667f) - decodeY(2.3333333f)); //height + } + return rect; + } + + private Rectangle2D decodeRect2() { + if (drawButtonBorder) { + rect.setRect(decodeX(0.6666667f), //x + decodeY(0.4f), //y + decodeX(3.0f) - decodeX(0.6666667f), //width + decodeY(1.0f) - decodeY(0.4f)); //height + } else { + rect.setRect(decodeX(0.6666667f), //x + decodeY(0.4f), //y + decodeX(3.0f) - 2 * decodeX(0.6666667f), //width + decodeY(1.0f) - decodeY(0.4f)); //height + } + return rect; + } + + private Rectangle2D decodeRect3() { + if (drawButtonBorder) { + rect.setRect(decodeX(1.0f), //x + decodeY(0.6f), //y + decodeX(3.0f) - decodeX(1.0f), //width + decodeY(1.0f) - decodeY(0.6f)); //height + } else { + rect.setRect(decodeX(1.0f), //x + decodeY(0.6f), //y + decodeX(3.0f) - 2 * decodeX(1.0f), //width + decodeY(1.0f) - decodeY(0.6f)); //height + } + return rect; + } + + private Rectangle2D decodeRect4() { + if (drawButtonBorder) { + rect.setRect(decodeX(0.6666667f), //x + decodeY(1.0f), //y + decodeX(3.0f) - decodeX(0.6666667f), //width + decodeY(2.3333333f) - decodeY(1.0f)); //height + } else { + rect.setRect(decodeX(0.6666667f), //x + decodeY(1.0f), //y + decodeX(3.0f) - 2 * decodeX(0.6666667f), //width + decodeY(2.3333333f) - decodeY(1.0f)); //height + } + return rect; + } + + private Rectangle2D decodeRect5() { + if (drawButtonBorder) { + rect.setRect(decodeX(1.0f), //x + decodeY(1.0f), //y + decodeX(3.0f) - decodeX(1.0f), //width + decodeY(2.0f) - decodeY(1.0f)); //height + } else { + rect.setRect(decodeX(1.0f), //x + decodeY(1.0f), //y + decodeX(3.0f) - 2 * decodeX(1.0f), //width + decodeY(2.0f) - decodeY(1.0f)); //height + } + return rect; + } + + private Paint decodeGradient1(Shape s) { + Rectangle2D bounds = s.getBounds2D(); + float x = (float)bounds.getX(); + float y = (float)bounds.getY(); + float w = (float)bounds.getWidth(); + float h = (float)bounds.getHeight(); + return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, + new float[] { 0.0f,0.5f,1.0f }, + new Color[] { color2, + decodeColor(color2,color3,0.5f), + color3}); + } + + private Paint decodeGradient2(Shape s) { + Rectangle2D bounds = s.getBounds2D(); + float x = (float)bounds.getX(); + float y = (float)bounds.getY(); + float w = (float)bounds.getWidth(); + float h = (float)bounds.getHeight(); + return decodeGradient((0.5f * w) + x, (1.0f * h) + y, (0.5f * w) + x, (0.0f * h) + y, + new float[] { 0.0f,0.5f,1.0f }, + new Color[] { color4, + decodeColor(color4,color5,0.5f), + color5}); + } + + private Paint decodeGradient3(Shape s) { + Rectangle2D bounds = s.getBounds2D(); + float x = (float)bounds.getX(); + float y = (float)bounds.getY(); + float w = (float)bounds.getWidth(); + float h = (float)bounds.getHeight(); + return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, + new float[] { 0.0f,0.49573863f,0.99147725f }, + new Color[] { color8, + decodeColor(color8,color9,0.5f), + color9}); + } + + private Paint decodeGradient4(Shape s) { + Rectangle2D bounds = s.getBounds2D(); + float x = (float)bounds.getX(); + float y = (float)bounds.getY(); + float w = (float)bounds.getWidth(); + float h = (float)bounds.getHeight(); + return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y, + new float[] { 0.1f,0.49999997f,0.9f }, + new Color[] { color10, + decodeColor(color10,(Color) componentColors[0],0.5f), + (Color) componentColors[0]}); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/res/metal/metal.xml b/modules/desktop/src/com/haulmont/cuba/desktop/res/metal/metal.xml index 2efc17cb79..ded7f183d0 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/res/metal/metal.xml +++ b/modules/desktop/src/com/haulmont/cuba/desktop/res/metal/metal.xml @@ -1,19 +1,19 @@ - - - javax.swing.plaf.metal.MetalLookAndFeel - + + + javax.swing.plaf.metal.MetalLookAndFeel + diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/res/nimbus/nimbus.xml b/modules/desktop/src/com/haulmont/cuba/desktop/res/nimbus/nimbus.xml index ba9bbc38eb..683f04a954 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/res/nimbus/nimbus.xml +++ b/modules/desktop/src/com/haulmont/cuba/desktop/res/nimbus/nimbus.xml @@ -1,82 +1,82 @@ - - - - javax.swing.plaf.nimbus.NimbusLookAndFeel - com.haulmont.cuba.desktop.theme.impl.NimbusTheme - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + javax.swing.plaf.nimbus.NimbusLookAndFeel + com.haulmont.cuba.desktop.theme.impl.NimbusTheme + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/ButtonTabComponent.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/ButtonTabComponent.java index 2671719ade..6f712d4e9f 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/ButtonTabComponent.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/ButtonTabComponent.java @@ -1,296 +1,296 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; - -import javax.swing.*; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import javax.swing.plaf.basic.BasicButtonUI; -import java.awt.*; -import java.awt.event.*; - -/** - * Component to be used as tabComponent.
- * Contains a JLabel to show the text and a JButton to close the tab it belongs to. - */ -public class ButtonTabComponent extends JPanel { - - protected JButton tabButton; - protected JButton detachButton; - - protected Messages messages = AppBeans.get(Messages.NAME); - - public interface CloseListener { - void onTabClose(int tabIndex); - } - - public interface DetachListener { - void onDetach(int tabIndex); - } - - private final JTabbedPane pane; - private CloseListener closeListener; - private DetachListener detachListener; - private JLabel titleLabel; - private boolean closeable; - private boolean detachable; - - public ButtonTabComponent(final JTabbedPane pane, boolean closeable, boolean detachable, - CloseListener closeListener, DetachListener detachListener) { - //unset default FlowLayout' gaps - super(new FlowLayout(FlowLayout.LEFT, 0, 0)); - if (pane == null) { - throw new NullPointerException("TabbedPane is null"); - } - this.closeable = closeable; - this.detachable = detachable; - this.detachListener = detachListener; - this.closeListener = closeListener; - - this.pane = pane; - setOpaque(false); - - //make JLabel read titles from JTabbedPane - titleLabel = new JLabel() { - @Override - public String getText() { - int i = pane.indexOfTabComponent(ButtonTabComponent.this); - if (i != -1) { - return pane.getTitleAt(i); - } - return null; - } - }; - - add(titleLabel); - //add more space between the label and the button - titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - detachButton = new DetachButton(); - if (detachable) { - add(detachButton); - } - //tab button - tabButton = new TabButton(); - if (closeable) { - add(tabButton); - } - //add more space to the top of the component - setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); - - this.closeListener = closeListener; - } - - public String getCaption() { - return titleLabel.getText(); - } - - public void setCaption(String caption) { - int i = pane.indexOfTabComponent(this); - if (i != -1) { - pane.setTitleAt(i, caption); - } - titleLabel.setText(caption); - tabButton.revalidate(); - tabButton.repaint(); - detachButton.revalidate(); - detachButton.repaint(); - } - - public boolean isCloseable() { - return closeable; - } - - public void setCloseable(boolean closeable) { - if (this.closeable != closeable) { - this.closeable = closeable; - if (closeable) { - add(tabButton, detachable ? 2 : 1); - } else { - remove(tabButton); - } - } - } - - public boolean isDetachable() { - return detachable; - } - - public void setDetachable(boolean detachable) { - if (this.detachable != detachable) { - this.detachable = detachable; - if (detachable) { - add(detachButton, 1); - } else { - remove(detachButton); - } - } - } - - public JLabel getTitleLabel() { - return titleLabel; - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - detachButton.setEnabled(enabled); - tabButton.setEnabled(enabled); - } - - private class TabButton extends JButton implements ActionListener { - public TabButton() { - int size = 17; - setPreferredSize(new Dimension(size, size)); - setToolTipText(messages.getMainMessage("closeTabToolTip")); - //Make the button looks the same for all Laf's - setUI(new BasicButtonUI()); - //Make it transparent - setContentAreaFilled(false); - //No need to be focusable - setFocusable(false); - setBorder(BorderFactory.createEtchedBorder()); - setBorderPainted(false); - //Making nice rollover effect - //we use the same listener for all buttons - addMouseListener(buttonMouseListener); - addAncestorListener(ancestorListener); - - setRolloverEnabled(true); - //Close the proper tab by clicking the button - addActionListener(this); - } - - @Override - public void actionPerformed(ActionEvent e) { - int i = pane.indexOfTabComponent(ButtonTabComponent.this); - if (i != -1) { - if (closeListener != null) { - closeListener.onTabClose(i); - } else - pane.remove(i); - } - } - - //we don't want to update UI for this button - @Override - public void updateUI() { - } - - //paint the cross - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - doPaintContent(g); - } - - protected void doPaintContent(Graphics g) { - Graphics2D g2 = (Graphics2D) g.create(); - //shift the image for pressed buttons - if (isEnabled() && getModel().isPressed()) { - g2.translate(1, 1); - } - g2.setStroke(new BasicStroke(2)); - g2.setColor(Color.BLACK); - if (getModel().isRollover()) { - g2.setColor(Color.RED); - } - int delta = 6; - g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); - g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); - g2.dispose(); - } - } - - private class DetachButton extends TabButton { - - public DetachButton() { - setToolTipText(messages.getMainMessage("detach")); - } - - @Override - public void actionPerformed(ActionEvent e) { - int i = pane.indexOfTabComponent(ButtonTabComponent.this); - if (i != -1) { - if (detachListener != null) { - detachListener.onDetach(i); - } else - pane.remove(i); - } - } - - @Override - protected void doPaintContent(Graphics g) { - Graphics2D g2 = (Graphics2D) g.create(); - //shift the image for pressed buttons - if (isEnabled() && getModel().isPressed()) { - g2.translate(1, 1); - } - g2.setStroke(new BasicStroke(1)); - g2.setColor(Color.BLACK); - if (getModel().isRollover()) { - g2.setColor(Color.RED); - } - int delta = 6; - //back - g2.drawLine(delta, delta - 2, delta + delta, delta - 2); - g2.drawLine(delta + delta, delta - 2, delta + delta, delta - 2 + delta); - //front - g2.drawRect(delta - 2, delta, delta, delta); - g2.dispose(); - } - } - - private final static MouseListener buttonMouseListener = new MouseAdapter() { - @Override - public void mouseEntered(MouseEvent e) { - Component component = e.getComponent(); - if (component instanceof AbstractButton && component.isEnabled()) { - AbstractButton button = (AbstractButton) component; - button.setBorderPainted(true); - } - } - - @Override - public void mouseExited(MouseEvent e) { - Component component = e.getComponent(); - if (component instanceof AbstractButton) { - AbstractButton button = (AbstractButton) component; - button.setBorderPainted(false); - } - } - }; - - private final AncestorListener ancestorListener = new AncestorListener() { - @Override - public void ancestorAdded(AncestorEvent event) { - detachButton.setBorderPainted(false); - tabButton.setBorderPainted(false); - } - - @Override - public void ancestorRemoved(AncestorEvent event) { - } - - @Override - public void ancestorMoved(AncestorEvent event) { - } - }; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; + +import javax.swing.*; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.*; +import java.awt.event.*; + +/** + * Component to be used as tabComponent.
+ * Contains a JLabel to show the text and a JButton to close the tab it belongs to. + */ +public class ButtonTabComponent extends JPanel { + + protected JButton tabButton; + protected JButton detachButton; + + protected Messages messages = AppBeans.get(Messages.NAME); + + public interface CloseListener { + void onTabClose(int tabIndex); + } + + public interface DetachListener { + void onDetach(int tabIndex); + } + + private final JTabbedPane pane; + private CloseListener closeListener; + private DetachListener detachListener; + private JLabel titleLabel; + private boolean closeable; + private boolean detachable; + + public ButtonTabComponent(final JTabbedPane pane, boolean closeable, boolean detachable, + CloseListener closeListener, DetachListener detachListener) { + //unset default FlowLayout' gaps + super(new FlowLayout(FlowLayout.LEFT, 0, 0)); + if (pane == null) { + throw new NullPointerException("TabbedPane is null"); + } + this.closeable = closeable; + this.detachable = detachable; + this.detachListener = detachListener; + this.closeListener = closeListener; + + this.pane = pane; + setOpaque(false); + + //make JLabel read titles from JTabbedPane + titleLabel = new JLabel() { + @Override + public String getText() { + int i = pane.indexOfTabComponent(ButtonTabComponent.this); + if (i != -1) { + return pane.getTitleAt(i); + } + return null; + } + }; + + add(titleLabel); + //add more space between the label and the button + titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + detachButton = new DetachButton(); + if (detachable) { + add(detachButton); + } + //tab button + tabButton = new TabButton(); + if (closeable) { + add(tabButton); + } + //add more space to the top of the component + setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); + + this.closeListener = closeListener; + } + + public String getCaption() { + return titleLabel.getText(); + } + + public void setCaption(String caption) { + int i = pane.indexOfTabComponent(this); + if (i != -1) { + pane.setTitleAt(i, caption); + } + titleLabel.setText(caption); + tabButton.revalidate(); + tabButton.repaint(); + detachButton.revalidate(); + detachButton.repaint(); + } + + public boolean isCloseable() { + return closeable; + } + + public void setCloseable(boolean closeable) { + if (this.closeable != closeable) { + this.closeable = closeable; + if (closeable) { + add(tabButton, detachable ? 2 : 1); + } else { + remove(tabButton); + } + } + } + + public boolean isDetachable() { + return detachable; + } + + public void setDetachable(boolean detachable) { + if (this.detachable != detachable) { + this.detachable = detachable; + if (detachable) { + add(detachButton, 1); + } else { + remove(detachButton); + } + } + } + + public JLabel getTitleLabel() { + return titleLabel; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + detachButton.setEnabled(enabled); + tabButton.setEnabled(enabled); + } + + private class TabButton extends JButton implements ActionListener { + public TabButton() { + int size = 17; + setPreferredSize(new Dimension(size, size)); + setToolTipText(messages.getMainMessage("closeTabToolTip")); + //Make the button looks the same for all Laf's + setUI(new BasicButtonUI()); + //Make it transparent + setContentAreaFilled(false); + //No need to be focusable + setFocusable(false); + setBorder(BorderFactory.createEtchedBorder()); + setBorderPainted(false); + //Making nice rollover effect + //we use the same listener for all buttons + addMouseListener(buttonMouseListener); + addAncestorListener(ancestorListener); + + setRolloverEnabled(true); + //Close the proper tab by clicking the button + addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + int i = pane.indexOfTabComponent(ButtonTabComponent.this); + if (i != -1) { + if (closeListener != null) { + closeListener.onTabClose(i); + } else + pane.remove(i); + } + } + + //we don't want to update UI for this button + @Override + public void updateUI() { + } + + //paint the cross + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + doPaintContent(g); + } + + protected void doPaintContent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + //shift the image for pressed buttons + if (isEnabled() && getModel().isPressed()) { + g2.translate(1, 1); + } + g2.setStroke(new BasicStroke(2)); + g2.setColor(Color.BLACK); + if (getModel().isRollover()) { + g2.setColor(Color.RED); + } + int delta = 6; + g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1); + g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1); + g2.dispose(); + } + } + + private class DetachButton extends TabButton { + + public DetachButton() { + setToolTipText(messages.getMainMessage("detach")); + } + + @Override + public void actionPerformed(ActionEvent e) { + int i = pane.indexOfTabComponent(ButtonTabComponent.this); + if (i != -1) { + if (detachListener != null) { + detachListener.onDetach(i); + } else + pane.remove(i); + } + } + + @Override + protected void doPaintContent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + //shift the image for pressed buttons + if (isEnabled() && getModel().isPressed()) { + g2.translate(1, 1); + } + g2.setStroke(new BasicStroke(1)); + g2.setColor(Color.BLACK); + if (getModel().isRollover()) { + g2.setColor(Color.RED); + } + int delta = 6; + //back + g2.drawLine(delta, delta - 2, delta + delta, delta - 2); + g2.drawLine(delta + delta, delta - 2, delta + delta, delta - 2 + delta); + //front + g2.drawRect(delta - 2, delta, delta, delta); + g2.dispose(); + } + } + + private final static MouseListener buttonMouseListener = new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + Component component = e.getComponent(); + if (component instanceof AbstractButton && component.isEnabled()) { + AbstractButton button = (AbstractButton) component; + button.setBorderPainted(true); + } + } + + @Override + public void mouseExited(MouseEvent e) { + Component component = e.getComponent(); + if (component instanceof AbstractButton) { + AbstractButton button = (AbstractButton) component; + button.setBorderPainted(false); + } + } + }; + + private final AncestorListener ancestorListener = new AncestorListener() { + @Override + public void ancestorAdded(AncestorEvent event) { + detachButton.setBorderPainted(false); + tabButton.setBorderPainted(false); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + } + + @Override + public void ancestorMoved(AncestorEvent event) { + } + }; +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/ClientTimeSynchronizer.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/ClientTimeSynchronizer.java index 823cc24493..9683c07f4f 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/ClientTimeSynchronizer.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/ClientTimeSynchronizer.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.app.ServerInfoService; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.gui.executors.BackgroundTask; -import com.haulmont.cuba.gui.executors.BackgroundWorker; -import com.haulmont.cuba.gui.executors.TaskLifeCycle; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import java.util.TimeZone; - -/** - * Maintains desktop client time zone and time. - *
- * Time zone is taken from server. - * Time is synchronized after each login. Additionally it can be performed by scheduled task (using spring scheduler). - *
- * All requests to server are performed in background thread to avoid delays in UI. - */ -@Component(ClientTimeSynchronizer.NAME) -public class ClientTimeSynchronizer { - public static final String NAME = "cuba_ClientTimeSynchronizer"; - - protected static final int TIMEOUT_SEC = 60; - - private Logger log = LoggerFactory.getLogger(ClientTimeSynchronizer.class); - - @Inject - protected ServerInfoService serverInfoService; - @Inject - protected Configuration configuration; - @Inject - protected BackgroundWorker backgroundWorker; - @Inject - protected DesktopTimeSource timeSource; - - /** - * @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTimeZone() - */ - public void syncTimeZone() { - boolean useServerTimeZone = configuration.getConfig(DesktopConfig.class).isUseServerTimeZone(); - if (useServerTimeZone) { - backgroundWorker.handle(new ObtainServerTimeZoneTask()).execute(); - } - } - - /** - * @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTime() - */ - public void syncTime() { - if (!AppContext.isStarted()) { - return; - } - boolean useServerTime = configuration.getConfig(DesktopConfig.class).isUseServerTime(); - boolean connected = App.getInstance() != null && App.getInstance().getConnection() != null - && App.getInstance().getConnection().isConnected(); - - if (useServerTime && connected) { - backgroundWorker.handle(new UpdateTimeOffsetTask()).execute(); - } - } - - protected class ObtainServerTimeZoneTask extends BackgroundTask { - protected ObtainServerTimeZoneTask() { - super(TIMEOUT_SEC); - } - - @Override - public Void run(TaskLifeCycle taskLifeCycle) throws Exception { - TimeZone serverTimeZone = serverInfoService.getTimeZone(); - - TimeZone.setDefault(serverTimeZone); // works OK from any thread - log.info("Time zone set to " + serverTimeZone); - return null; - } - } - - protected class UpdateTimeOffsetTask extends BackgroundTask { - public UpdateTimeOffsetTask() { - super(TIMEOUT_SEC); - } - - @Override - public Void run(TaskLifeCycle taskLifeCycle) throws Exception { - long serverTime = serverInfoService.getTimeMillis(); - long timeOffset = serverTime - System.currentTimeMillis(); - - timeSource.setTimeOffset(timeOffset); // works OK from any thread - log.info("Using server time, offset=" + timeOffset + "ms"); - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.app.ServerInfoService; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.gui.executors.BackgroundTask; +import com.haulmont.cuba.gui.executors.BackgroundWorker; +import com.haulmont.cuba.gui.executors.TaskLifeCycle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import java.util.TimeZone; + +/** + * Maintains desktop client time zone and time. + *
+ * Time zone is taken from server. + * Time is synchronized after each login. Additionally it can be performed by scheduled task (using spring scheduler). + *
+ * All requests to server are performed in background thread to avoid delays in UI. + */ +@Component(ClientTimeSynchronizer.NAME) +public class ClientTimeSynchronizer { + public static final String NAME = "cuba_ClientTimeSynchronizer"; + + protected static final int TIMEOUT_SEC = 60; + + private Logger log = LoggerFactory.getLogger(ClientTimeSynchronizer.class); + + @Inject + protected ServerInfoService serverInfoService; + @Inject + protected Configuration configuration; + @Inject + protected BackgroundWorker backgroundWorker; + @Inject + protected DesktopTimeSource timeSource; + + /** + * @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTimeZone() + */ + public void syncTimeZone() { + boolean useServerTimeZone = configuration.getConfig(DesktopConfig.class).isUseServerTimeZone(); + if (useServerTimeZone) { + backgroundWorker.handle(new ObtainServerTimeZoneTask()).execute(); + } + } + + /** + * @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTime() + */ + public void syncTime() { + if (!AppContext.isStarted()) { + return; + } + boolean useServerTime = configuration.getConfig(DesktopConfig.class).isUseServerTime(); + boolean connected = App.getInstance() != null && App.getInstance().getConnection() != null + && App.getInstance().getConnection().isConnected(); + + if (useServerTime && connected) { + backgroundWorker.handle(new UpdateTimeOffsetTask()).execute(); + } + } + + protected class ObtainServerTimeZoneTask extends BackgroundTask { + protected ObtainServerTimeZoneTask() { + super(TIMEOUT_SEC); + } + + @Override + public Void run(TaskLifeCycle taskLifeCycle) throws Exception { + TimeZone serverTimeZone = serverInfoService.getTimeZone(); + + TimeZone.setDefault(serverTimeZone); // works OK from any thread + log.info("Time zone set to " + serverTimeZone); + return null; + } + } + + protected class UpdateTimeOffsetTask extends BackgroundTask { + public UpdateTimeOffsetTask() { + super(TIMEOUT_SEC); + } + + @Override + public Void run(TaskLifeCycle taskLifeCycle) throws Exception { + long serverTime = serverInfoService.getTimeMillis(); + long timeOffset = serverTime - System.currentTimeMillis(); + + timeSource.setTimeOffset(timeOffset); // works OK from any thread + log.info("Using server time, offset=" + timeOffset + "ms"); + return null; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopAppContextLoader.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopAppContextLoader.java index fc30358d62..f3fa6fccf8 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopAppContextLoader.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopAppContextLoader.java @@ -1,168 +1,168 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.google.common.base.Splitter; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AbstractAppContextLoader; -import com.haulmont.cuba.core.sys.AppComponents; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SingleSecurityContextHolder; -import com.haulmont.cuba.gui.AppConfig; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.apache.commons.lang.text.StrTokenizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * {@link AppContext} loader of the desktop client application. - * - */ -public class DesktopAppContextLoader extends AbstractAppContextLoader { - - public static final String HOME_DIR_SYS_PROP = "cuba.desktop.home"; - - public static final Pattern SEPARATOR_PATTERN = Pattern.compile("\\s"); - - public static final String APP_COMPONENTS_SYS_PROP = "cuba.appComponents"; - - public static final String APP_PROPERTIES_CONFIG_SYS_PROP = "cuba.appPropertiesConfig"; - - private String defaultAppComponents; - private String defaultAppPropertiesConfig; - private String[] args; - - private Logger log = LoggerFactory.getLogger(DesktopAppContextLoader.class); - - public DesktopAppContextLoader(String defaultAppComponents, String defaultAppPropertiesConfig, String[] args) { - this.defaultAppComponents = defaultAppComponents; - this.defaultAppPropertiesConfig = defaultAppPropertiesConfig; - this.args = args; - } - - @Override - protected String getBlock() { - return "desktop"; - } - - public void load() { - AppContext.Internals.setSecurityContextHolder(new SingleSecurityContextHolder()); - - initAppComponents(); - initAppProperties(); - afterInitAppProperties(); - - beforeInitAppContext(); - initAppContext(); - afterInitAppContext(); - - initEnvironment(); - - AppContext.Internals.startContext(); - log.info("AppContext initialized"); - } - - protected void initEnvironment() { - Configuration configuration = AppBeans.get(Configuration.NAME); - String tempPath = configuration.getConfig(GlobalConfig.class).getTempDir(); - File tempDir = new File(tempPath); - if (!tempDir.exists()) { - try { - boolean result = tempDir.mkdirs(); - if (!result) - throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, tempPath); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - } - - private void initAppComponents() { - String block = getBlock(); - - String appComponentsProp = System.getProperty(APP_COMPONENTS_SYS_PROP); - if (StringUtils.isBlank(appComponentsProp)) - appComponentsProp = defaultAppComponents; - - AppComponents appComponents; - if (StringUtils.isEmpty(appComponentsProp)) { - appComponents = new AppComponents(block); - } else { - List compNames = Splitter.on(SEPARATOR_PATTERN).omitEmptyStrings().splitToList(appComponentsProp); - appComponents = new AppComponents(compNames, block); - } - AppContext.Internals.setAppComponents(appComponents); - } - - protected void initAppProperties() { - AppContext.setProperty(AppConfig.CLIENT_TYPE_PROP, ClientType.DESKTOP.toString()); - - String appPropertiesConfig = System.getProperty(APP_PROPERTIES_CONFIG_SYS_PROP); - if (StringUtils.isBlank(appPropertiesConfig)) - appPropertiesConfig = defaultAppPropertiesConfig; - - final Properties properties = new Properties(); - - StrTokenizer tokenizer = new StrTokenizer(appPropertiesConfig); - for (String str : tokenizer.getTokenArray()) { - InputStream stream = null; - try { - stream = getClass().getResourceAsStream(str); - if (stream != null) { - Reader reader = new InputStreamReader(stream, StandardCharsets.UTF_8.name()); - properties.load(reader); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - IOUtils.closeQuietly(stream); - } - } - - for (String arg : args) { - arg = arg.trim(); - int pos = arg.indexOf('='); - if (pos > 0) { - String key = arg.substring(0, pos); - String value = arg.substring(pos + 1); - properties.setProperty(key, value); - } - } - - for (Object key : properties.keySet()) { - AppContext.setProperty((String) key, properties.getProperty((String) key).trim()); - } - - List list = new ArrayList<>(); - for (String key : AppContext.getPropertyNames()) { - list.add(key + "=" + AppContext.getProperty(key)); - } - Collections.sort(list); - log.info(new StrBuilder("AppProperties:\n").appendWithSeparators(list, "\n").toString()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.google.common.base.Splitter; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AbstractAppContextLoader; +import com.haulmont.cuba.core.sys.AppComponents; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SingleSecurityContextHolder; +import com.haulmont.cuba.gui.AppConfig; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.apache.commons.lang.text.StrTokenizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * {@link AppContext} loader of the desktop client application. + * + */ +public class DesktopAppContextLoader extends AbstractAppContextLoader { + + public static final String HOME_DIR_SYS_PROP = "cuba.desktop.home"; + + public static final Pattern SEPARATOR_PATTERN = Pattern.compile("\\s"); + + public static final String APP_COMPONENTS_SYS_PROP = "cuba.appComponents"; + + public static final String APP_PROPERTIES_CONFIG_SYS_PROP = "cuba.appPropertiesConfig"; + + private String defaultAppComponents; + private String defaultAppPropertiesConfig; + private String[] args; + + private Logger log = LoggerFactory.getLogger(DesktopAppContextLoader.class); + + public DesktopAppContextLoader(String defaultAppComponents, String defaultAppPropertiesConfig, String[] args) { + this.defaultAppComponents = defaultAppComponents; + this.defaultAppPropertiesConfig = defaultAppPropertiesConfig; + this.args = args; + } + + @Override + protected String getBlock() { + return "desktop"; + } + + public void load() { + AppContext.Internals.setSecurityContextHolder(new SingleSecurityContextHolder()); + + initAppComponents(); + initAppProperties(); + afterInitAppProperties(); + + beforeInitAppContext(); + initAppContext(); + afterInitAppContext(); + + initEnvironment(); + + AppContext.Internals.startContext(); + log.info("AppContext initialized"); + } + + protected void initEnvironment() { + Configuration configuration = AppBeans.get(Configuration.NAME); + String tempPath = configuration.getConfig(GlobalConfig.class).getTempDir(); + File tempDir = new File(tempPath); + if (!tempDir.exists()) { + try { + boolean result = tempDir.mkdirs(); + if (!result) + throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, tempPath); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + + private void initAppComponents() { + String block = getBlock(); + + String appComponentsProp = System.getProperty(APP_COMPONENTS_SYS_PROP); + if (StringUtils.isBlank(appComponentsProp)) + appComponentsProp = defaultAppComponents; + + AppComponents appComponents; + if (StringUtils.isEmpty(appComponentsProp)) { + appComponents = new AppComponents(block); + } else { + List compNames = Splitter.on(SEPARATOR_PATTERN).omitEmptyStrings().splitToList(appComponentsProp); + appComponents = new AppComponents(compNames, block); + } + AppContext.Internals.setAppComponents(appComponents); + } + + protected void initAppProperties() { + AppContext.setProperty(AppConfig.CLIENT_TYPE_PROP, ClientType.DESKTOP.toString()); + + String appPropertiesConfig = System.getProperty(APP_PROPERTIES_CONFIG_SYS_PROP); + if (StringUtils.isBlank(appPropertiesConfig)) + appPropertiesConfig = defaultAppPropertiesConfig; + + final Properties properties = new Properties(); + + StrTokenizer tokenizer = new StrTokenizer(appPropertiesConfig); + for (String str : tokenizer.getTokenArray()) { + InputStream stream = null; + try { + stream = getClass().getResourceAsStream(str); + if (stream != null) { + Reader reader = new InputStreamReader(stream, StandardCharsets.UTF_8.name()); + properties.load(reader); + } + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + IOUtils.closeQuietly(stream); + } + } + + for (String arg : args) { + arg = arg.trim(); + int pos = arg.indexOf('='); + if (pos > 0) { + String key = arg.substring(0, pos); + String value = arg.substring(pos + 1); + properties.setProperty(key, value); + } + } + + for (Object key : properties.keySet()) { + AppContext.setProperty((String) key, properties.getProperty((String) key).trim()); + } + + List list = new ArrayList<>(); + for (String key : AppContext.getPropertyNames()) { + list.add(key + "=" + AppContext.getProperty(key)); + } + Collections.sort(list); + log.info(new StrBuilder("AppProperties:\n").appendWithSeparators(list, "\n").toString()); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopToolTipManager.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopToolTipManager.java index 9ae1ab85bd..ebbbbf50e0 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopToolTipManager.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopToolTipManager.java @@ -1,303 +1,303 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -/** - * Class that encapsulates displaying of tooltips for all components. - */ -public class DesktopToolTipManager extends MouseAdapter { - - public static final int F1_CODE = 112; - - private static int CLOSE_TIME = 500; - private static int SHOW_TIME = 1000; - - private boolean tooltipShowing = false; - - private JToolTip toolTipWindow; - private Popup window; - private JComponent component; - - private Timer showTimer = new Timer(SHOW_TIME, null); - private Timer closeTimer; - - private MouseListener componentMouseListener = new ComponentMouseListener(); - private KeyListener fieldKeyListener = new FieldKeyListener(); - private ActionListener btnActionListener = new ButtonClickListener(); - - - private static DesktopToolTipManager instance; - - /** - * Return singleton instance of DesktopToolTipManager for application. - * - * @return instance of DesktopToolTipManager - */ - public static DesktopToolTipManager getInstance() { - if (instance == null) { - instance = new DesktopToolTipManager(); - } - return instance; - } - - private DesktopToolTipManager() { - closeTimer = new Timer(CLOSE_TIME, null); - closeTimer.setRepeats(false); - closeTimer.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - window.hide(); - window = null; - tooltipShowing = false; - toolTipWindow.removeMouseListener(DesktopToolTipManager.this); - component.removeMouseListener(DesktopToolTipManager.this); - - } - }); - - Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { - private MouseEvent event; - - @Override - public void eventDispatched(AWTEvent e) { - if (!tooltipShowing) { - return; - } - event = (MouseEvent) e; - if (event.getID() == MouseEvent.MOUSE_PRESSED) { - if (event.getComponent() != null && event.getComponent().isShowing()) { - if (!isPointInComponent(event.getLocationOnScreen(), toolTipWindow)) - hideTooltip(); - } else - hideTooltip(); - } - } - }, AWTEvent.MOUSE_EVENT_MASK); - } - - private boolean isPointInComponent(Point point, JComponent component) { - if (!component.isShowing()) - return false; - - Point componentLocation = component.getLocationOnScreen(); - Rectangle bounds = component.getBounds(); - return (((point.x >= componentLocation.x) && (point.x <= componentLocation.x + bounds.width)) && - (point.y >= componentLocation.y) && (point.y <= componentLocation.y + bounds.height)); - } - - /** - * Register tooltip for component. - * Tooltip is displayed when user press F1 on focused component - * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. - * - * @param component component to register - */ - public void registerTooltip(final JComponent component) { - component.removeKeyListener(fieldKeyListener); - component.addKeyListener(fieldKeyListener); - } - - /** - * Register tooltip for {@link javax.swing.AbstractButton}. - * Tooltip is displayed when the user hovers over a button - * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. - * - * @param btn Button to register - */ - public void registerTooltip(final AbstractButton btn) { - btn.removeMouseListener(componentMouseListener); - btn.addMouseListener(componentMouseListener); - } - - /** - * Register tooltip for {@link javax.swing.JLabel}. - * Tooltip is displayed when the user hovers over a label - * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. - * - * @param lbl Label to register - */ - public void registerTooltip(final JLabel lbl) { - lbl.removeMouseListener(componentMouseListener); - lbl.addMouseListener(componentMouseListener); - } - - /** - * Register tooltip for ToolTipButton. - * Tooltip is displayed when the user presses the button - * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()} . - * - * @param btn Button to register - */ - public void registerTooltip(final ToolTipButton btn) { - btn.removeActionListener(btnActionListener); - btn.addActionListener(btnActionListener); - } - - private void hideTooltip() { - closeTimer.stop(); - if (window != null) { - window.hide(); - window = null; - tooltipShowing = false; - toolTipWindow.removeMouseListener(DesktopToolTipManager.this); - component.removeMouseListener(DesktopToolTipManager.this); - } - } - - private void showTooltip(JComponent field, String text) { - if (!field.isShowing()) - return; - - PointerInfo pointerInfo = MouseInfo.getPointerInfo(); - if (pointerInfo == null) { - return; - } - - Point mouseLocation = pointerInfo.getLocation(); - Point location = new Point(); - - GraphicsConfiguration gc; - gc = field.getGraphicsConfiguration(); - Rectangle sBounds = gc.getBounds(); - Insets screenInsets = Toolkit.getDefaultToolkit() - .getScreenInsets(gc); - - sBounds.x += screenInsets.left; - sBounds.y += screenInsets.top; - sBounds.width -= (screenInsets.left + screenInsets.right); - sBounds.height -= (screenInsets.top + screenInsets.bottom); - - location.x = mouseLocation.x + 15; - location.y = mouseLocation.y + 15; - int x = location.x; - int y = location.y; - - if (toolTipWindow != null) { - hideTooltip(); - } - - component = field; - final JToolTip toolTip = new JToolTip(); - - toolTip.setTipText("" + text + ""); - final Popup tooltipContainer = PopupFactory.getSharedInstance().getPopup(field, toolTip, x, y); - tooltipContainer.show(); - window = tooltipContainer; - toolTipWindow = toolTip; - - tooltipShowing = true; - if ((!(field instanceof ToolTipButton)) && ((field instanceof AbstractButton) || (field instanceof JLabel))) { - toolTip.addMouseListener(this); - field.addMouseListener(this); - } - } - - @Override - public void mouseExited(MouseEvent e) { - closeTimer.start(); - } - - @Override - public void mouseEntered(MouseEvent e) { - if (closeTimer.isRunning()) { - closeTimer.stop(); - } - } - - private class ComponentMouseListener extends MouseAdapter { - - private JComponent cmp; - - { - showTimer.setRepeats(false); - showTimer.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (!tooltipShowing) - showTooltip(cmp, cmp.getToolTipText()); - } - }); - } - - @Override - public void mouseEntered(MouseEvent e) { - if (window != null) { - if (e.getSource() != component && e.getSource() != toolTipWindow && component instanceof AbstractButton) { - hideTooltip(); - cmp = (JComponent) e.getSource(); - showTimer.start(); - return; - } - } - if (!tooltipShowing) { - cmp = (JComponent) e.getSource(); - showTimer.start(); - } - } - - @Override - public void mouseExited(MouseEvent e) { - if (!tooltipShowing) { - if (showTimer.isRunning()) { - showTimer.stop(); - } - } - } - - @Override - public void mouseClicked(MouseEvent e) { - showTimer.stop(); - hideTooltip(); - } - } - - private class FieldKeyListener extends KeyAdapter { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == F1_CODE) { - hideTooltip(); - JComponent field = (JComponent) e.getSource(); - showTooltip(field, field.getToolTipText()); - } else { - if (tooltipShowing) { - hideTooltip(); - } - } - } - } - - private class ButtonClickListener implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - if (component == e.getSource() && tooltipShowing) { - return; - } - if (tooltipShowing) { - hideTooltip(); - } - showTooltip((JComponent) e.getSource(), ((JButton) e.getSource()).getToolTipText()); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.desktop.sys.vcl.ToolTipButton; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/** + * Class that encapsulates displaying of tooltips for all components. + */ +public class DesktopToolTipManager extends MouseAdapter { + + public static final int F1_CODE = 112; + + private static int CLOSE_TIME = 500; + private static int SHOW_TIME = 1000; + + private boolean tooltipShowing = false; + + private JToolTip toolTipWindow; + private Popup window; + private JComponent component; + + private Timer showTimer = new Timer(SHOW_TIME, null); + private Timer closeTimer; + + private MouseListener componentMouseListener = new ComponentMouseListener(); + private KeyListener fieldKeyListener = new FieldKeyListener(); + private ActionListener btnActionListener = new ButtonClickListener(); + + + private static DesktopToolTipManager instance; + + /** + * Return singleton instance of DesktopToolTipManager for application. + * + * @return instance of DesktopToolTipManager + */ + public static DesktopToolTipManager getInstance() { + if (instance == null) { + instance = new DesktopToolTipManager(); + } + return instance; + } + + private DesktopToolTipManager() { + closeTimer = new Timer(CLOSE_TIME, null); + closeTimer.setRepeats(false); + closeTimer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + window.hide(); + window = null; + tooltipShowing = false; + toolTipWindow.removeMouseListener(DesktopToolTipManager.this); + component.removeMouseListener(DesktopToolTipManager.this); + + } + }); + + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + private MouseEvent event; + + @Override + public void eventDispatched(AWTEvent e) { + if (!tooltipShowing) { + return; + } + event = (MouseEvent) e; + if (event.getID() == MouseEvent.MOUSE_PRESSED) { + if (event.getComponent() != null && event.getComponent().isShowing()) { + if (!isPointInComponent(event.getLocationOnScreen(), toolTipWindow)) + hideTooltip(); + } else + hideTooltip(); + } + } + }, AWTEvent.MOUSE_EVENT_MASK); + } + + private boolean isPointInComponent(Point point, JComponent component) { + if (!component.isShowing()) + return false; + + Point componentLocation = component.getLocationOnScreen(); + Rectangle bounds = component.getBounds(); + return (((point.x >= componentLocation.x) && (point.x <= componentLocation.x + bounds.width)) && + (point.y >= componentLocation.y) && (point.y <= componentLocation.y + bounds.height)); + } + + /** + * Register tooltip for component. + * Tooltip is displayed when user press F1 on focused component + * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. + * + * @param component component to register + */ + public void registerTooltip(final JComponent component) { + component.removeKeyListener(fieldKeyListener); + component.addKeyListener(fieldKeyListener); + } + + /** + * Register tooltip for {@link javax.swing.AbstractButton}. + * Tooltip is displayed when the user hovers over a button + * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. + * + * @param btn Button to register + */ + public void registerTooltip(final AbstractButton btn) { + btn.removeMouseListener(componentMouseListener); + btn.addMouseListener(componentMouseListener); + } + + /** + * Register tooltip for {@link javax.swing.JLabel}. + * Tooltip is displayed when the user hovers over a label + * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()}. + * + * @param lbl Label to register + */ + public void registerTooltip(final JLabel lbl) { + lbl.removeMouseListener(componentMouseListener); + lbl.addMouseListener(componentMouseListener); + } + + /** + * Register tooltip for ToolTipButton. + * Tooltip is displayed when the user presses the button + * ToolTip text is taken from {@link javax.swing.JComponent#getToolTipText()} . + * + * @param btn Button to register + */ + public void registerTooltip(final ToolTipButton btn) { + btn.removeActionListener(btnActionListener); + btn.addActionListener(btnActionListener); + } + + private void hideTooltip() { + closeTimer.stop(); + if (window != null) { + window.hide(); + window = null; + tooltipShowing = false; + toolTipWindow.removeMouseListener(DesktopToolTipManager.this); + component.removeMouseListener(DesktopToolTipManager.this); + } + } + + private void showTooltip(JComponent field, String text) { + if (!field.isShowing()) + return; + + PointerInfo pointerInfo = MouseInfo.getPointerInfo(); + if (pointerInfo == null) { + return; + } + + Point mouseLocation = pointerInfo.getLocation(); + Point location = new Point(); + + GraphicsConfiguration gc; + gc = field.getGraphicsConfiguration(); + Rectangle sBounds = gc.getBounds(); + Insets screenInsets = Toolkit.getDefaultToolkit() + .getScreenInsets(gc); + + sBounds.x += screenInsets.left; + sBounds.y += screenInsets.top; + sBounds.width -= (screenInsets.left + screenInsets.right); + sBounds.height -= (screenInsets.top + screenInsets.bottom); + + location.x = mouseLocation.x + 15; + location.y = mouseLocation.y + 15; + int x = location.x; + int y = location.y; + + if (toolTipWindow != null) { + hideTooltip(); + } + + component = field; + final JToolTip toolTip = new JToolTip(); + + toolTip.setTipText("" + text + ""); + final Popup tooltipContainer = PopupFactory.getSharedInstance().getPopup(field, toolTip, x, y); + tooltipContainer.show(); + window = tooltipContainer; + toolTipWindow = toolTip; + + tooltipShowing = true; + if ((!(field instanceof ToolTipButton)) && ((field instanceof AbstractButton) || (field instanceof JLabel))) { + toolTip.addMouseListener(this); + field.addMouseListener(this); + } + } + + @Override + public void mouseExited(MouseEvent e) { + closeTimer.start(); + } + + @Override + public void mouseEntered(MouseEvent e) { + if (closeTimer.isRunning()) { + closeTimer.stop(); + } + } + + private class ComponentMouseListener extends MouseAdapter { + + private JComponent cmp; + + { + showTimer.setRepeats(false); + showTimer.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!tooltipShowing) + showTooltip(cmp, cmp.getToolTipText()); + } + }); + } + + @Override + public void mouseEntered(MouseEvent e) { + if (window != null) { + if (e.getSource() != component && e.getSource() != toolTipWindow && component instanceof AbstractButton) { + hideTooltip(); + cmp = (JComponent) e.getSource(); + showTimer.start(); + return; + } + } + if (!tooltipShowing) { + cmp = (JComponent) e.getSource(); + showTimer.start(); + } + } + + @Override + public void mouseExited(MouseEvent e) { + if (!tooltipShowing) { + if (showTimer.isRunning()) { + showTimer.stop(); + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + showTimer.stop(); + hideTooltip(); + } + } + + private class FieldKeyListener extends KeyAdapter { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == F1_CODE) { + hideTooltip(); + JComponent field = (JComponent) e.getSource(); + showTooltip(field, field.getToolTipText()); + } else { + if (tooltipShowing) { + hideTooltip(); + } + } + } + } + + private class ButtonClickListener implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + if (component == e.getSource() && tooltipShowing) { + return; + } + if (tooltipShowing) { + hideTooltip(); + } + showTooltip((JComponent) e.getSource(), ((JButton) e.getSource()).getToolTipText()); + } + } +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopWindowManager.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopWindowManager.java index 6e7fd905f4..72245f789f 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopWindowManager.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DesktopWindowManager.java @@ -1,2164 +1,2164 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.google.common.base.Strings; -import com.haulmont.bali.util.Dom4j; -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.desktop.gui.components.DesktopAbstractComponent; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.gui.components.DesktopWindow; -import com.haulmont.cuba.desktop.sys.validation.ValidationAlertHolder; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareWindowClosingListener; -import com.haulmont.cuba.gui.*; -import com.haulmont.cuba.gui.app.core.dev.LayoutAnalyzer; -import com.haulmont.cuba.gui.app.core.dev.LayoutTip; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.Action; -import com.haulmont.cuba.gui.components.Action.Status; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.DialogAction.Type; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.Frame.MessageMode; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.gui.config.WindowInfo; -import com.haulmont.cuba.gui.executors.*; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import com.haulmont.cuba.gui.settings.SettingsImpl; -import com.haulmont.cuba.gui.theme.ThemeConstantsManager; -import com.haulmont.cuba.security.global.NoUserSessionException; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.jdesktop.swingx.JXErrorPane; -import org.jdesktop.swingx.error.ErrorInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.inject.Provider; -import javax.swing.*; -import javax.swing.Timer; -import java.awt.*; -import java.awt.event.*; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.List; - -import static com.haulmont.cuba.gui.ComponentsHelper.preprocessHtmlMessage; -import static com.haulmont.cuba.gui.components.Component.AUTO_SIZE; -import static com.haulmont.cuba.gui.components.Component.AUTO_SIZE_PX; -import static com.haulmont.cuba.gui.components.Frame.MessageType; -import static com.haulmont.cuba.gui.components.Frame.NotificationType; -import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; - -public class DesktopWindowManager extends WindowManager { - - private static final Logger log = LoggerFactory.getLogger(DesktopWindowManager.class); - private Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - - protected static final float NEW_WINDOW_SCALE = 0.7f; - - protected JTabbedPane tabsPane; - - protected final Map tabs = new HashMap<>(); - protected final Map windowOpenMode = new LinkedHashMap<>(); - protected final Map>> stacks = new HashMap<>(); - protected final Map windows = new HashMap<>(); - protected final TopLevelFrame frame; - protected final boolean isMainWindowManager; - - protected boolean disableSavingScreenHistory; - protected ScreenHistorySupport screenHistorySupport = new ScreenHistorySupport(); - - protected boolean recursiveFramesClose = false; - - public DesktopWindowManager(TopLevelFrame frame) { - this.frame = frame; - isMainWindowManager = frame == App.getInstance().getMainFrame(); - } - - public TopLevelFrame getFrame() { - return frame; - } - - public void setTabsPane(final JTabbedPane tabsPane) { - this.tabsPane = tabsPane; - - // todo move to config - tabsPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( - KeyStroke.getKeyStroke("control W"), - "closeTab" - ); - tabsPane.getActionMap().put("closeTab", new ValidationAwareAction() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - closeTab((JComponent) tabsPane.getSelectedComponent()); - } - }); - } - - protected void closeTab(JComponent tabContent) { - if (tabContent == null) - return; - WindowBreadCrumbs breadCrumbs = tabs.get(tabContent); - // may be window already closed - if (breadCrumbs != null) { - Runnable closeTask = new TabCloseTask(breadCrumbs); - closeTask.run(); - } - } - - @Override - public Collection getOpenWindows() { - return new ArrayList<>(windowOpenMode.keySet()); - } - - @Override - public void selectWindowTab(Window window) { - if (isMainWindowManager) { - WindowOpenInfo openInfo = windowOpenMode.get(window); - if (openInfo != null) { - OpenMode openMode = openInfo.getOpenMode(); - if (openMode == OpenMode.NEW_TAB - || openMode == OpenMode.THIS_TAB) { - // show in tabsheet - JComponent layout = (JComponent) openInfo.getData(); - tabsPane.setSelectedComponent(layout); - } - } - } - } - - @Override - public void setWindowCaption(Window window, String caption, String description) { - Window desktopWindow = window; - if (window instanceof Window.Wrapper) { - desktopWindow = ((Window.Wrapper) window).getWrappedWindow(); - } - window.setCaption(caption); - - String formattedCaption = formatTabDescription(caption, description); - WindowOpenInfo openInfo = windowOpenMode.get(desktopWindow); - - if (openInfo != null) { - OpenMode openMode = openInfo.getOpenMode(); - - if (openMode != OpenMode.DIALOG) { - if (tabsPane != null) { - int selectedIndex = tabsPane.getSelectedIndex(); - if (selectedIndex != -1) { - setActiveWindowCaption(caption, description, selectedIndex); - } - } else if (!isMainWindowManager) { - setTopLevelWindowCaption(formattedCaption); - } - } else { - JDialog jDialog = (JDialog) openInfo.getData(); - if (jDialog != null) { - jDialog.setTitle(formattedCaption); - } - } - } - } - - @Nullable - public DialogWindow getLastDialogWindow() { - List openedWindows = new ArrayList<>(windowOpenMode.keySet()); - if (openedWindows.size() > 0) { - Window w = openedWindows.get(openedWindows.size() - 1); - WindowOpenInfo mode = windowOpenMode.get(w); - if (mode.getOpenMode() == OpenMode.DIALOG && mode.getData() instanceof DialogWindow) { - return (DialogWindow) mode.getData(); - } - } - return null; - } - - @Override - protected void putToWindowMap(Window window, Integer hashCode) { - if (window != null) { - windows.put(window, hashCode); - } - } - - protected Integer getWindowHashCode(Window window) { - return windows.get(window); - } - - @Override - protected Window getWindow(Integer hashCode) { - Set> set = windows.entrySet(); - for (Map.Entry entry : set) { - if (hashCode.equals(entry.getValue())) { - return entry.getKey(); - } - } - return null; - } - - @Override - protected void checkCanOpenWindow(WindowInfo windowInfo, OpenType openType, Map params) { - } - - protected boolean hasModalWindow() { - for (Map.Entry entry : windowOpenMode.entrySet()) { - if (OpenMode.DIALOG == entry.getValue().getOpenMode() - && BooleanUtils.isTrue(entry.getKey().getDialogOptions().getModal())) { - return true; - } - } - return false; - } - - @Override - protected void showWindow(Window window, String caption, OpenType openType, boolean multipleOpen) { - showWindow(window, caption, null, openType, multipleOpen); - } - - @Override - protected void showWindow(final Window window, final String caption, final String description, OpenType openType, boolean multipleOpen) { - OpenType targetOpenType = openType.copy(); - - // for backward compatibility only - copyDialogParamsToOpenType(targetOpenType); - - overrideOpenTypeParams(targetOpenType, window.getDialogOptions()); - - boolean forciblyDialog = false; - boolean addWindowData = true; - if (targetOpenType.getOpenMode() != OpenMode.DIALOG && hasModalWindow()) { - targetOpenType.setOpenMode(OpenMode.DIALOG); - forciblyDialog = true; - } - - if (targetOpenType.getOpenMode() == OpenMode.THIS_TAB && tabs.size() == 0) { - targetOpenType.setOpenMode(OpenMode.NEW_TAB); - } - - window.setCaption(caption); - window.setDescription(description); - - Object windowData; - - switch (targetOpenType.getOpenMode()) { - case NEW_TAB: - if (!isMainWindowManager) { - addWindowData = false; - showInMainWindowManager(window, caption, description, targetOpenType, multipleOpen); - windowData = null; - } else { - Integer hashCode = getWindowHashCode(window); - JComponent tab; - if (hashCode != null && !multipleOpen && (tab = findTab(hashCode)) != null) { - WindowBreadCrumbs oldBreadCrumbs = tabs.get(tab); - - final Window oldWindow = oldBreadCrumbs.getCurrentWindow(); - selectWindowTab(((Window.Wrapper) oldBreadCrumbs.getCurrentWindow()).getWrappedWindow()); - - final int finalTabPosition = getTabPosition(tab); - oldWindow.closeAndRun(MAIN_MENU_ACTION_ID, new Runnable() { - @Override - public void run() { - showWindow(window, caption, description, OpenType.NEW_TAB, false); - - Window wrappedWindow = window; - if (window instanceof Window.Wrapper) { - wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); - } - - if (finalTabPosition >= 0 && finalTabPosition < tabsPane.getComponentCount() - 1) { - moveWindowTab(wrappedWindow, finalTabPosition); - } - } - }); - return; - } else { - windowData = showWindowNewTab(window, caption, description, null); - } - } - break; - case THIS_TAB: - windowData = showWindowThisTab(window, caption, description); - break; - case DIALOG: - windowData = showWindowDialog(window, caption, description, targetOpenType, forciblyDialog); - break; - case NEW_WINDOW: - addWindowData = false; - windowData = showNewWindow(window, targetOpenType, caption); - break; - default: - throw new UnsupportedOperationException(); - } - - if (addWindowData) { - addWindowData(window, windowData, targetOpenType); - } - afterShowWindow(window); - } - - protected int getTabPosition(JComponent tab) { - int position = -1; - for (int i = 0; i < tabsPane.getTabCount(); i++) { - if (tab.equals(tabsPane.getComponentAt(i))) { - position = i; - } - } - return position; - } - - /** - * @param window Window implementation (DesktopWindow) - * @param position new tab position - */ - protected void moveWindowTab(Window window, int position) { - if (isMainWindowManager && position >= 0 && position < tabsPane.getComponentCount()) { - WindowOpenInfo openInfo = windowOpenMode.get(window); - if (openInfo != null) { - OpenMode openMode = openInfo.getOpenMode(); - if (openMode == OpenMode.NEW_TAB - || openMode == OpenMode.THIS_TAB) { - // show in tabsheet - JComponent layout = (JComponent) openInfo.getData(); - - int currentPosition = getTabPosition(layout); - - String label = tabsPane.getTitleAt(currentPosition); - Icon icon = tabsPane.getIconAt(currentPosition); - Icon iconDis = tabsPane.getDisabledIconAt(currentPosition); - String tooltip = tabsPane.getToolTipTextAt(currentPosition); - boolean enabled = tabsPane.isEnabledAt(currentPosition); - int keycode = tabsPane.getMnemonicAt(currentPosition); - int mnemonicLoc = tabsPane.getDisplayedMnemonicIndexAt(currentPosition); - Color fg = tabsPane.getForegroundAt(currentPosition); - Color bg = tabsPane.getBackgroundAt(currentPosition); - java.awt.Component tabHeaderComponent = tabsPane.getTabComponentAt(currentPosition); - - tabsPane.remove(layout); - - tabsPane.insertTab(label, icon, layout, tooltip, position); - - tabsPane.setDisabledIconAt(position, iconDis); - tabsPane.setEnabledAt(position, enabled); - tabsPane.setMnemonicAt(position, keycode); - tabsPane.setDisplayedMnemonicIndexAt(position, mnemonicLoc); - tabsPane.setForegroundAt(position, fg); - tabsPane.setBackgroundAt(position, bg); - tabsPane.setTabComponentAt(position, tabHeaderComponent); - - tabsPane.setSelectedComponent(layout); - } - } - } - } - - protected void showInMainWindowManager(Window window, String caption, String description, OpenType openType, boolean multipleOpen) { - DesktopWindowManager mainMgr = App.getInstance().getMainFrame().getWindowManager(); - windows.remove(window); - window.setWindowManager(mainMgr); - mainMgr.showWindow(window, caption, openType, multipleOpen); - } - - protected TopLevelFrame createTopLevelFrame(String caption) { - final TopLevelFrame windowFrame = new TopLevelFrame(caption); - Dimension size = frame.getSize(); - int width = Math.round(size.width * NEW_WINDOW_SCALE); - int height = Math.round(size.height * NEW_WINDOW_SCALE); - - windowFrame.setSize(width, height); - windowFrame.setLocationRelativeTo(frame); - - return windowFrame; - } - - protected void closeFrame(TopLevelFrame frame) { - frame.setVisible(false); - frame.dispose(); - frame.getWindowManager().dispose(); - App.getInstance().unregisterFrame(getFrame()); - } - - protected JComponent showNewWindow(Window window, OpenType openType, String caption) { - window.setHeight("100%"); - window.setWidth("100%"); - - TopLevelFrame windowFrame = createTopLevelFrame(caption); - windowFrame.setName(window.getId()); - - Dimension dimension = new Dimension(); - - dimension.width = 800; - if (openType.getWidth() != null) { - dimension.width = openType.getWidth().intValue(); - } - - dimension.height = 500; - if (openType.getHeight() != null) { - dimension.height = openType.getHeight().intValue(); - } - - boolean resizable = true; - if (openType.getResizable() != null) { - resizable = openType.getResizable(); - } - windowFrame.setResizable(resizable); - windowFrame.setMinimumSize(dimension); - windowFrame.pack(); - - getDialogParams().reset(); - - WindowBreadCrumbs breadCrumbs = createBreadCrumbs(); - breadCrumbs.addWindow(window); - - JComponent tabContent = createTabPanel(window, breadCrumbs); - - WindowOpenInfo openInfo = new WindowOpenInfo(window, OpenMode.NEW_WINDOW); - openInfo.setData(tabContent); - Map openInfos = new HashMap<>(); - if (window instanceof Window.Wrapper) { - Window wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); - openInfos.put(wrappedWindow, openInfo); - } else { - openInfos.put(window, openInfo); - } - - windowFrame.getWindowManager().attachTab(breadCrumbs, - new Stack<>(), - window, - getWindowHashCode(window), - tabContent, openInfos); - - App.getInstance().registerFrame(windowFrame); - - windowFrame.setVisible(true); - return DesktopComponentsHelper.getComposition(window); - } - - protected void addShortcuts(Window window, OpenType openType) { - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - - String closeShortcut = clientConfig.getCloseShortcut(); - window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("closeWindowShortcutAction", closeShortcut) { - @Override - public void actionPerform(Component component) { - if (openType.getOpenMode() != OpenMode.DIALOG - || BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) { - if (!isCloseWithShortcutPrevented(window)) { - window.close("close"); - } - } - } - }); - - String previousTabShortcut = clientConfig.getPreviousTabShortcut(); - window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("onPreviousTab", previousTabShortcut) { - @Override - public void actionPerform(Component component) { - if (window.getWindowManager() != DesktopWindowManager.this) { - // detached tab - return; - } - - if (isMainWindowManager && getLastDialogWindow() == null && tabsPane.getTabCount() > 1) { - int selectedIndex = getSelectedTabIndex(); - - int newIndex = (selectedIndex + tabsPane.getTabCount() - 1) % tabsPane.getTabCount(); - java.awt.Component newTab = tabsPane.getComponentAt(newIndex); - tabsPane.setSelectedComponent(newTab); - - moveFocus(newTab); - } - } - }); - - String nextTabShortcut = clientConfig.getNextTabShortcut(); - window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("onNextTab", nextTabShortcut) { - @Override - public void actionPerform(Component component) { - if (window.getWindowManager() != DesktopWindowManager.this) { - // detached tab - return; - } - - if (isMainWindowManager && getLastDialogWindow() == null && tabsPane.getTabCount() > 1) { - int selectedIndex = getSelectedTabIndex(); - - int newIndex = (selectedIndex + 1) % tabsPane.getTabCount(); - java.awt.Component newTab = tabsPane.getComponentAt(newIndex); - tabsPane.setSelectedComponent(newTab); - - moveFocus(newTab); - } - } - }); - } - - protected void moveFocus(java.awt.Component tab) { - Window window = tabs.get(tab).getCurrentWindow(); - - if (window != null) { - String focusComponentId = window.getFocusComponent(); - - boolean focused = false; - if (focusComponentId != null) { - com.haulmont.cuba.gui.components.Component focusComponent = window.getComponent(focusComponentId); - if (focusComponent != null) { - if (focusComponent.isEnabled() && focusComponent.isVisible()) { - focusComponent.requestFocus(); - focused = true; - } - } - } - - if (!focused && window instanceof Window.Wrapper) { - Window.Wrapper wrapper = (Window.Wrapper) window; - focused = ((DesktopWindow) wrapper.getWrappedWindow()).findAndFocusChildComponent(); - if (!focused) { - tabsPane.requestFocus(); - } - } - } - } - - protected int getSelectedTabIndex() { - java.awt.Component selectedComponent = tabsPane.getSelectedComponent(); - for (int i = 0; i < tabsPane.getTabCount(); i++) { - if (selectedComponent == tabsPane.getComponentAt(i)) { - return i; - } - } - return -1; - } - - protected JDialog showWindowDialog(final Window window, String caption, String description, OpenType openType, boolean forciblyDialog) { - final DialogWindow dialog = new DialogWindow(frame, caption); - dialog.setName(window.getId()); - dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - - JComponent jComponent = DesktopComponentsHelper.getComposition(window); - dialog.add(jComponent); - - dialog.addWindowListener(new ValidationAwareWindowClosingListener() { - @Override - public void windowClosingAfterValidation(WindowEvent e) { - if (BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) { - if (!isCloseWithCloseButtonPrevented(window)) { - if (window.close("close")) { - dialog.dispose(); - } - } - } - } - }); - - Dimension dim = new Dimension(); - if (forciblyDialog) { - // todo move it to desktop application preferences - dim.width = 800; - dim.height = 500; - - dialog.setResizable(BooleanUtils.isNotFalse(openType.getResizable())); - if (!dialog.isResizable()) { - dialog.setFixedHeight(dim.height); - dialog.setFixedWidth(dim.width); - } - - window.setHeight("100%"); - } else { - dialog.setResizable(BooleanUtils.isTrue(openType.getResizable())); - if (openType.getWidth() == null) { - dim.width = 600; - if (!dialog.isResizable()) { - dialog.setFixedWidth(dim.width); - } - } else if (openType.getWidth() == DialogParams.AUTO_SIZE_PX) { - window.setWidth(AUTO_SIZE); - } else { - if (openType.getWidthUnit() != null && openType.getWidthUnit() != SizeUnit.PIXELS) { - throw new UnsupportedOperationException("Dialog size can be set only in pixels"); - } - dim.width = openType.getWidth().intValue(); - if (!dialog.isResizable()) { - dialog.setFixedWidth(dim.width); - } - } - - if (openType.getHeight() != null && openType.getHeight() != DialogParams.AUTO_SIZE_PX) { - if (openType.getHeightUnit() != null && openType.getHeightUnit() != SizeUnit.PIXELS) { - throw new UnsupportedOperationException("Dialog size can be set only in pixels"); - } - dim.height = openType.getHeight().intValue(); - if (!dialog.isResizable()) { - dialog.setFixedHeight(dim.height); - } - window.setHeight("100%"); - } else { - window.setHeight(AUTO_SIZE); - } - } - - getDialogParams().reset(); - - dialog.setMinimumSize(dim); - dialog.pack(); - - if (openType.getPositionY() == null - && openType.getPositionX() == null) { - dialog.setLocationRelativeTo(frame); - } else { - dialog.setLocation( - openType.getPositionX() != null ? openType.getPositionX() : 0, - openType.getPositionY() != null ? openType.getPositionY() : 0 - ); - } - - boolean modal = true; - if (!hasModalWindow() && openType.getModal() != null) { - modal = openType.getModal(); - } - - if (modal) { - DialogWindow lastDialogWindow = getLastDialogWindow(); - if (lastDialogWindow == null) - frame.deactivate(null); - else - lastDialogWindow.disableWindow(null); - - dialog.setSoftModal(true); - } - - dialog.setVisible(true); - - JPopupMenu popupMenu = createWindowPopupMenu(window); - if (popupMenu.getComponentCount() > 0) { - jComponent.setComponentPopupMenu(popupMenu); - } - - return dialog; - } - - protected JComponent showWindowThisTab(Window window, String caption, String description) { - getDialogParams().reset(); - - window.setWidth("100%"); - window.setHeight("100%"); - - JComponent layout; - if (isMainWindowManager) { - layout = (JComponent) tabsPane.getSelectedComponent(); - } else { - layout = (JComponent) frame.getContentPane().getComponent(0); - } - WindowBreadCrumbs breadCrumbs = tabs.get(layout); - if (breadCrumbs == null) - throw new IllegalStateException("BreadCrumbs not found"); - - Window currentWindow = breadCrumbs.getCurrentWindow(); - Window currentWindowFrame = (Window) currentWindow.getFrame(); - windowOpenMode.get(currentWindowFrame).setFocusOwner(frame.getFocusOwner()); - - Set> set = windows.entrySet(); - boolean pushed = false; - for (Map.Entry entry : set) { - if (entry.getKey().equals(currentWindow)) { - windows.remove(currentWindow); - stacks.get(breadCrumbs).push(entry); - pushed = true; - break; - } - } - if (!pushed) { - stacks.get(breadCrumbs).push(new AbstractMap.SimpleEntry<>(currentWindow, null)); - } - - windows.remove(window); - layout.remove(DesktopComponentsHelper.getComposition(currentWindow)); - - JComponent component = DesktopComponentsHelper.getComposition(window); - layout.add(component); - - breadCrumbs.addWindow(window); - if (isMainWindowManager) { - setActiveWindowCaption(caption, description, tabsPane.getSelectedIndex()); - } else { - setTopLevelWindowCaption(caption); - component.revalidate(); - component.repaint(); - } - - return layout; - } - - protected void setActiveWindowCaption(String caption, String description, int tabIndex) { - ButtonTabComponent tabComponent = (ButtonTabComponent) tabsPane.getTabComponentAt(tabIndex); - String formattedCaption = formatTabCaption(caption, description); - tabComponent.setCaption(formattedCaption); - } - - protected void setTopLevelWindowCaption(String caption) { - frame.setTitle(caption); - } - - protected WindowBreadCrumbs createBreadCrumbs() { - final WindowBreadCrumbs breadCrumbs = new WindowBreadCrumbs(); - breadCrumbs.addListener( - new WindowBreadCrumbs.Listener() { - @Override - public void windowClick(final Window window) { - Runnable op = new Runnable() { - @Override - public void run() { - Window currentWindow = breadCrumbs.getCurrentWindow(); - if (currentWindow != null && window != currentWindow) { - if (!isCloseWithCloseButtonPrevented(currentWindow)) { - currentWindow.closeAndRun("close", this); - } - } - } - }; - op.run(); - } - } - ); - return breadCrumbs; - } - - protected JComponent showWindowNewTab(Window window, String caption, String description, Integer tabPosition) { - getDialogParams().reset(); - - window.setWidth("100%"); - window.setHeight("100%"); - - final WindowBreadCrumbs breadCrumbs = createBreadCrumbs(); - stacks.put(breadCrumbs, new Stack<>()); - - breadCrumbs.addWindow(window); - JComponent tabContent = createNewTab(window, caption, description, breadCrumbs, tabPosition); - tabs.put(tabContent, breadCrumbs); - return tabContent; - } - - protected JPanel createTabPanel(Window window, WindowBreadCrumbs breadCrumbs) { - JPanel panel = new JPanel(new BorderLayout()); - panel.add(breadCrumbs, BorderLayout.NORTH); - JComponent composition = DesktopComponentsHelper.getComposition(window); - panel.add(composition, BorderLayout.CENTER); - return panel; - } - - protected JComponent createNewTab(Window window, String caption, String description, WindowBreadCrumbs breadCrumbs, Integer tabPosition) { - JPanel panel = createTabPanel(window, breadCrumbs); - int idx; - if (tabPosition != null) { - idx = tabPosition; - } else { - idx = tabsPane.getTabCount(); - } - tabsPane.insertTab(formatTabCaption(caption, description), null, panel, null, idx); - - ButtonTabComponent tabComponent = new ButtonTabComponent( - tabsPane, true, true, - new ButtonTabComponent.CloseListener() { - @Override - public void onTabClose(final int tabIndex) { - ValidationAlertHolder.runIfValid(new Runnable() { - @Override - public void run() { - JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); - closeTab(tabContent); - } - }); - } - }, - new ButtonTabComponent.DetachListener() { - @Override - public void onDetach(final int tabIndex) { - ValidationAlertHolder.runIfValid(new Runnable() { - @Override - public void run() { - detachTab(tabIndex); - } - }); - } - } - ); - tabsPane.setTabComponentAt(idx, tabComponent); - tabsPane.setSelectedIndex(idx); - - initTabContextMenu(tabComponent); - - return panel; - } - - protected void initTabContextMenu(JComponent tabComponent) { - tabComponent.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - dispatchToParent(e); - if (e.isPopupTrigger()) { - showTabPopup(e); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - dispatchToParent(e); - if (e.isPopupTrigger()) { - showTabPopup(e); - } - } - - @Override - public void mouseEntered(MouseEvent e) { - dispatchToParent(e); - } - - @Override - public void mouseMoved(MouseEvent e) { - dispatchToParent(e); - } - - @Override - public void mouseDragged(MouseEvent e) { - dispatchToParent(e); - } - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - dispatchToParent(e); - } - - @Override - public void mouseExited(MouseEvent e) { - dispatchToParent(e); - } - - @Override - public void mouseClicked(MouseEvent e) { - dispatchToParent(e); - } - - public void dispatchToParent(MouseEvent e) { - tabsPane.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, tabsPane)); - } - }); - } - - public void showTabPopup(MouseEvent e) { - JComponent tabHeaderComponent = (JComponent) e.getComponent(); - int tabIndex = getTabIndex(tabHeaderComponent); - JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); - WindowBreadCrumbs windowBreadCrumbs = tabs.get(tabContent); - - Window window = windowBreadCrumbs.getCurrentWindow(); - - JPopupMenu popupMenu = createWindowPopupMenu(window); - if (popupMenu.getComponentCount() > 0) { - popupMenu.show(tabHeaderComponent, e.getX(), e.getY()); - } - } - - protected int getTabIndex(java.awt.Component tabHeaderComponent) { - for (int i = 0; i < tabsPane.getTabCount(); i++) { - if (tabsPane.getTabComponentAt(i) == tabHeaderComponent) - return i; - } - return -1; - } - - protected JPopupMenu createWindowPopupMenu(final Window window) { - JPopupMenu popupMenu = new JPopupMenu(); - - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - - if (clientConfig.getManualScreenSettingsSaving()) { - JMenuItem saveSettingsItem = new JMenuItem(messages.getMainMessage("actions.saveSettings")); - saveSettingsItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - window.saveSettings(); - } - }); - popupMenu.add(saveSettingsItem); - - JMenuItem restoreToDefaultsItem = new JMenuItem(messages.getMainMessage("actions.restoreToDefaults")); - restoreToDefaultsItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - window.deleteSettings(); - } - }); - popupMenu.add(restoreToDefaultsItem); - } - if (clientConfig.getLayoutAnalyzerEnabled()) { - JMenuItem analyzeLayoutItem = new JMenuItem(messages.getMainMessage("actions.analyzeLayout")); - analyzeLayoutItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - LayoutAnalyzer analyzer = new LayoutAnalyzer(); - List tipsList = analyzer.analyze(window); - - if (tipsList.isEmpty()) { - showNotification("No layout problems found", NotificationType.HUMANIZED); - } else { - window.openWindow("layoutAnalyzer", OpenType.DIALOG, ParamsMap.of("tipsList", tipsList)); - } - } - }); - popupMenu.add(analyzeLayoutItem); - } - return popupMenu; - } - - protected void detachTab(int tabIndex) { - //Create new top-level frame, put this tab to it with breadcrumbs. - // remove tab data from this window manager - JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); - WindowBreadCrumbs breadCrumbs = tabs.get(tabContent); - Window window = breadCrumbs.getCurrentWindow(); - - if (window == null) { - throw new IllegalArgumentException("window is null"); - } - - //WindowOpenMode map - Map detachOpenModes = new HashMap<>(); - detachOpenModes.put((Window) window.getFrame(), windowOpenMode.get(window.getFrame())); - windowOpenMode.remove(window.getFrame()); - Stack> stack = stacks.get(breadCrumbs); - for (Map.Entry entry : stack) { - WindowOpenInfo openInfo = windowOpenMode.get(entry.getKey().getFrame()); - detachOpenModes.put((Window) entry.getKey().getFrame(), openInfo); - windowOpenMode.remove(entry.getKey().getFrame()); - } - - tabs.remove(tabContent); - - Integer hashCode = windows.remove(window); - tabsPane.remove(tabIndex); - stacks.remove(breadCrumbs); - - final TopLevelFrame windowFrame = createTopLevelFrame(window.getCaption()); - App.getInstance().registerFrame(windowFrame); - windowFrame.setVisible(true); - windowFrame.getWindowManager().attachTab(breadCrumbs, stack, window, hashCode, tabContent, detachOpenModes); - } - - public void attachTab(WindowBreadCrumbs breadCrumbs, Stack> stack, - Window window, Integer hashCode, final JComponent tabContent, - Map openInfos) { - frame.add(tabContent); - frame.addWindowListener(new ValidationAwareWindowClosingListener() { - @Override - public void windowClosingAfterValidation(WindowEvent e) { - closeTab(tabContent); - } - }); - tabs.put(tabContent, breadCrumbs); - windowOpenMode.putAll(openInfos); - stacks.put(breadCrumbs, stack); - for (Map.Entry entry : stack) { - entry.getKey().setWindowManager(this); - } - window.setWindowManager(this); - if (hashCode != null) { - windows.put(window, hashCode); - } - - JPopupMenu popupMenu = createWindowPopupMenu(window); - if (popupMenu.getComponentCount() > 0) { - frame.getRootPane().setComponentPopupMenu(popupMenu); - } - } - - protected String formatTabCaption(String caption, String description) { - String s = formatTabDescription(caption, description); - int maxLength = configuration.getConfig(DesktopConfig.class).getMainTabCaptionLength(); - if (s.length() > maxLength) { - return s.substring(0, maxLength) + "..."; - } else { - return s; - } - } - - protected String formatTabDescription(final String caption, final String description) { - if (!StringUtils.isEmpty(description)) { - return String.format("%s: %s", caption, description); - } else { - return caption; - } - } - - @Override - protected void showFrame(Component parent, Frame frame) { - // the same as web window manager does - if (parent instanceof Component.Container) { - Component.Container container = (Component.Container) parent; - for (Component c : container.getComponents()) { - if (c instanceof Component.Disposable) { - Component.Disposable disposable = - (Component.Disposable) c; - if (!disposable.isDisposed()) { - disposable.dispose(); - } - } - container.remove(c); - } - container.add(frame); - } else { - throw new IllegalStateException( - "Parent component must be com.haulmont.cuba.gui.components.Component.Container" - ); - } - } - - @Override - public void close(Window window) { - if (window instanceof Window.Wrapper) { - window = ((Window.Wrapper) window).getWrappedWindow(); - } - - final WindowOpenInfo openInfo = windowOpenMode.get(window); - if (openInfo == null) { - log.warn("Problem closing window " + window + " : WindowOpenMode not found"); - return; - } - disableSavingScreenHistory = false; - closeWindow(window, openInfo); - windowOpenMode.remove(window); - windows.remove(openInfo.getWindow()); - } - - protected void closeWindow(Window window, WindowOpenInfo openInfo) { - if (!disableSavingScreenHistory) { - screenHistorySupport.saveScreenHistory(window, openInfo.getOpenMode()); - } - - switch (openInfo.getOpenMode()) { - case DIALOG: { - JDialog dialog = (JDialog) openInfo.getData(); - dialog.setVisible(false); - dialog.dispose(); - cleanupAfterModalDialogClosed(window); - - fireListeners(window, tabs.size() != 0); - break; - } - case NEW_TAB: - case NEW_WINDOW: { - JComponent layout = (JComponent) openInfo.getData(); - layout.remove(DesktopComponentsHelper.getComposition(window)); - if (isMainWindowManager) { - tabsPane.remove(layout); - } - - WindowBreadCrumbs windowBreadCrumbs = tabs.get(layout); - if (windowBreadCrumbs != null) { - windowBreadCrumbs.clearListeners(); - windowBreadCrumbs.removeWindow(); - } - - tabs.remove(layout); - stacks.remove(windowBreadCrumbs); - - fireListeners(window, tabs.size() != 0); - if (!isMainWindowManager) { - closeFrame(getFrame()); - } - break; - } - case THIS_TAB: { - JComponent layout = (JComponent) openInfo.getData(); - - final WindowBreadCrumbs breadCrumbs = tabs.get(layout); - if (breadCrumbs == null) - throw new IllegalStateException("Unable to close screen: breadCrumbs not found"); - - breadCrumbs.removeWindow(); - Window currentWindow = breadCrumbs.getCurrentWindow(); - if (!stacks.get(breadCrumbs).empty()) { - Map.Entry entry = stacks.get(breadCrumbs).pop(); - putToWindowMap(entry.getKey(), entry.getValue()); - } - JComponent component = DesktopComponentsHelper.getComposition(currentWindow); - Window currentWindowFrame = (Window) currentWindow.getFrame(); - final java.awt.Component focusedCmp = windowOpenMode.get(currentWindowFrame).getFocusOwner(); - if (focusedCmp != null) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - focusedCmp.requestFocus(); - } - }); - } - layout.remove(DesktopComponentsHelper.getComposition(window)); - - if (App.getInstance().getConnection().isConnected()) { - layout.add(component); - if (isMainWindowManager) { - // If user clicked on close button maybe selectedIndex != tabsPane.getSelectedIndex() - // Refs #1117 - int selectedIndex = 0; - while ((selectedIndex < tabs.size()) && - (tabsPane.getComponentAt(selectedIndex) != layout)) { - selectedIndex++; - } - if (selectedIndex == tabs.size()) { - selectedIndex = tabsPane.getSelectedIndex(); - } - - setActiveWindowCaption(currentWindow.getCaption(), currentWindow.getDescription(), selectedIndex); - } else { - setTopLevelWindowCaption(currentWindow.getCaption()); - component.revalidate(); - component.repaint(); - } - } - - fireListeners(window, tabs.size() != 0); - break; - } - - default: - throw new UnsupportedOperationException(); - } - } - - protected void cleanupAfterModalDialogClosed(@Nullable Window closingWindow) { - WindowOpenInfo previous = null; - for (Iterator it = windowOpenMode.keySet().iterator(); it.hasNext(); ) { - Window w = it.next(); - // Check if there is a modal window opened before the current - WindowOpenInfo mode = windowOpenMode.get(w); - if (w != closingWindow && mode.getOpenMode() == OpenMode.DIALOG) { - previous = mode; - } - // If there are windows opened after the current, close them - if (w == closingWindow && it.hasNext()) { - close(it.next()); - break; - } - } - if (previous == null) { - frame.activate(); - } else if (previous.getData() instanceof DialogWindow) { - ((DialogWindow) previous.getData()).enableWindow(); - } else if (previous.getData() instanceof JDialog) { - ((JDialog) previous.getData()).requestFocus(); - } - } - - @Override - public void showNotification(String caption) { - showNotification(caption, null, NotificationType.HUMANIZED); - } - - @Override - public void showNotification(String caption, NotificationType type) { - showNotification(caption, null, type); - } - - @Override - public void showNotification(String caption, String description, NotificationType type) { - backgroundWorker.checkUIAccess(); - - DesktopConfig config = configuration.getConfig(DesktopConfig.class); - - if (!NotificationType.isHTML(type)) { - caption = preprocessHtmlMessage(escapeHtml(Strings.nullToEmpty(caption))); - description = preprocessHtmlMessage(escapeHtml(Strings.nullToEmpty(description))); - } - - String text = preparePopupText(caption, description); - if (config.isDialogNotificationsEnabled() - && type != NotificationType.TRAY - && type != NotificationType.TRAY_HTML) { - showNotificationDialog(text, type); - } else { - showNotificationPopup(text, type); - } - } - - protected void showNotificationDialog(String text, NotificationType type) { - String title = messages.getMainMessage("notification.title." + type); - - Icon icon = convertNotificationType(type); - - showOptionDialog(title, text, null, icon, false, new Action[]{ - new DesktopNotificationAction(Type.CLOSE) - }, "notificationDialog"); - } - - protected void showNotificationPopup(String popupText, NotificationType type) { - JPanel panel = new JPanel(new MigLayout("flowy")); - panel.setBorder(BorderFactory.createLineBorder(Color.gray)); - - switch (type) { - case WARNING: - case WARNING_HTML: - panel.setBackground(Color.yellow); - break; - case ERROR: - case ERROR_HTML: - panel.setBackground(Color.orange); - break; - default: - panel.setBackground(Color.cyan); - } - - JLabel label = new JLabel(popupText); - panel.add(label); - - Dimension labelSize = DesktopComponentsHelper.measureHtmlText(popupText); - - int x = frame.getX() + frame.getWidth() - (50 + labelSize.getSize().width); - int y = frame.getY() + frame.getHeight() - (50 + labelSize.getSize().height); - - PopupFactory factory = PopupFactory.getSharedInstance(); - final Popup popup = factory.getPopup(frame, panel, x, y); - popup.show(); - - panel.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - popup.hide(); - } - }); - - PointerInfo pointerInfo = MouseInfo.getPointerInfo(); - if (pointerInfo != null) { - final Point location = pointerInfo.getLocation(); - final Timer timer = new Timer(3000, null); - timer.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - PointerInfo currentPointer = MouseInfo.getPointerInfo(); - if (currentPointer == null) { - timer.stop(); - } else if (!currentPointer.getLocation().equals(location)) { - popup.hide(); - timer.stop(); - } - } - }); - timer.start(); - } - } - - protected String preparePopupText(String caption, String description) { - if (StringUtils.isNotBlank(description)) { - caption = String.format("%s
%s", caption, description); - } - StringBuilder sb = new StringBuilder(""); - String[] strings = caption.split("(
)|(
)"); - for (String string : strings) { - sb.append(string).append("
"); - } - sb.append(""); - return sb.toString(); - } - - @Override - public void showMessageDialog(final String title, final String message, MessageType messageType) { - showOptionDialog(title, message, messageType, false, new Action[]{ - new DialogAction(Type.OK) - }, "messageDialog"); - } - - protected JPanel createButtonsPanel(Action[] actions, final DialogWindow dialog) { - JPanel buttonsPanel = new JPanel(); - - boolean hasPrimaryAction = false; - for (final Action action : actions) { - JButton button = new JButton(action.getCaption()); - String icon = action.getIcon(); - - if (icon != null) { - button.setIcon(App.getInstance().getResources().getIcon(icon)); - } - - final DialogActionHandler dialogActionHandler = new DialogActionHandler(dialog, action); - button.addActionListener(dialogActionHandler); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - JButton b = (JButton) e.getSource(); - userActionsLog.trace("Button (name = {}, text = {}) was clicked in dialog", b.getName(), b.getText()); - } - }); - if (actions.length == 1) { - dialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - dialogActionHandler.onClose(); - } - }); - } - - button.setPreferredSize(new Dimension(button.getPreferredSize().width, DesktopComponentsHelper.BUTTON_HEIGHT)); - button.setMaximumSize(new Dimension(Integer.MAX_VALUE, DesktopComponentsHelper.BUTTON_HEIGHT)); - - if (action instanceof AbstractAction && ((AbstractAction) action).isPrimary()) { - hasPrimaryAction = true; - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - button.requestFocus(); - } - }); - } - - buttonsPanel.add(button); - } - - if (!hasPrimaryAction && actions.length > 0) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - buttonsPanel.getComponent(0).requestFocus(); - } - }); - } - - return buttonsPanel; - } - - public WindowBreadCrumbs getBreadCrumbs(JComponent container) { - return tabs.get(container); - } - - protected void assignDialogShortcuts(final JDialog dialog, JPanel panel, final Action[] actions) { - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - - InputMap inputMap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - ActionMap actionMap = panel.getActionMap(); - - String commitShortcut = getConfigValueIfConnected(clientConfig::getCommitShortcut, "cuba.gui.commitShortcut", "CTRL-ENTER"); - - KeyCombination okCombination = KeyCombination.create(commitShortcut); - KeyStroke okKeyStroke = DesktopComponentsHelper.convertKeyCombination(okCombination); - - inputMap.put(okKeyStroke, "okAction"); - actionMap.put("okAction", new javax.swing.AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - for (Action action : actions) { - if (action instanceof DialogAction) { - switch (((DialogAction) action).getType()) { - case OK: - case YES: - action.actionPerform(null); - dialog.setVisible(false); - cleanupAfterModalDialogClosed(null); - return; - } - } - } - } - }); - - String closeShortcut = getConfigValueIfConnected(clientConfig::getCloseShortcut, "cuba.gui.closeShortcut", "ESCAPE"); - - KeyCombination closeCombination = KeyCombination.create(closeShortcut); - KeyStroke closeKeyStroke = DesktopComponentsHelper.convertKeyCombination(closeCombination); - - inputMap.put(closeKeyStroke, "closeAction"); - actionMap.put("closeAction", new javax.swing.AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (actions.length == 1) { - actions[0].actionPerform(null); - dialog.setVisible(false); - cleanupAfterModalDialogClosed(null); - } else { - for (Action action : actions) { - if (action instanceof DialogAction) { - switch (((DialogAction) action).getType()) { - case CANCEL: - case CLOSE: - case NO: - action.actionPerform(null); - dialog.setVisible(false); - cleanupAfterModalDialogClosed(null); - return; - } - } - } - } - } - }); - } - - protected void showOptionDialog(final String title, final String message, MessageType messageType, - boolean alwaysModal, final Action[] actions, String debugName) { - Icon icon = convertMessageType(messageType.getMessageMode()); - - String msg = message; - if (!MessageType.isHTML(messageType)) { - msg = StringEscapeUtils.escapeHtml(msg); - msg = ComponentsHelper.preprocessHtmlMessage("" + msg + ""); - } else { - msg = "" + msg + ""; - } - - showOptionDialog(title, msg, messageType, icon, alwaysModal, actions, debugName); - } - - protected void showOptionDialog(final String title, final String message, @Nullable MessageType messageType, - final Icon icon, boolean alwaysModal, final Action[] actions, String debugName) { - final DialogWindow dialog = new DialogWindow(frame, title); - - if (App.getInstance().isTestMode()) { - dialog.setName(debugName); - } - dialog.setModal(false); - - if (actions.length > 1) { - dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); - } - - int width = 500; - SizeUnit unit = null; - DialogParams dialogParams = getDialogParams(); - if (messageType != null && messageType.getWidth() != null) { - width = messageType.getWidth().intValue(); - unit = messageType.getWidthUnit(); - } else if (dialogParams.getWidth() != null) { - width = dialogParams.getWidth().intValue(); - unit = dialogParams.getWidthUnit(); - } - - LC lc = new LC(); - lc.insets("10"); - - MigLayout layout = new MigLayout(lc); - final JPanel panel = new JPanel(layout); - if (icon != null) { - JLabel iconLabel = new JLabel(icon); - panel.add(iconLabel, "aligny top"); - } - - JLabel msgLabel = new JLabel(message); - - if (width != AUTO_SIZE_PX) { - panel.add(msgLabel, "width 100%, wrap, growy 0"); - } else { - panel.add(msgLabel, "wrap"); - } - - if (icon != null) { - panel.add(new JLabel(" ")); - } - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - dialog.requestFocus(); - } - }); - - final JPanel buttonsPanel = createButtonsPanel(actions, dialog); - panel.add(buttonsPanel, "alignx right"); - - if (width != AUTO_SIZE_PX) { - if (unit != null && unit != SizeUnit.PIXELS) { - throw new UnsupportedOperationException("Dialog size can be set only in pixels"); - } - dialog.setLayout(new MigLayout(new LC().insets("0").width(width + "px"))); - dialog.setFixedWidth(width); - dialog.add(panel, "width 100%, growy 0"); - } else { - dialog.add(panel); - } - - assignDialogShortcuts(dialog, panel, actions); - - dialog.pack(); - dialog.setResizable(false); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - panel.revalidate(); - panel.repaint(); - - java.awt.Container container = panel.getTopLevelAncestor(); - if (container instanceof JDialog) { - JDialog dialog = (JDialog) container; - dialog.pack(); - } - } - }); - dialog.setLocationRelativeTo(frame); - - boolean modal = true; - if (!alwaysModal) { - if (!hasModalWindow()) { - if (messageType != null && messageType.getModal() != null) { - modal = messageType.getModal(); - } else if (dialogParams.getModal() != null) { - modal = dialogParams.getModal(); - } - } - } else { - if (messageType != null && messageType.getModal() != null) { - log.warn("MessageType.modal is not supported for showOptionDialog"); - } - } - - if (modal) { - DialogWindow lastDialogWindow = getLastDialogWindow(); - if (lastDialogWindow == null) { - frame.deactivate(null); - } else { - lastDialogWindow.disableWindow(null); - } - } - - dialog.setVisible(true); - } - - @Override - public void showExceptionDialog(Throwable throwable) { - showExceptionDialog(throwable, null, null); - } - - @Override - public void showExceptionDialog(Throwable throwable, @Nullable String caption, @Nullable String message) { - Preconditions.checkNotNullArgument(throwable); - - JXErrorPane errorPane = new JXErrorPaneExt(); - errorPane.setErrorInfo(createErrorInfo(caption, message, throwable)); - - final TopLevelFrame mainFrame = App.getInstance().getMainFrame(); - - JDialog dialog = JXErrorPane.createDialog(mainFrame, errorPane); - dialog.setMinimumSize(new Dimension(600, (int) dialog.getMinimumSize().getHeight())); - - final DialogWindow lastDialogWindow = getLastDialogWindow(); - dialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - if (lastDialogWindow != null) { - lastDialogWindow.enableWindow(); - } else { - mainFrame.activate(); - } - } - }); - dialog.setModal(false); - - if (lastDialogWindow != null) { - lastDialogWindow.disableWindow(null); - } else { - mainFrame.deactivate(null); - } - - dialog.setVisible(true); - } - - protected ErrorInfo createErrorInfo(String caption, String message, Throwable exception) { - UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - Security security = AppBeans.get(Security.NAME); - if (userSessionSource.getUserSession() == null - || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { - - String dialogCaption = StringUtils.isNotEmpty(caption) ? caption : getMessage("errorPane.title"); - String dialogMessage = StringUtils.isNotEmpty(message) ? message : getMessage("exceptionDialog.contactAdmin"); - - return new ErrorInfo(dialogCaption, dialogMessage,null, null, null, null, null); - } - - Throwable rootCause = ExceptionUtils.getRootCause(exception); - if (rootCause == null) - rootCause = exception; - - StringBuilder msg = new StringBuilder(); - if (rootCause instanceof RemoteException) { - RemoteException re = (RemoteException) rootCause; - if (!re.getCauses().isEmpty()) { - RemoteException.Cause cause = re.getCauses().get(re.getCauses().size() - 1); - if (cause.getThrowable() != null) - rootCause = cause.getThrowable(); - else { - // root cause is not supported by client - String className = cause.getClassName(); - if (className != null && className.indexOf('.') > 0) { - className = className.substring(className.lastIndexOf('.') + 1); - } - msg.append(className).append(": ").append(cause.getMessage()); - } - } - } - - if (msg.length() == 0) { - msg.append(rootCause.getClass().getSimpleName()); - if (!StringUtils.isBlank(rootCause.getMessage())) - msg.append(": ").append(rootCause.getMessage()); - - if (rootCause instanceof DevelopmentException) { - Map params = new LinkedHashMap<>(); - if (rootCause instanceof GuiDevelopmentException) { - GuiDevelopmentException guiDevException = (GuiDevelopmentException) rootCause; - if (guiDevException.getFrameId() != null) { - params.put("Frame ID", guiDevException.getFrameId()); - try { - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - params.put("XML descriptor", - windowConfig.getWindowInfo(guiDevException.getFrameId()).getTemplate()); - } catch (Exception e) { - params.put("XML descriptor", "not found for " + guiDevException.getFrameId()); - } - } - } - params.putAll(((DevelopmentException) rootCause).getParams()); - - if (!params.isEmpty()) { - msg.append("\n\n"); - for (Map.Entry entry : params.entrySet()) { - msg.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } - } - } - } - - return new ErrorInfo(getMessage("errorPane.title"), msg.toString(), - null, null, rootCause, null, null); - } - - protected String getMessage(String key) { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage(key, App.getInstance().getLocale()); - } - - /** - * Handler for OptionDialog, MessageDialog, NotificationPopup buttons, - * also used for handling dialog close event if dialog has only one action. - */ - protected class DialogActionHandler extends WindowAdapter implements ActionListener { - - protected Action action; - - protected final DialogWindow dialog; - - protected final java.awt.Component lastFocusedComponent; - - public DialogActionHandler(DialogWindow dialog, Action action) { - this.action = action; - this.dialog = dialog; - this.dialog.addWindowListener(this); - - DialogWindow lastDialogWindow = getLastDialogWindow(); - if (lastDialogWindow != null) { - lastFocusedComponent = lastDialogWindow.getFocusOwner(); - } else { - lastFocusedComponent = frame.getFocusOwner(); - } - } - - public void onClose() { - if (lastFocusedComponent != null - && lastFocusedComponent.isEnabled() - && lastFocusedComponent.isVisible() - && !(lastFocusedComponent instanceof JDialog) - && !(lastFocusedComponent instanceof JFrame)) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - lastFocusedComponent.requestFocus(); - } - }); - } - - action.actionPerform(null); - dialog.setVisible(false); - cleanupAfterModalDialogClosed(null); - dialog.dispose(); - } - - @Override - public void actionPerformed(ActionEvent e) { - onClose(); - } - - @Override - public void windowClosed(WindowEvent e) { - action = null; - } - } - - protected Icon convertMessageType(MessageMode messageType) { - switch (messageType) { - case CONFIRMATION: - case CONFIRMATION_HTML: - return UIManager.getIcon("OptionPane.informationIcon"); - case WARNING: - case WARNING_HTML: - return UIManager.getIcon("OptionPane.warningIcon"); - default: - return null; - } - } - - protected Icon convertNotificationType(NotificationType type) { - switch (type) { - case ERROR: - case ERROR_HTML: - return UIManager.getIcon("OptionPane.errorIcon"); - case HUMANIZED: - case HUMANIZED_HTML: - return UIManager.getIcon("OptionPane.informationIcon"); - case WARNING: - case WARNING_HTML: - return UIManager.getIcon("OptionPane.warningIcon"); - default: - return null; - } - } - - @Override - public void showOptionDialog(String title, String message, MessageType messageType, final Action[] actions) { - backgroundWorker.checkUIAccess(); - - showOptionDialog(title, message, messageType, true, actions, "optionDialog"); - } - - @Override - public void showWebPage(String url, @Nullable Map params) { - try { - Desktop.getDesktop().browse(new URI(url)); - } catch (IOException | URISyntaxException e) { - throw new RuntimeException("Unable to show web page " + url, e); - } - } - - protected JComponent findTab(Integer hashCode) { - Set> set = tabs.entrySet(); - for (Map.Entry entry : set) { - Window currentWindow = entry.getValue().getCurrentWindow(); - if (hashCode.equals(getWindowHashCode(currentWindow))) - return entry.getKey(); - } - return null; - } - - /** - * Release resources right before throwing away this WindowManager instance. - */ - public void dispose() { - for (WindowOpenInfo openInfo : windowOpenMode.values()) { - if (openInfo.getOpenMode() == OpenMode.DIALOG) { - JDialog dialog = (JDialog) openInfo.getData(); - dialog.setVisible(false); - } - } - - if (isMainWindowManager) { - // Stop background tasks - WatchDog watchDog = AppBeans.get(WatchDog.NAME); - watchDog.stopTasks(); - } - - // Dispose windows - for (Window window : windowOpenMode.keySet()) { - Frame frame = window.getFrame(); - if (frame instanceof Component.Disposable) - ((Component.Disposable) frame).dispose(); - } - - tabs.clear(); - windowOpenMode.clear(); - stacks.clear(); - } - - protected static class WindowOpenInfo { - - protected Window window; - protected OpenMode openMode; - protected Object data; - protected java.awt.Component focusOwner; - - public WindowOpenInfo(Window window, OpenMode openMode) { - this.window = window; - this.openMode = openMode; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public Window getWindow() { - return window; - } - - public OpenMode getOpenMode() { - return openMode; - } - - public java.awt.Component getFocusOwner() { - return focusOwner; - } - - public void setFocusOwner(java.awt.Component focusOwner) { - this.focusOwner = focusOwner; - } - } - - public class TabCloseTask implements Runnable { - protected final WindowBreadCrumbs breadCrumbs; - - public TabCloseTask(WindowBreadCrumbs breadCrumbs) { - this.breadCrumbs = breadCrumbs; - } - - @Override - public void run() { - Window windowToClose = breadCrumbs.getCurrentWindow(); - if (windowToClose != null) { - if (!isCloseWithCloseButtonPrevented(windowToClose)) { - windowToClose.closeAndRun("close", new TabCloseTask(breadCrumbs)); - } - } - } - } - - public void addWindowData(Window window, Object windowData, OpenType openType) { - WindowOpenInfo openInfo = new WindowOpenInfo(window, openType.getOpenMode()); - openInfo.setData(windowData); - if (window instanceof Window.Wrapper) { - Window wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); - windowOpenMode.put(wrappedWindow, openInfo); - } else { - windowOpenMode.put(window, openInfo); - } - - addShortcuts(window, openType); - } - - public void checkModificationsAndCloseAll(final Runnable runIfOk, final @Nullable Runnable runIfCancel) { - boolean modified = false; - for (Window window : getOpenWindows()) { - if (!disableSavingScreenHistory) { - screenHistorySupport.saveScreenHistory(window, windowOpenMode.get(window).getOpenMode()); - } - - recursiveFramesClose = true; - try { - if (window instanceof WrappedWindow && ((WrappedWindow) window).getWrapper() != null) { - ((WrappedWindow) window).getWrapper().saveSettings(); - } else { - window.saveSettings(); - } - } finally { - recursiveFramesClose = false; - } - - if (window.getDsContext() != null && window.getDsContext().isModified()) { - modified = true; - } - } - disableSavingScreenHistory = true; - if (modified) { - showOptionDialog( - messages.getMainMessage("closeUnsaved.caption"), - messages.getMainMessage("discardChangesOnClose"), - MessageType.WARNING, - new Action[]{ - new com.haulmont.cuba.gui.components.AbstractAction( - messages.getMainMessage("closeApplication")) { - @Override - public void actionPerform(com.haulmont.cuba.gui.components.Component component) { - if (runIfOk != null) - runIfOk.run(); - } - - @Override - public String getIcon() { - return "icons/ok.png"; - } - }, - new com.haulmont.cuba.gui.components.AbstractAction( - messages.getMainMessage("actions.Cancel"), Status.PRIMARY) { - @Override - public void actionPerform(com.haulmont.cuba.gui.components.Component component) { - if (runIfCancel != null) - runIfCancel.run(); - } - - @Override - public String getIcon() { - return "icons/cancel.png"; - } - } - } - ); - } else { - runIfOk.run(); - } - } - - protected String getConfigValueIfConnected(Provider valueProvider, - String fallbackProperty, String fallbackValue) { - if (App.getInstance().getConnection().isConnected()) { - try { - return valueProvider.get(); - } catch (NoUserSessionException ignored) { - } - } - - String propertyValue = AppContext.getProperty(fallbackProperty); - if (propertyValue != null) { - return propertyValue; - } - - return fallbackValue; - } - - @Override - protected SettingsImpl getSettingsImpl(String id) { - return new AsyncSettingsImpl(id); - } - - protected class AsyncSettingsImpl extends SettingsImpl { - public AsyncSettingsImpl(String id) { - super(id); - } - - @Override - public void commit() { - if (modified && root != null) { - final String xml = Dom4j.writeDocument(root.getDocument(), true); - if (!recursiveFramesClose) { - saveSettingsAsync(xml); - } else { - getSettingsClient().setSetting(name, xml); - } - - modified = false; - } - } - - protected void saveSettingsAsync(final String xml) { - BackgroundWorker worker = AppConfig.getBackgroundWorker(); - BackgroundTaskHandler handle = worker.handle(new BackgroundTask(10) { - @Override - public Object run(TaskLifeCycle taskLifeCycle) throws Exception { - getSettingsClient().setSetting(AsyncSettingsImpl.this.name, xml); - - return null; - } - - @Override - public boolean handleException(Exception ex) { - log.warn("Unable to save user settings " + AsyncSettingsImpl.this.name, ex); - - return true; - } - - @Override - public boolean handleTimeoutException() { - log.warn("Time out while saving user settings " + AsyncSettingsImpl.this.name); - - return true; - } - }); - handle.execute(); - } - } - - @Override - protected void initDebugIds(Frame frame) { - if (App.getInstance().isTestMode()) { - ComponentsHelper.walkComponents(frame, new ComponentVisitor() { - @Override - public void visit(com.haulmont.cuba.gui.components.Component component, String name) { - if (component.getDebugId() == null) { - Frame componentFrame = null; - if (component instanceof com.haulmont.cuba.gui.components.Component.BelongToFrame) { - componentFrame = ((com.haulmont.cuba.gui.components.Component.BelongToFrame) component).getFrame(); - } - if (componentFrame == null) { - log.warn("Frame for component " + component.getClass() + " is not assigned"); - } else { - if (component instanceof DesktopAbstractComponent) { - DesktopAbstractComponent desktopComponent = (DesktopAbstractComponent) component; - desktopComponent.assignAutoDebugId(); - } - } - } - } - }); - } - } - - protected boolean isCloseWithShortcutPrevented(Window currentWindow) { - DesktopWindow desktopWindow = (DesktopWindow) ComponentsHelper.getWindowImplementation(currentWindow); - - if (desktopWindow != null) { - Window.BeforeCloseWithShortcutEvent event = new Window.BeforeCloseWithShortcutEvent(desktopWindow); - desktopWindow.fireBeforeCloseWithShortcut(event); - return event.isClosePrevented(); - } - - return false; - } - - protected boolean isCloseWithCloseButtonPrevented(Window currentWindow) { - DesktopWindow desktopWindow = (DesktopWindow) ComponentsHelper.getWindowImplementation(currentWindow); - - if (desktopWindow != null) { - Window.BeforeCloseWithCloseButtonEvent event = new Window.BeforeCloseWithCloseButtonEvent(desktopWindow); - desktopWindow.fireBeforeCloseWithCloseButton(event); - return event.isClosePrevented(); - } - - return false; - } - - protected class DesktopNotificationAction implements Action { - private Type type; - - public DesktopNotificationAction(Type type) { - this.type = type; - } - - public Type getType() { - return type; - } - - @Override - public String getId() { - return type.getId(); - } - - @Override - public String getCaption() { - return messages.getMainMessage(type.getMsgKey()); - } - - @Override - public void setCaption(String caption) { - } - - @Override - public String getDescription() { - return null; - } - - @Override - public void setDescription(String description) { - } - - @Override - public KeyCombination getShortcutCombination() { - return null; - } - - @Override - public void setShortcutCombination(KeyCombination shortcut) { - } - - @Override - public void setShortcut(String shortcut) { - } - - @Override - public String getIcon() { - ThemeConstantsManager thCM = AppBeans.get(ThemeConstantsManager.NAME); - return thCM.getThemeValue(type.getIconKey()); - } - - @Override - public void setIcon(String icon) { - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public void setEnabled(boolean enabled) { - } - - @Override - public boolean isVisible() { - return true; - } - - @Override - public void setVisible(boolean visible) { - } - - @Override - public void refreshState() { - } - - @Override - public Component.ActionOwner getOwner() { - return null; - } - - @Override - public Collection getOwners() { - return Collections.emptyList(); - } - - @Override - public void addOwner(Component.ActionOwner actionOwner) { - } - - @Override - public void removeOwner(Component.ActionOwner actionOwner) { - } - - @Override - public void actionPerform(Component component) { - } - - @Override - public void addPropertyChangeListener(PropertyChangeListener listener) { - } - - @Override - public void removePropertyChangeListener(PropertyChangeListener listener) { - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.google.common.base.Strings; +import com.haulmont.bali.util.Dom4j; +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.desktop.gui.components.DesktopAbstractComponent; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.gui.components.DesktopWindow; +import com.haulmont.cuba.desktop.sys.validation.ValidationAlertHolder; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareAction; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareWindowClosingListener; +import com.haulmont.cuba.gui.*; +import com.haulmont.cuba.gui.app.core.dev.LayoutAnalyzer; +import com.haulmont.cuba.gui.app.core.dev.LayoutTip; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.Action; +import com.haulmont.cuba.gui.components.Action.Status; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.DialogAction.Type; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.Frame.MessageMode; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.gui.config.WindowInfo; +import com.haulmont.cuba.gui.executors.*; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import com.haulmont.cuba.gui.settings.SettingsImpl; +import com.haulmont.cuba.gui.theme.ThemeConstantsManager; +import com.haulmont.cuba.security.global.NoUserSessionException; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.jdesktop.swingx.JXErrorPane; +import org.jdesktop.swingx.error.ErrorInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.inject.Provider; +import javax.swing.*; +import javax.swing.Timer; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.List; + +import static com.haulmont.cuba.gui.ComponentsHelper.preprocessHtmlMessage; +import static com.haulmont.cuba.gui.components.Component.AUTO_SIZE; +import static com.haulmont.cuba.gui.components.Component.AUTO_SIZE_PX; +import static com.haulmont.cuba.gui.components.Frame.MessageType; +import static com.haulmont.cuba.gui.components.Frame.NotificationType; +import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; + +public class DesktopWindowManager extends WindowManager { + + private static final Logger log = LoggerFactory.getLogger(DesktopWindowManager.class); + private Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + + protected static final float NEW_WINDOW_SCALE = 0.7f; + + protected JTabbedPane tabsPane; + + protected final Map tabs = new HashMap<>(); + protected final Map windowOpenMode = new LinkedHashMap<>(); + protected final Map>> stacks = new HashMap<>(); + protected final Map windows = new HashMap<>(); + protected final TopLevelFrame frame; + protected final boolean isMainWindowManager; + + protected boolean disableSavingScreenHistory; + protected ScreenHistorySupport screenHistorySupport = new ScreenHistorySupport(); + + protected boolean recursiveFramesClose = false; + + public DesktopWindowManager(TopLevelFrame frame) { + this.frame = frame; + isMainWindowManager = frame == App.getInstance().getMainFrame(); + } + + public TopLevelFrame getFrame() { + return frame; + } + + public void setTabsPane(final JTabbedPane tabsPane) { + this.tabsPane = tabsPane; + + // todo move to config + tabsPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( + KeyStroke.getKeyStroke("control W"), + "closeTab" + ); + tabsPane.getActionMap().put("closeTab", new ValidationAwareAction() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + closeTab((JComponent) tabsPane.getSelectedComponent()); + } + }); + } + + protected void closeTab(JComponent tabContent) { + if (tabContent == null) + return; + WindowBreadCrumbs breadCrumbs = tabs.get(tabContent); + // may be window already closed + if (breadCrumbs != null) { + Runnable closeTask = new TabCloseTask(breadCrumbs); + closeTask.run(); + } + } + + @Override + public Collection getOpenWindows() { + return new ArrayList<>(windowOpenMode.keySet()); + } + + @Override + public void selectWindowTab(Window window) { + if (isMainWindowManager) { + WindowOpenInfo openInfo = windowOpenMode.get(window); + if (openInfo != null) { + OpenMode openMode = openInfo.getOpenMode(); + if (openMode == OpenMode.NEW_TAB + || openMode == OpenMode.THIS_TAB) { + // show in tabsheet + JComponent layout = (JComponent) openInfo.getData(); + tabsPane.setSelectedComponent(layout); + } + } + } + } + + @Override + public void setWindowCaption(Window window, String caption, String description) { + Window desktopWindow = window; + if (window instanceof Window.Wrapper) { + desktopWindow = ((Window.Wrapper) window).getWrappedWindow(); + } + window.setCaption(caption); + + String formattedCaption = formatTabDescription(caption, description); + WindowOpenInfo openInfo = windowOpenMode.get(desktopWindow); + + if (openInfo != null) { + OpenMode openMode = openInfo.getOpenMode(); + + if (openMode != OpenMode.DIALOG) { + if (tabsPane != null) { + int selectedIndex = tabsPane.getSelectedIndex(); + if (selectedIndex != -1) { + setActiveWindowCaption(caption, description, selectedIndex); + } + } else if (!isMainWindowManager) { + setTopLevelWindowCaption(formattedCaption); + } + } else { + JDialog jDialog = (JDialog) openInfo.getData(); + if (jDialog != null) { + jDialog.setTitle(formattedCaption); + } + } + } + } + + @Nullable + public DialogWindow getLastDialogWindow() { + List openedWindows = new ArrayList<>(windowOpenMode.keySet()); + if (openedWindows.size() > 0) { + Window w = openedWindows.get(openedWindows.size() - 1); + WindowOpenInfo mode = windowOpenMode.get(w); + if (mode.getOpenMode() == OpenMode.DIALOG && mode.getData() instanceof DialogWindow) { + return (DialogWindow) mode.getData(); + } + } + return null; + } + + @Override + protected void putToWindowMap(Window window, Integer hashCode) { + if (window != null) { + windows.put(window, hashCode); + } + } + + protected Integer getWindowHashCode(Window window) { + return windows.get(window); + } + + @Override + protected Window getWindow(Integer hashCode) { + Set> set = windows.entrySet(); + for (Map.Entry entry : set) { + if (hashCode.equals(entry.getValue())) { + return entry.getKey(); + } + } + return null; + } + + @Override + protected void checkCanOpenWindow(WindowInfo windowInfo, OpenType openType, Map params) { + } + + protected boolean hasModalWindow() { + for (Map.Entry entry : windowOpenMode.entrySet()) { + if (OpenMode.DIALOG == entry.getValue().getOpenMode() + && BooleanUtils.isTrue(entry.getKey().getDialogOptions().getModal())) { + return true; + } + } + return false; + } + + @Override + protected void showWindow(Window window, String caption, OpenType openType, boolean multipleOpen) { + showWindow(window, caption, null, openType, multipleOpen); + } + + @Override + protected void showWindow(final Window window, final String caption, final String description, OpenType openType, boolean multipleOpen) { + OpenType targetOpenType = openType.copy(); + + // for backward compatibility only + copyDialogParamsToOpenType(targetOpenType); + + overrideOpenTypeParams(targetOpenType, window.getDialogOptions()); + + boolean forciblyDialog = false; + boolean addWindowData = true; + if (targetOpenType.getOpenMode() != OpenMode.DIALOG && hasModalWindow()) { + targetOpenType.setOpenMode(OpenMode.DIALOG); + forciblyDialog = true; + } + + if (targetOpenType.getOpenMode() == OpenMode.THIS_TAB && tabs.size() == 0) { + targetOpenType.setOpenMode(OpenMode.NEW_TAB); + } + + window.setCaption(caption); + window.setDescription(description); + + Object windowData; + + switch (targetOpenType.getOpenMode()) { + case NEW_TAB: + if (!isMainWindowManager) { + addWindowData = false; + showInMainWindowManager(window, caption, description, targetOpenType, multipleOpen); + windowData = null; + } else { + Integer hashCode = getWindowHashCode(window); + JComponent tab; + if (hashCode != null && !multipleOpen && (tab = findTab(hashCode)) != null) { + WindowBreadCrumbs oldBreadCrumbs = tabs.get(tab); + + final Window oldWindow = oldBreadCrumbs.getCurrentWindow(); + selectWindowTab(((Window.Wrapper) oldBreadCrumbs.getCurrentWindow()).getWrappedWindow()); + + final int finalTabPosition = getTabPosition(tab); + oldWindow.closeAndRun(MAIN_MENU_ACTION_ID, new Runnable() { + @Override + public void run() { + showWindow(window, caption, description, OpenType.NEW_TAB, false); + + Window wrappedWindow = window; + if (window instanceof Window.Wrapper) { + wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); + } + + if (finalTabPosition >= 0 && finalTabPosition < tabsPane.getComponentCount() - 1) { + moveWindowTab(wrappedWindow, finalTabPosition); + } + } + }); + return; + } else { + windowData = showWindowNewTab(window, caption, description, null); + } + } + break; + case THIS_TAB: + windowData = showWindowThisTab(window, caption, description); + break; + case DIALOG: + windowData = showWindowDialog(window, caption, description, targetOpenType, forciblyDialog); + break; + case NEW_WINDOW: + addWindowData = false; + windowData = showNewWindow(window, targetOpenType, caption); + break; + default: + throw new UnsupportedOperationException(); + } + + if (addWindowData) { + addWindowData(window, windowData, targetOpenType); + } + afterShowWindow(window); + } + + protected int getTabPosition(JComponent tab) { + int position = -1; + for (int i = 0; i < tabsPane.getTabCount(); i++) { + if (tab.equals(tabsPane.getComponentAt(i))) { + position = i; + } + } + return position; + } + + /** + * @param window Window implementation (DesktopWindow) + * @param position new tab position + */ + protected void moveWindowTab(Window window, int position) { + if (isMainWindowManager && position >= 0 && position < tabsPane.getComponentCount()) { + WindowOpenInfo openInfo = windowOpenMode.get(window); + if (openInfo != null) { + OpenMode openMode = openInfo.getOpenMode(); + if (openMode == OpenMode.NEW_TAB + || openMode == OpenMode.THIS_TAB) { + // show in tabsheet + JComponent layout = (JComponent) openInfo.getData(); + + int currentPosition = getTabPosition(layout); + + String label = tabsPane.getTitleAt(currentPosition); + Icon icon = tabsPane.getIconAt(currentPosition); + Icon iconDis = tabsPane.getDisabledIconAt(currentPosition); + String tooltip = tabsPane.getToolTipTextAt(currentPosition); + boolean enabled = tabsPane.isEnabledAt(currentPosition); + int keycode = tabsPane.getMnemonicAt(currentPosition); + int mnemonicLoc = tabsPane.getDisplayedMnemonicIndexAt(currentPosition); + Color fg = tabsPane.getForegroundAt(currentPosition); + Color bg = tabsPane.getBackgroundAt(currentPosition); + java.awt.Component tabHeaderComponent = tabsPane.getTabComponentAt(currentPosition); + + tabsPane.remove(layout); + + tabsPane.insertTab(label, icon, layout, tooltip, position); + + tabsPane.setDisabledIconAt(position, iconDis); + tabsPane.setEnabledAt(position, enabled); + tabsPane.setMnemonicAt(position, keycode); + tabsPane.setDisplayedMnemonicIndexAt(position, mnemonicLoc); + tabsPane.setForegroundAt(position, fg); + tabsPane.setBackgroundAt(position, bg); + tabsPane.setTabComponentAt(position, tabHeaderComponent); + + tabsPane.setSelectedComponent(layout); + } + } + } + } + + protected void showInMainWindowManager(Window window, String caption, String description, OpenType openType, boolean multipleOpen) { + DesktopWindowManager mainMgr = App.getInstance().getMainFrame().getWindowManager(); + windows.remove(window); + window.setWindowManager(mainMgr); + mainMgr.showWindow(window, caption, openType, multipleOpen); + } + + protected TopLevelFrame createTopLevelFrame(String caption) { + final TopLevelFrame windowFrame = new TopLevelFrame(caption); + Dimension size = frame.getSize(); + int width = Math.round(size.width * NEW_WINDOW_SCALE); + int height = Math.round(size.height * NEW_WINDOW_SCALE); + + windowFrame.setSize(width, height); + windowFrame.setLocationRelativeTo(frame); + + return windowFrame; + } + + protected void closeFrame(TopLevelFrame frame) { + frame.setVisible(false); + frame.dispose(); + frame.getWindowManager().dispose(); + App.getInstance().unregisterFrame(getFrame()); + } + + protected JComponent showNewWindow(Window window, OpenType openType, String caption) { + window.setHeight("100%"); + window.setWidth("100%"); + + TopLevelFrame windowFrame = createTopLevelFrame(caption); + windowFrame.setName(window.getId()); + + Dimension dimension = new Dimension(); + + dimension.width = 800; + if (openType.getWidth() != null) { + dimension.width = openType.getWidth().intValue(); + } + + dimension.height = 500; + if (openType.getHeight() != null) { + dimension.height = openType.getHeight().intValue(); + } + + boolean resizable = true; + if (openType.getResizable() != null) { + resizable = openType.getResizable(); + } + windowFrame.setResizable(resizable); + windowFrame.setMinimumSize(dimension); + windowFrame.pack(); + + getDialogParams().reset(); + + WindowBreadCrumbs breadCrumbs = createBreadCrumbs(); + breadCrumbs.addWindow(window); + + JComponent tabContent = createTabPanel(window, breadCrumbs); + + WindowOpenInfo openInfo = new WindowOpenInfo(window, OpenMode.NEW_WINDOW); + openInfo.setData(tabContent); + Map openInfos = new HashMap<>(); + if (window instanceof Window.Wrapper) { + Window wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); + openInfos.put(wrappedWindow, openInfo); + } else { + openInfos.put(window, openInfo); + } + + windowFrame.getWindowManager().attachTab(breadCrumbs, + new Stack<>(), + window, + getWindowHashCode(window), + tabContent, openInfos); + + App.getInstance().registerFrame(windowFrame); + + windowFrame.setVisible(true); + return DesktopComponentsHelper.getComposition(window); + } + + protected void addShortcuts(Window window, OpenType openType) { + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + + String closeShortcut = clientConfig.getCloseShortcut(); + window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("closeWindowShortcutAction", closeShortcut) { + @Override + public void actionPerform(Component component) { + if (openType.getOpenMode() != OpenMode.DIALOG + || BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) { + if (!isCloseWithShortcutPrevented(window)) { + window.close("close"); + } + } + } + }); + + String previousTabShortcut = clientConfig.getPreviousTabShortcut(); + window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("onPreviousTab", previousTabShortcut) { + @Override + public void actionPerform(Component component) { + if (window.getWindowManager() != DesktopWindowManager.this) { + // detached tab + return; + } + + if (isMainWindowManager && getLastDialogWindow() == null && tabsPane.getTabCount() > 1) { + int selectedIndex = getSelectedTabIndex(); + + int newIndex = (selectedIndex + tabsPane.getTabCount() - 1) % tabsPane.getTabCount(); + java.awt.Component newTab = tabsPane.getComponentAt(newIndex); + tabsPane.setSelectedComponent(newTab); + + moveFocus(newTab); + } + } + }); + + String nextTabShortcut = clientConfig.getNextTabShortcut(); + window.addAction(new com.haulmont.cuba.gui.components.AbstractAction("onNextTab", nextTabShortcut) { + @Override + public void actionPerform(Component component) { + if (window.getWindowManager() != DesktopWindowManager.this) { + // detached tab + return; + } + + if (isMainWindowManager && getLastDialogWindow() == null && tabsPane.getTabCount() > 1) { + int selectedIndex = getSelectedTabIndex(); + + int newIndex = (selectedIndex + 1) % tabsPane.getTabCount(); + java.awt.Component newTab = tabsPane.getComponentAt(newIndex); + tabsPane.setSelectedComponent(newTab); + + moveFocus(newTab); + } + } + }); + } + + protected void moveFocus(java.awt.Component tab) { + Window window = tabs.get(tab).getCurrentWindow(); + + if (window != null) { + String focusComponentId = window.getFocusComponent(); + + boolean focused = false; + if (focusComponentId != null) { + com.haulmont.cuba.gui.components.Component focusComponent = window.getComponent(focusComponentId); + if (focusComponent != null) { + if (focusComponent.isEnabled() && focusComponent.isVisible()) { + focusComponent.requestFocus(); + focused = true; + } + } + } + + if (!focused && window instanceof Window.Wrapper) { + Window.Wrapper wrapper = (Window.Wrapper) window; + focused = ((DesktopWindow) wrapper.getWrappedWindow()).findAndFocusChildComponent(); + if (!focused) { + tabsPane.requestFocus(); + } + } + } + } + + protected int getSelectedTabIndex() { + java.awt.Component selectedComponent = tabsPane.getSelectedComponent(); + for (int i = 0; i < tabsPane.getTabCount(); i++) { + if (selectedComponent == tabsPane.getComponentAt(i)) { + return i; + } + } + return -1; + } + + protected JDialog showWindowDialog(final Window window, String caption, String description, OpenType openType, boolean forciblyDialog) { + final DialogWindow dialog = new DialogWindow(frame, caption); + dialog.setName(window.getId()); + dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + JComponent jComponent = DesktopComponentsHelper.getComposition(window); + dialog.add(jComponent); + + dialog.addWindowListener(new ValidationAwareWindowClosingListener() { + @Override + public void windowClosingAfterValidation(WindowEvent e) { + if (BooleanUtils.isNotFalse(window.getDialogOptions().getCloseable())) { + if (!isCloseWithCloseButtonPrevented(window)) { + if (window.close("close")) { + dialog.dispose(); + } + } + } + } + }); + + Dimension dim = new Dimension(); + if (forciblyDialog) { + // todo move it to desktop application preferences + dim.width = 800; + dim.height = 500; + + dialog.setResizable(BooleanUtils.isNotFalse(openType.getResizable())); + if (!dialog.isResizable()) { + dialog.setFixedHeight(dim.height); + dialog.setFixedWidth(dim.width); + } + + window.setHeight("100%"); + } else { + dialog.setResizable(BooleanUtils.isTrue(openType.getResizable())); + if (openType.getWidth() == null) { + dim.width = 600; + if (!dialog.isResizable()) { + dialog.setFixedWidth(dim.width); + } + } else if (openType.getWidth() == DialogParams.AUTO_SIZE_PX) { + window.setWidth(AUTO_SIZE); + } else { + if (openType.getWidthUnit() != null && openType.getWidthUnit() != SizeUnit.PIXELS) { + throw new UnsupportedOperationException("Dialog size can be set only in pixels"); + } + dim.width = openType.getWidth().intValue(); + if (!dialog.isResizable()) { + dialog.setFixedWidth(dim.width); + } + } + + if (openType.getHeight() != null && openType.getHeight() != DialogParams.AUTO_SIZE_PX) { + if (openType.getHeightUnit() != null && openType.getHeightUnit() != SizeUnit.PIXELS) { + throw new UnsupportedOperationException("Dialog size can be set only in pixels"); + } + dim.height = openType.getHeight().intValue(); + if (!dialog.isResizable()) { + dialog.setFixedHeight(dim.height); + } + window.setHeight("100%"); + } else { + window.setHeight(AUTO_SIZE); + } + } + + getDialogParams().reset(); + + dialog.setMinimumSize(dim); + dialog.pack(); + + if (openType.getPositionY() == null + && openType.getPositionX() == null) { + dialog.setLocationRelativeTo(frame); + } else { + dialog.setLocation( + openType.getPositionX() != null ? openType.getPositionX() : 0, + openType.getPositionY() != null ? openType.getPositionY() : 0 + ); + } + + boolean modal = true; + if (!hasModalWindow() && openType.getModal() != null) { + modal = openType.getModal(); + } + + if (modal) { + DialogWindow lastDialogWindow = getLastDialogWindow(); + if (lastDialogWindow == null) + frame.deactivate(null); + else + lastDialogWindow.disableWindow(null); + + dialog.setSoftModal(true); + } + + dialog.setVisible(true); + + JPopupMenu popupMenu = createWindowPopupMenu(window); + if (popupMenu.getComponentCount() > 0) { + jComponent.setComponentPopupMenu(popupMenu); + } + + return dialog; + } + + protected JComponent showWindowThisTab(Window window, String caption, String description) { + getDialogParams().reset(); + + window.setWidth("100%"); + window.setHeight("100%"); + + JComponent layout; + if (isMainWindowManager) { + layout = (JComponent) tabsPane.getSelectedComponent(); + } else { + layout = (JComponent) frame.getContentPane().getComponent(0); + } + WindowBreadCrumbs breadCrumbs = tabs.get(layout); + if (breadCrumbs == null) + throw new IllegalStateException("BreadCrumbs not found"); + + Window currentWindow = breadCrumbs.getCurrentWindow(); + Window currentWindowFrame = (Window) currentWindow.getFrame(); + windowOpenMode.get(currentWindowFrame).setFocusOwner(frame.getFocusOwner()); + + Set> set = windows.entrySet(); + boolean pushed = false; + for (Map.Entry entry : set) { + if (entry.getKey().equals(currentWindow)) { + windows.remove(currentWindow); + stacks.get(breadCrumbs).push(entry); + pushed = true; + break; + } + } + if (!pushed) { + stacks.get(breadCrumbs).push(new AbstractMap.SimpleEntry<>(currentWindow, null)); + } + + windows.remove(window); + layout.remove(DesktopComponentsHelper.getComposition(currentWindow)); + + JComponent component = DesktopComponentsHelper.getComposition(window); + layout.add(component); + + breadCrumbs.addWindow(window); + if (isMainWindowManager) { + setActiveWindowCaption(caption, description, tabsPane.getSelectedIndex()); + } else { + setTopLevelWindowCaption(caption); + component.revalidate(); + component.repaint(); + } + + return layout; + } + + protected void setActiveWindowCaption(String caption, String description, int tabIndex) { + ButtonTabComponent tabComponent = (ButtonTabComponent) tabsPane.getTabComponentAt(tabIndex); + String formattedCaption = formatTabCaption(caption, description); + tabComponent.setCaption(formattedCaption); + } + + protected void setTopLevelWindowCaption(String caption) { + frame.setTitle(caption); + } + + protected WindowBreadCrumbs createBreadCrumbs() { + final WindowBreadCrumbs breadCrumbs = new WindowBreadCrumbs(); + breadCrumbs.addListener( + new WindowBreadCrumbs.Listener() { + @Override + public void windowClick(final Window window) { + Runnable op = new Runnable() { + @Override + public void run() { + Window currentWindow = breadCrumbs.getCurrentWindow(); + if (currentWindow != null && window != currentWindow) { + if (!isCloseWithCloseButtonPrevented(currentWindow)) { + currentWindow.closeAndRun("close", this); + } + } + } + }; + op.run(); + } + } + ); + return breadCrumbs; + } + + protected JComponent showWindowNewTab(Window window, String caption, String description, Integer tabPosition) { + getDialogParams().reset(); + + window.setWidth("100%"); + window.setHeight("100%"); + + final WindowBreadCrumbs breadCrumbs = createBreadCrumbs(); + stacks.put(breadCrumbs, new Stack<>()); + + breadCrumbs.addWindow(window); + JComponent tabContent = createNewTab(window, caption, description, breadCrumbs, tabPosition); + tabs.put(tabContent, breadCrumbs); + return tabContent; + } + + protected JPanel createTabPanel(Window window, WindowBreadCrumbs breadCrumbs) { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(breadCrumbs, BorderLayout.NORTH); + JComponent composition = DesktopComponentsHelper.getComposition(window); + panel.add(composition, BorderLayout.CENTER); + return panel; + } + + protected JComponent createNewTab(Window window, String caption, String description, WindowBreadCrumbs breadCrumbs, Integer tabPosition) { + JPanel panel = createTabPanel(window, breadCrumbs); + int idx; + if (tabPosition != null) { + idx = tabPosition; + } else { + idx = tabsPane.getTabCount(); + } + tabsPane.insertTab(formatTabCaption(caption, description), null, panel, null, idx); + + ButtonTabComponent tabComponent = new ButtonTabComponent( + tabsPane, true, true, + new ButtonTabComponent.CloseListener() { + @Override + public void onTabClose(final int tabIndex) { + ValidationAlertHolder.runIfValid(new Runnable() { + @Override + public void run() { + JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); + closeTab(tabContent); + } + }); + } + }, + new ButtonTabComponent.DetachListener() { + @Override + public void onDetach(final int tabIndex) { + ValidationAlertHolder.runIfValid(new Runnable() { + @Override + public void run() { + detachTab(tabIndex); + } + }); + } + } + ); + tabsPane.setTabComponentAt(idx, tabComponent); + tabsPane.setSelectedIndex(idx); + + initTabContextMenu(tabComponent); + + return panel; + } + + protected void initTabContextMenu(JComponent tabComponent) { + tabComponent.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + dispatchToParent(e); + if (e.isPopupTrigger()) { + showTabPopup(e); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + dispatchToParent(e); + if (e.isPopupTrigger()) { + showTabPopup(e); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + dispatchToParent(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + dispatchToParent(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + dispatchToParent(e); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + dispatchToParent(e); + } + + @Override + public void mouseExited(MouseEvent e) { + dispatchToParent(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + dispatchToParent(e); + } + + public void dispatchToParent(MouseEvent e) { + tabsPane.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, tabsPane)); + } + }); + } + + public void showTabPopup(MouseEvent e) { + JComponent tabHeaderComponent = (JComponent) e.getComponent(); + int tabIndex = getTabIndex(tabHeaderComponent); + JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); + WindowBreadCrumbs windowBreadCrumbs = tabs.get(tabContent); + + Window window = windowBreadCrumbs.getCurrentWindow(); + + JPopupMenu popupMenu = createWindowPopupMenu(window); + if (popupMenu.getComponentCount() > 0) { + popupMenu.show(tabHeaderComponent, e.getX(), e.getY()); + } + } + + protected int getTabIndex(java.awt.Component tabHeaderComponent) { + for (int i = 0; i < tabsPane.getTabCount(); i++) { + if (tabsPane.getTabComponentAt(i) == tabHeaderComponent) + return i; + } + return -1; + } + + protected JPopupMenu createWindowPopupMenu(final Window window) { + JPopupMenu popupMenu = new JPopupMenu(); + + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + + if (clientConfig.getManualScreenSettingsSaving()) { + JMenuItem saveSettingsItem = new JMenuItem(messages.getMainMessage("actions.saveSettings")); + saveSettingsItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + window.saveSettings(); + } + }); + popupMenu.add(saveSettingsItem); + + JMenuItem restoreToDefaultsItem = new JMenuItem(messages.getMainMessage("actions.restoreToDefaults")); + restoreToDefaultsItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + window.deleteSettings(); + } + }); + popupMenu.add(restoreToDefaultsItem); + } + if (clientConfig.getLayoutAnalyzerEnabled()) { + JMenuItem analyzeLayoutItem = new JMenuItem(messages.getMainMessage("actions.analyzeLayout")); + analyzeLayoutItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + LayoutAnalyzer analyzer = new LayoutAnalyzer(); + List tipsList = analyzer.analyze(window); + + if (tipsList.isEmpty()) { + showNotification("No layout problems found", NotificationType.HUMANIZED); + } else { + window.openWindow("layoutAnalyzer", OpenType.DIALOG, ParamsMap.of("tipsList", tipsList)); + } + } + }); + popupMenu.add(analyzeLayoutItem); + } + return popupMenu; + } + + protected void detachTab(int tabIndex) { + //Create new top-level frame, put this tab to it with breadcrumbs. + // remove tab data from this window manager + JComponent tabContent = (JComponent) tabsPane.getComponentAt(tabIndex); + WindowBreadCrumbs breadCrumbs = tabs.get(tabContent); + Window window = breadCrumbs.getCurrentWindow(); + + if (window == null) { + throw new IllegalArgumentException("window is null"); + } + + //WindowOpenMode map + Map detachOpenModes = new HashMap<>(); + detachOpenModes.put((Window) window.getFrame(), windowOpenMode.get(window.getFrame())); + windowOpenMode.remove(window.getFrame()); + Stack> stack = stacks.get(breadCrumbs); + for (Map.Entry entry : stack) { + WindowOpenInfo openInfo = windowOpenMode.get(entry.getKey().getFrame()); + detachOpenModes.put((Window) entry.getKey().getFrame(), openInfo); + windowOpenMode.remove(entry.getKey().getFrame()); + } + + tabs.remove(tabContent); + + Integer hashCode = windows.remove(window); + tabsPane.remove(tabIndex); + stacks.remove(breadCrumbs); + + final TopLevelFrame windowFrame = createTopLevelFrame(window.getCaption()); + App.getInstance().registerFrame(windowFrame); + windowFrame.setVisible(true); + windowFrame.getWindowManager().attachTab(breadCrumbs, stack, window, hashCode, tabContent, detachOpenModes); + } + + public void attachTab(WindowBreadCrumbs breadCrumbs, Stack> stack, + Window window, Integer hashCode, final JComponent tabContent, + Map openInfos) { + frame.add(tabContent); + frame.addWindowListener(new ValidationAwareWindowClosingListener() { + @Override + public void windowClosingAfterValidation(WindowEvent e) { + closeTab(tabContent); + } + }); + tabs.put(tabContent, breadCrumbs); + windowOpenMode.putAll(openInfos); + stacks.put(breadCrumbs, stack); + for (Map.Entry entry : stack) { + entry.getKey().setWindowManager(this); + } + window.setWindowManager(this); + if (hashCode != null) { + windows.put(window, hashCode); + } + + JPopupMenu popupMenu = createWindowPopupMenu(window); + if (popupMenu.getComponentCount() > 0) { + frame.getRootPane().setComponentPopupMenu(popupMenu); + } + } + + protected String formatTabCaption(String caption, String description) { + String s = formatTabDescription(caption, description); + int maxLength = configuration.getConfig(DesktopConfig.class).getMainTabCaptionLength(); + if (s.length() > maxLength) { + return s.substring(0, maxLength) + "..."; + } else { + return s; + } + } + + protected String formatTabDescription(final String caption, final String description) { + if (!StringUtils.isEmpty(description)) { + return String.format("%s: %s", caption, description); + } else { + return caption; + } + } + + @Override + protected void showFrame(Component parent, Frame frame) { + // the same as web window manager does + if (parent instanceof Component.Container) { + Component.Container container = (Component.Container) parent; + for (Component c : container.getComponents()) { + if (c instanceof Component.Disposable) { + Component.Disposable disposable = + (Component.Disposable) c; + if (!disposable.isDisposed()) { + disposable.dispose(); + } + } + container.remove(c); + } + container.add(frame); + } else { + throw new IllegalStateException( + "Parent component must be com.haulmont.cuba.gui.components.Component.Container" + ); + } + } + + @Override + public void close(Window window) { + if (window instanceof Window.Wrapper) { + window = ((Window.Wrapper) window).getWrappedWindow(); + } + + final WindowOpenInfo openInfo = windowOpenMode.get(window); + if (openInfo == null) { + log.warn("Problem closing window " + window + " : WindowOpenMode not found"); + return; + } + disableSavingScreenHistory = false; + closeWindow(window, openInfo); + windowOpenMode.remove(window); + windows.remove(openInfo.getWindow()); + } + + protected void closeWindow(Window window, WindowOpenInfo openInfo) { + if (!disableSavingScreenHistory) { + screenHistorySupport.saveScreenHistory(window, openInfo.getOpenMode()); + } + + switch (openInfo.getOpenMode()) { + case DIALOG: { + JDialog dialog = (JDialog) openInfo.getData(); + dialog.setVisible(false); + dialog.dispose(); + cleanupAfterModalDialogClosed(window); + + fireListeners(window, tabs.size() != 0); + break; + } + case NEW_TAB: + case NEW_WINDOW: { + JComponent layout = (JComponent) openInfo.getData(); + layout.remove(DesktopComponentsHelper.getComposition(window)); + if (isMainWindowManager) { + tabsPane.remove(layout); + } + + WindowBreadCrumbs windowBreadCrumbs = tabs.get(layout); + if (windowBreadCrumbs != null) { + windowBreadCrumbs.clearListeners(); + windowBreadCrumbs.removeWindow(); + } + + tabs.remove(layout); + stacks.remove(windowBreadCrumbs); + + fireListeners(window, tabs.size() != 0); + if (!isMainWindowManager) { + closeFrame(getFrame()); + } + break; + } + case THIS_TAB: { + JComponent layout = (JComponent) openInfo.getData(); + + final WindowBreadCrumbs breadCrumbs = tabs.get(layout); + if (breadCrumbs == null) + throw new IllegalStateException("Unable to close screen: breadCrumbs not found"); + + breadCrumbs.removeWindow(); + Window currentWindow = breadCrumbs.getCurrentWindow(); + if (!stacks.get(breadCrumbs).empty()) { + Map.Entry entry = stacks.get(breadCrumbs).pop(); + putToWindowMap(entry.getKey(), entry.getValue()); + } + JComponent component = DesktopComponentsHelper.getComposition(currentWindow); + Window currentWindowFrame = (Window) currentWindow.getFrame(); + final java.awt.Component focusedCmp = windowOpenMode.get(currentWindowFrame).getFocusOwner(); + if (focusedCmp != null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + focusedCmp.requestFocus(); + } + }); + } + layout.remove(DesktopComponentsHelper.getComposition(window)); + + if (App.getInstance().getConnection().isConnected()) { + layout.add(component); + if (isMainWindowManager) { + // If user clicked on close button maybe selectedIndex != tabsPane.getSelectedIndex() + // Refs #1117 + int selectedIndex = 0; + while ((selectedIndex < tabs.size()) && + (tabsPane.getComponentAt(selectedIndex) != layout)) { + selectedIndex++; + } + if (selectedIndex == tabs.size()) { + selectedIndex = tabsPane.getSelectedIndex(); + } + + setActiveWindowCaption(currentWindow.getCaption(), currentWindow.getDescription(), selectedIndex); + } else { + setTopLevelWindowCaption(currentWindow.getCaption()); + component.revalidate(); + component.repaint(); + } + } + + fireListeners(window, tabs.size() != 0); + break; + } + + default: + throw new UnsupportedOperationException(); + } + } + + protected void cleanupAfterModalDialogClosed(@Nullable Window closingWindow) { + WindowOpenInfo previous = null; + for (Iterator it = windowOpenMode.keySet().iterator(); it.hasNext(); ) { + Window w = it.next(); + // Check if there is a modal window opened before the current + WindowOpenInfo mode = windowOpenMode.get(w); + if (w != closingWindow && mode.getOpenMode() == OpenMode.DIALOG) { + previous = mode; + } + // If there are windows opened after the current, close them + if (w == closingWindow && it.hasNext()) { + close(it.next()); + break; + } + } + if (previous == null) { + frame.activate(); + } else if (previous.getData() instanceof DialogWindow) { + ((DialogWindow) previous.getData()).enableWindow(); + } else if (previous.getData() instanceof JDialog) { + ((JDialog) previous.getData()).requestFocus(); + } + } + + @Override + public void showNotification(String caption) { + showNotification(caption, null, NotificationType.HUMANIZED); + } + + @Override + public void showNotification(String caption, NotificationType type) { + showNotification(caption, null, type); + } + + @Override + public void showNotification(String caption, String description, NotificationType type) { + backgroundWorker.checkUIAccess(); + + DesktopConfig config = configuration.getConfig(DesktopConfig.class); + + if (!NotificationType.isHTML(type)) { + caption = preprocessHtmlMessage(escapeHtml(Strings.nullToEmpty(caption))); + description = preprocessHtmlMessage(escapeHtml(Strings.nullToEmpty(description))); + } + + String text = preparePopupText(caption, description); + if (config.isDialogNotificationsEnabled() + && type != NotificationType.TRAY + && type != NotificationType.TRAY_HTML) { + showNotificationDialog(text, type); + } else { + showNotificationPopup(text, type); + } + } + + protected void showNotificationDialog(String text, NotificationType type) { + String title = messages.getMainMessage("notification.title." + type); + + Icon icon = convertNotificationType(type); + + showOptionDialog(title, text, null, icon, false, new Action[]{ + new DesktopNotificationAction(Type.CLOSE) + }, "notificationDialog"); + } + + protected void showNotificationPopup(String popupText, NotificationType type) { + JPanel panel = new JPanel(new MigLayout("flowy")); + panel.setBorder(BorderFactory.createLineBorder(Color.gray)); + + switch (type) { + case WARNING: + case WARNING_HTML: + panel.setBackground(Color.yellow); + break; + case ERROR: + case ERROR_HTML: + panel.setBackground(Color.orange); + break; + default: + panel.setBackground(Color.cyan); + } + + JLabel label = new JLabel(popupText); + panel.add(label); + + Dimension labelSize = DesktopComponentsHelper.measureHtmlText(popupText); + + int x = frame.getX() + frame.getWidth() - (50 + labelSize.getSize().width); + int y = frame.getY() + frame.getHeight() - (50 + labelSize.getSize().height); + + PopupFactory factory = PopupFactory.getSharedInstance(); + final Popup popup = factory.getPopup(frame, panel, x, y); + popup.show(); + + panel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + popup.hide(); + } + }); + + PointerInfo pointerInfo = MouseInfo.getPointerInfo(); + if (pointerInfo != null) { + final Point location = pointerInfo.getLocation(); + final Timer timer = new Timer(3000, null); + timer.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + PointerInfo currentPointer = MouseInfo.getPointerInfo(); + if (currentPointer == null) { + timer.stop(); + } else if (!currentPointer.getLocation().equals(location)) { + popup.hide(); + timer.stop(); + } + } + }); + timer.start(); + } + } + + protected String preparePopupText(String caption, String description) { + if (StringUtils.isNotBlank(description)) { + caption = String.format("%s
%s", caption, description); + } + StringBuilder sb = new StringBuilder(""); + String[] strings = caption.split("(
)|(
)"); + for (String string : strings) { + sb.append(string).append("
"); + } + sb.append(""); + return sb.toString(); + } + + @Override + public void showMessageDialog(final String title, final String message, MessageType messageType) { + showOptionDialog(title, message, messageType, false, new Action[]{ + new DialogAction(Type.OK) + }, "messageDialog"); + } + + protected JPanel createButtonsPanel(Action[] actions, final DialogWindow dialog) { + JPanel buttonsPanel = new JPanel(); + + boolean hasPrimaryAction = false; + for (final Action action : actions) { + JButton button = new JButton(action.getCaption()); + String icon = action.getIcon(); + + if (icon != null) { + button.setIcon(App.getInstance().getResources().getIcon(icon)); + } + + final DialogActionHandler dialogActionHandler = new DialogActionHandler(dialog, action); + button.addActionListener(dialogActionHandler); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JButton b = (JButton) e.getSource(); + userActionsLog.trace("Button (name = {}, text = {}) was clicked in dialog", b.getName(), b.getText()); + } + }); + if (actions.length == 1) { + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + dialogActionHandler.onClose(); + } + }); + } + + button.setPreferredSize(new Dimension(button.getPreferredSize().width, DesktopComponentsHelper.BUTTON_HEIGHT)); + button.setMaximumSize(new Dimension(Integer.MAX_VALUE, DesktopComponentsHelper.BUTTON_HEIGHT)); + + if (action instanceof AbstractAction && ((AbstractAction) action).isPrimary()) { + hasPrimaryAction = true; + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + button.requestFocus(); + } + }); + } + + buttonsPanel.add(button); + } + + if (!hasPrimaryAction && actions.length > 0) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + buttonsPanel.getComponent(0).requestFocus(); + } + }); + } + + return buttonsPanel; + } + + public WindowBreadCrumbs getBreadCrumbs(JComponent container) { + return tabs.get(container); + } + + protected void assignDialogShortcuts(final JDialog dialog, JPanel panel, final Action[] actions) { + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + + InputMap inputMap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + ActionMap actionMap = panel.getActionMap(); + + String commitShortcut = getConfigValueIfConnected(clientConfig::getCommitShortcut, "cuba.gui.commitShortcut", "CTRL-ENTER"); + + KeyCombination okCombination = KeyCombination.create(commitShortcut); + KeyStroke okKeyStroke = DesktopComponentsHelper.convertKeyCombination(okCombination); + + inputMap.put(okKeyStroke, "okAction"); + actionMap.put("okAction", new javax.swing.AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + for (Action action : actions) { + if (action instanceof DialogAction) { + switch (((DialogAction) action).getType()) { + case OK: + case YES: + action.actionPerform(null); + dialog.setVisible(false); + cleanupAfterModalDialogClosed(null); + return; + } + } + } + } + }); + + String closeShortcut = getConfigValueIfConnected(clientConfig::getCloseShortcut, "cuba.gui.closeShortcut", "ESCAPE"); + + KeyCombination closeCombination = KeyCombination.create(closeShortcut); + KeyStroke closeKeyStroke = DesktopComponentsHelper.convertKeyCombination(closeCombination); + + inputMap.put(closeKeyStroke, "closeAction"); + actionMap.put("closeAction", new javax.swing.AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (actions.length == 1) { + actions[0].actionPerform(null); + dialog.setVisible(false); + cleanupAfterModalDialogClosed(null); + } else { + for (Action action : actions) { + if (action instanceof DialogAction) { + switch (((DialogAction) action).getType()) { + case CANCEL: + case CLOSE: + case NO: + action.actionPerform(null); + dialog.setVisible(false); + cleanupAfterModalDialogClosed(null); + return; + } + } + } + } + } + }); + } + + protected void showOptionDialog(final String title, final String message, MessageType messageType, + boolean alwaysModal, final Action[] actions, String debugName) { + Icon icon = convertMessageType(messageType.getMessageMode()); + + String msg = message; + if (!MessageType.isHTML(messageType)) { + msg = StringEscapeUtils.escapeHtml(msg); + msg = ComponentsHelper.preprocessHtmlMessage("" + msg + ""); + } else { + msg = "" + msg + ""; + } + + showOptionDialog(title, msg, messageType, icon, alwaysModal, actions, debugName); + } + + protected void showOptionDialog(final String title, final String message, @Nullable MessageType messageType, + final Icon icon, boolean alwaysModal, final Action[] actions, String debugName) { + final DialogWindow dialog = new DialogWindow(frame, title); + + if (App.getInstance().isTestMode()) { + dialog.setName(debugName); + } + dialog.setModal(false); + + if (actions.length > 1) { + dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + } + + int width = 500; + SizeUnit unit = null; + DialogParams dialogParams = getDialogParams(); + if (messageType != null && messageType.getWidth() != null) { + width = messageType.getWidth().intValue(); + unit = messageType.getWidthUnit(); + } else if (dialogParams.getWidth() != null) { + width = dialogParams.getWidth().intValue(); + unit = dialogParams.getWidthUnit(); + } + + LC lc = new LC(); + lc.insets("10"); + + MigLayout layout = new MigLayout(lc); + final JPanel panel = new JPanel(layout); + if (icon != null) { + JLabel iconLabel = new JLabel(icon); + panel.add(iconLabel, "aligny top"); + } + + JLabel msgLabel = new JLabel(message); + + if (width != AUTO_SIZE_PX) { + panel.add(msgLabel, "width 100%, wrap, growy 0"); + } else { + panel.add(msgLabel, "wrap"); + } + + if (icon != null) { + panel.add(new JLabel(" ")); + } + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + dialog.requestFocus(); + } + }); + + final JPanel buttonsPanel = createButtonsPanel(actions, dialog); + panel.add(buttonsPanel, "alignx right"); + + if (width != AUTO_SIZE_PX) { + if (unit != null && unit != SizeUnit.PIXELS) { + throw new UnsupportedOperationException("Dialog size can be set only in pixels"); + } + dialog.setLayout(new MigLayout(new LC().insets("0").width(width + "px"))); + dialog.setFixedWidth(width); + dialog.add(panel, "width 100%, growy 0"); + } else { + dialog.add(panel); + } + + assignDialogShortcuts(dialog, panel, actions); + + dialog.pack(); + dialog.setResizable(false); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + panel.revalidate(); + panel.repaint(); + + java.awt.Container container = panel.getTopLevelAncestor(); + if (container instanceof JDialog) { + JDialog dialog = (JDialog) container; + dialog.pack(); + } + } + }); + dialog.setLocationRelativeTo(frame); + + boolean modal = true; + if (!alwaysModal) { + if (!hasModalWindow()) { + if (messageType != null && messageType.getModal() != null) { + modal = messageType.getModal(); + } else if (dialogParams.getModal() != null) { + modal = dialogParams.getModal(); + } + } + } else { + if (messageType != null && messageType.getModal() != null) { + log.warn("MessageType.modal is not supported for showOptionDialog"); + } + } + + if (modal) { + DialogWindow lastDialogWindow = getLastDialogWindow(); + if (lastDialogWindow == null) { + frame.deactivate(null); + } else { + lastDialogWindow.disableWindow(null); + } + } + + dialog.setVisible(true); + } + + @Override + public void showExceptionDialog(Throwable throwable) { + showExceptionDialog(throwable, null, null); + } + + @Override + public void showExceptionDialog(Throwable throwable, @Nullable String caption, @Nullable String message) { + Preconditions.checkNotNullArgument(throwable); + + JXErrorPane errorPane = new JXErrorPaneExt(); + errorPane.setErrorInfo(createErrorInfo(caption, message, throwable)); + + final TopLevelFrame mainFrame = App.getInstance().getMainFrame(); + + JDialog dialog = JXErrorPane.createDialog(mainFrame, errorPane); + dialog.setMinimumSize(new Dimension(600, (int) dialog.getMinimumSize().getHeight())); + + final DialogWindow lastDialogWindow = getLastDialogWindow(); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + if (lastDialogWindow != null) { + lastDialogWindow.enableWindow(); + } else { + mainFrame.activate(); + } + } + }); + dialog.setModal(false); + + if (lastDialogWindow != null) { + lastDialogWindow.disableWindow(null); + } else { + mainFrame.deactivate(null); + } + + dialog.setVisible(true); + } + + protected ErrorInfo createErrorInfo(String caption, String message, Throwable exception) { + UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + Security security = AppBeans.get(Security.NAME); + if (userSessionSource.getUserSession() == null + || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { + + String dialogCaption = StringUtils.isNotEmpty(caption) ? caption : getMessage("errorPane.title"); + String dialogMessage = StringUtils.isNotEmpty(message) ? message : getMessage("exceptionDialog.contactAdmin"); + + return new ErrorInfo(dialogCaption, dialogMessage,null, null, null, null, null); + } + + Throwable rootCause = ExceptionUtils.getRootCause(exception); + if (rootCause == null) + rootCause = exception; + + StringBuilder msg = new StringBuilder(); + if (rootCause instanceof RemoteException) { + RemoteException re = (RemoteException) rootCause; + if (!re.getCauses().isEmpty()) { + RemoteException.Cause cause = re.getCauses().get(re.getCauses().size() - 1); + if (cause.getThrowable() != null) + rootCause = cause.getThrowable(); + else { + // root cause is not supported by client + String className = cause.getClassName(); + if (className != null && className.indexOf('.') > 0) { + className = className.substring(className.lastIndexOf('.') + 1); + } + msg.append(className).append(": ").append(cause.getMessage()); + } + } + } + + if (msg.length() == 0) { + msg.append(rootCause.getClass().getSimpleName()); + if (!StringUtils.isBlank(rootCause.getMessage())) + msg.append(": ").append(rootCause.getMessage()); + + if (rootCause instanceof DevelopmentException) { + Map params = new LinkedHashMap<>(); + if (rootCause instanceof GuiDevelopmentException) { + GuiDevelopmentException guiDevException = (GuiDevelopmentException) rootCause; + if (guiDevException.getFrameId() != null) { + params.put("Frame ID", guiDevException.getFrameId()); + try { + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + params.put("XML descriptor", + windowConfig.getWindowInfo(guiDevException.getFrameId()).getTemplate()); + } catch (Exception e) { + params.put("XML descriptor", "not found for " + guiDevException.getFrameId()); + } + } + } + params.putAll(((DevelopmentException) rootCause).getParams()); + + if (!params.isEmpty()) { + msg.append("\n\n"); + for (Map.Entry entry : params.entrySet()) { + msg.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } + } + } + + return new ErrorInfo(getMessage("errorPane.title"), msg.toString(), + null, null, rootCause, null, null); + } + + protected String getMessage(String key) { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage(key, App.getInstance().getLocale()); + } + + /** + * Handler for OptionDialog, MessageDialog, NotificationPopup buttons, + * also used for handling dialog close event if dialog has only one action. + */ + protected class DialogActionHandler extends WindowAdapter implements ActionListener { + + protected Action action; + + protected final DialogWindow dialog; + + protected final java.awt.Component lastFocusedComponent; + + public DialogActionHandler(DialogWindow dialog, Action action) { + this.action = action; + this.dialog = dialog; + this.dialog.addWindowListener(this); + + DialogWindow lastDialogWindow = getLastDialogWindow(); + if (lastDialogWindow != null) { + lastFocusedComponent = lastDialogWindow.getFocusOwner(); + } else { + lastFocusedComponent = frame.getFocusOwner(); + } + } + + public void onClose() { + if (lastFocusedComponent != null + && lastFocusedComponent.isEnabled() + && lastFocusedComponent.isVisible() + && !(lastFocusedComponent instanceof JDialog) + && !(lastFocusedComponent instanceof JFrame)) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + lastFocusedComponent.requestFocus(); + } + }); + } + + action.actionPerform(null); + dialog.setVisible(false); + cleanupAfterModalDialogClosed(null); + dialog.dispose(); + } + + @Override + public void actionPerformed(ActionEvent e) { + onClose(); + } + + @Override + public void windowClosed(WindowEvent e) { + action = null; + } + } + + protected Icon convertMessageType(MessageMode messageType) { + switch (messageType) { + case CONFIRMATION: + case CONFIRMATION_HTML: + return UIManager.getIcon("OptionPane.informationIcon"); + case WARNING: + case WARNING_HTML: + return UIManager.getIcon("OptionPane.warningIcon"); + default: + return null; + } + } + + protected Icon convertNotificationType(NotificationType type) { + switch (type) { + case ERROR: + case ERROR_HTML: + return UIManager.getIcon("OptionPane.errorIcon"); + case HUMANIZED: + case HUMANIZED_HTML: + return UIManager.getIcon("OptionPane.informationIcon"); + case WARNING: + case WARNING_HTML: + return UIManager.getIcon("OptionPane.warningIcon"); + default: + return null; + } + } + + @Override + public void showOptionDialog(String title, String message, MessageType messageType, final Action[] actions) { + backgroundWorker.checkUIAccess(); + + showOptionDialog(title, message, messageType, true, actions, "optionDialog"); + } + + @Override + public void showWebPage(String url, @Nullable Map params) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException("Unable to show web page " + url, e); + } + } + + protected JComponent findTab(Integer hashCode) { + Set> set = tabs.entrySet(); + for (Map.Entry entry : set) { + Window currentWindow = entry.getValue().getCurrentWindow(); + if (hashCode.equals(getWindowHashCode(currentWindow))) + return entry.getKey(); + } + return null; + } + + /** + * Release resources right before throwing away this WindowManager instance. + */ + public void dispose() { + for (WindowOpenInfo openInfo : windowOpenMode.values()) { + if (openInfo.getOpenMode() == OpenMode.DIALOG) { + JDialog dialog = (JDialog) openInfo.getData(); + dialog.setVisible(false); + } + } + + if (isMainWindowManager) { + // Stop background tasks + WatchDog watchDog = AppBeans.get(WatchDog.NAME); + watchDog.stopTasks(); + } + + // Dispose windows + for (Window window : windowOpenMode.keySet()) { + Frame frame = window.getFrame(); + if (frame instanceof Component.Disposable) + ((Component.Disposable) frame).dispose(); + } + + tabs.clear(); + windowOpenMode.clear(); + stacks.clear(); + } + + protected static class WindowOpenInfo { + + protected Window window; + protected OpenMode openMode; + protected Object data; + protected java.awt.Component focusOwner; + + public WindowOpenInfo(Window window, OpenMode openMode) { + this.window = window; + this.openMode = openMode; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public Window getWindow() { + return window; + } + + public OpenMode getOpenMode() { + return openMode; + } + + public java.awt.Component getFocusOwner() { + return focusOwner; + } + + public void setFocusOwner(java.awt.Component focusOwner) { + this.focusOwner = focusOwner; + } + } + + public class TabCloseTask implements Runnable { + protected final WindowBreadCrumbs breadCrumbs; + + public TabCloseTask(WindowBreadCrumbs breadCrumbs) { + this.breadCrumbs = breadCrumbs; + } + + @Override + public void run() { + Window windowToClose = breadCrumbs.getCurrentWindow(); + if (windowToClose != null) { + if (!isCloseWithCloseButtonPrevented(windowToClose)) { + windowToClose.closeAndRun("close", new TabCloseTask(breadCrumbs)); + } + } + } + } + + public void addWindowData(Window window, Object windowData, OpenType openType) { + WindowOpenInfo openInfo = new WindowOpenInfo(window, openType.getOpenMode()); + openInfo.setData(windowData); + if (window instanceof Window.Wrapper) { + Window wrappedWindow = ((Window.Wrapper) window).getWrappedWindow(); + windowOpenMode.put(wrappedWindow, openInfo); + } else { + windowOpenMode.put(window, openInfo); + } + + addShortcuts(window, openType); + } + + public void checkModificationsAndCloseAll(final Runnable runIfOk, final @Nullable Runnable runIfCancel) { + boolean modified = false; + for (Window window : getOpenWindows()) { + if (!disableSavingScreenHistory) { + screenHistorySupport.saveScreenHistory(window, windowOpenMode.get(window).getOpenMode()); + } + + recursiveFramesClose = true; + try { + if (window instanceof WrappedWindow && ((WrappedWindow) window).getWrapper() != null) { + ((WrappedWindow) window).getWrapper().saveSettings(); + } else { + window.saveSettings(); + } + } finally { + recursiveFramesClose = false; + } + + if (window.getDsContext() != null && window.getDsContext().isModified()) { + modified = true; + } + } + disableSavingScreenHistory = true; + if (modified) { + showOptionDialog( + messages.getMainMessage("closeUnsaved.caption"), + messages.getMainMessage("discardChangesOnClose"), + MessageType.WARNING, + new Action[]{ + new com.haulmont.cuba.gui.components.AbstractAction( + messages.getMainMessage("closeApplication")) { + @Override + public void actionPerform(com.haulmont.cuba.gui.components.Component component) { + if (runIfOk != null) + runIfOk.run(); + } + + @Override + public String getIcon() { + return "icons/ok.png"; + } + }, + new com.haulmont.cuba.gui.components.AbstractAction( + messages.getMainMessage("actions.Cancel"), Status.PRIMARY) { + @Override + public void actionPerform(com.haulmont.cuba.gui.components.Component component) { + if (runIfCancel != null) + runIfCancel.run(); + } + + @Override + public String getIcon() { + return "icons/cancel.png"; + } + } + } + ); + } else { + runIfOk.run(); + } + } + + protected String getConfigValueIfConnected(Provider valueProvider, + String fallbackProperty, String fallbackValue) { + if (App.getInstance().getConnection().isConnected()) { + try { + return valueProvider.get(); + } catch (NoUserSessionException ignored) { + } + } + + String propertyValue = AppContext.getProperty(fallbackProperty); + if (propertyValue != null) { + return propertyValue; + } + + return fallbackValue; + } + + @Override + protected SettingsImpl getSettingsImpl(String id) { + return new AsyncSettingsImpl(id); + } + + protected class AsyncSettingsImpl extends SettingsImpl { + public AsyncSettingsImpl(String id) { + super(id); + } + + @Override + public void commit() { + if (modified && root != null) { + final String xml = Dom4j.writeDocument(root.getDocument(), true); + if (!recursiveFramesClose) { + saveSettingsAsync(xml); + } else { + getSettingsClient().setSetting(name, xml); + } + + modified = false; + } + } + + protected void saveSettingsAsync(final String xml) { + BackgroundWorker worker = AppConfig.getBackgroundWorker(); + BackgroundTaskHandler handle = worker.handle(new BackgroundTask(10) { + @Override + public Object run(TaskLifeCycle taskLifeCycle) throws Exception { + getSettingsClient().setSetting(AsyncSettingsImpl.this.name, xml); + + return null; + } + + @Override + public boolean handleException(Exception ex) { + log.warn("Unable to save user settings " + AsyncSettingsImpl.this.name, ex); + + return true; + } + + @Override + public boolean handleTimeoutException() { + log.warn("Time out while saving user settings " + AsyncSettingsImpl.this.name); + + return true; + } + }); + handle.execute(); + } + } + + @Override + protected void initDebugIds(Frame frame) { + if (App.getInstance().isTestMode()) { + ComponentsHelper.walkComponents(frame, new ComponentVisitor() { + @Override + public void visit(com.haulmont.cuba.gui.components.Component component, String name) { + if (component.getDebugId() == null) { + Frame componentFrame = null; + if (component instanceof com.haulmont.cuba.gui.components.Component.BelongToFrame) { + componentFrame = ((com.haulmont.cuba.gui.components.Component.BelongToFrame) component).getFrame(); + } + if (componentFrame == null) { + log.warn("Frame for component " + component.getClass() + " is not assigned"); + } else { + if (component instanceof DesktopAbstractComponent) { + DesktopAbstractComponent desktopComponent = (DesktopAbstractComponent) component; + desktopComponent.assignAutoDebugId(); + } + } + } + } + }); + } + } + + protected boolean isCloseWithShortcutPrevented(Window currentWindow) { + DesktopWindow desktopWindow = (DesktopWindow) ComponentsHelper.getWindowImplementation(currentWindow); + + if (desktopWindow != null) { + Window.BeforeCloseWithShortcutEvent event = new Window.BeforeCloseWithShortcutEvent(desktopWindow); + desktopWindow.fireBeforeCloseWithShortcut(event); + return event.isClosePrevented(); + } + + return false; + } + + protected boolean isCloseWithCloseButtonPrevented(Window currentWindow) { + DesktopWindow desktopWindow = (DesktopWindow) ComponentsHelper.getWindowImplementation(currentWindow); + + if (desktopWindow != null) { + Window.BeforeCloseWithCloseButtonEvent event = new Window.BeforeCloseWithCloseButtonEvent(desktopWindow); + desktopWindow.fireBeforeCloseWithCloseButton(event); + return event.isClosePrevented(); + } + + return false; + } + + protected class DesktopNotificationAction implements Action { + private Type type; + + public DesktopNotificationAction(Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + @Override + public String getId() { + return type.getId(); + } + + @Override + public String getCaption() { + return messages.getMainMessage(type.getMsgKey()); + } + + @Override + public void setCaption(String caption) { + } + + @Override + public String getDescription() { + return null; + } + + @Override + public void setDescription(String description) { + } + + @Override + public KeyCombination getShortcutCombination() { + return null; + } + + @Override + public void setShortcutCombination(KeyCombination shortcut) { + } + + @Override + public void setShortcut(String shortcut) { + } + + @Override + public String getIcon() { + ThemeConstantsManager thCM = AppBeans.get(ThemeConstantsManager.NAME); + return thCM.getThemeValue(type.getIconKey()); + } + + @Override + public void setIcon(String icon) { + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public void setEnabled(boolean enabled) { + } + + @Override + public boolean isVisible() { + return true; + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public void refreshState() { + } + + @Override + public Component.ActionOwner getOwner() { + return null; + } + + @Override + public Collection getOwners() { + return Collections.emptyList(); + } + + @Override + public void addOwner(Component.ActionOwner actionOwner) { + } + + @Override + public void removeOwner(Component.ActionOwner actionOwner) { + } + + @Override + public void actionPerform(Component component) { + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DisabledGlassPane.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DisabledGlassPane.java index ee1e3642ca..e5be48c1b2 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/DisabledGlassPane.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/DisabledGlassPane.java @@ -1,127 +1,127 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseMotionAdapter; - -public class DisabledGlassPane extends JComponent implements KeyListener { - - private final static Border MESSAGE_BORDER = new EmptyBorder(10, 10, 10, 10); - private JLabel message = new JLabel(); - - public DisabledGlassPane() { - // Set glass pane properties - - setOpaque(false); - Color base = UIManager.getColor("control"); - if (base == null) - base = Color.gray; - Color background = new Color(base.getRed(), base.getGreen(), base.getBlue(), 128); - setBackground(background); - setLayout(new GridBagLayout()); - - // Add a message label to the glass pane - - add(message, new GridBagConstraints()); - message.setOpaque(true); - message.setBorder(MESSAGE_BORDER); - - // Disable Mouse, Key and Focus events for the glass pane - - addMouseListener(new MouseAdapter() { - }); - addMouseMotionListener(new MouseMotionAdapter() { - }); - - addKeyListener(this); - - setFocusTraversalKeysEnabled(false); - } - - /* - * The component is transparent but we want to paint the background - * to give it the disabled look. - */ - @Override - protected void paintComponent(Graphics g) { - g.setColor(getBackground()); - g.fillRect(0, 0, getSize().width, getSize().height); - } - - /* - * The background color of the message label will be the same as the - * background of the glass pane without the alpha value - */ - @Override - public void setBackground(Color background) { - super.setBackground(background); - - Color messageBackground = new Color(background.getRGB()); - message.setBackground(messageBackground); - } - - // - // Implement the KeyListener to consume events - // - @Override - public void keyPressed(KeyEvent e) { - e.consume(); - } - - @Override - public void keyTyped(KeyEvent e) { - } - - @Override - public void keyReleased(KeyEvent e) { - e.consume(); - } - - /* - * Make the glass pane visible and change the cursor to the wait cursor - * - * A message can be displayed and it will be centered on the frame. - */ - public void activate(String text) { - if (text != null && text.length() > 0) { - message.setVisible(true); - message.setText(text); - message.setForeground(getForeground()); - } else - message.setVisible(false); - - setVisible(true); -// setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - requestFocusInWindow(); - } - - /* - * Hide the glass pane and restore the cursor - */ - public void deactivate() { -// setCursor(null); - setVisible(false); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseMotionAdapter; + +public class DisabledGlassPane extends JComponent implements KeyListener { + + private final static Border MESSAGE_BORDER = new EmptyBorder(10, 10, 10, 10); + private JLabel message = new JLabel(); + + public DisabledGlassPane() { + // Set glass pane properties + + setOpaque(false); + Color base = UIManager.getColor("control"); + if (base == null) + base = Color.gray; + Color background = new Color(base.getRed(), base.getGreen(), base.getBlue(), 128); + setBackground(background); + setLayout(new GridBagLayout()); + + // Add a message label to the glass pane + + add(message, new GridBagConstraints()); + message.setOpaque(true); + message.setBorder(MESSAGE_BORDER); + + // Disable Mouse, Key and Focus events for the glass pane + + addMouseListener(new MouseAdapter() { + }); + addMouseMotionListener(new MouseMotionAdapter() { + }); + + addKeyListener(this); + + setFocusTraversalKeysEnabled(false); + } + + /* + * The component is transparent but we want to paint the background + * to give it the disabled look. + */ + @Override + protected void paintComponent(Graphics g) { + g.setColor(getBackground()); + g.fillRect(0, 0, getSize().width, getSize().height); + } + + /* + * The background color of the message label will be the same as the + * background of the glass pane without the alpha value + */ + @Override + public void setBackground(Color background) { + super.setBackground(background); + + Color messageBackground = new Color(background.getRGB()); + message.setBackground(messageBackground); + } + + // + // Implement the KeyListener to consume events + // + @Override + public void keyPressed(KeyEvent e) { + e.consume(); + } + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + e.consume(); + } + + /* + * Make the glass pane visible and change the cursor to the wait cursor + * + * A message can be displayed and it will be centered on the frame. + */ + public void activate(String text) { + if (text != null && text.length() > 0) { + message.setVisible(true); + message.setText(text); + message.setForeground(getForeground()); + } else + message.setVisible(false); + + setVisible(true); +// setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + requestFocusInWindow(); + } + + /* + * Hide the glass pane and restore the cursor + */ + public void deactivate() { +// setCursor(null); + setVisible(false); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/FontDialog.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/FontDialog.java index db4452aee3..3015cd02f7 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/FontDialog.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/FontDialog.java @@ -1,321 +1,321 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.desktop.DesktopResources; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; -import org.jdesktop.swingx.combobox.ListComboBoxModel; - -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.*; -import java.awt.event.*; -import java.awt.font.TextAttribute; -import java.util.HashMap; -import java.util.Map; - -public class FontDialog extends JDialog { - - private Font result; - private Font editFont; - - private JLabel previewLabel; - private JToggleButton boldToggle; - private JToggleButton italicToggle; - private JToggleButton underlineToggle; - private JComboBox fontSizeBox; - private JComboBox fontFamilyBox; - - private Messages messages; - - public FontDialog(Frame parent, Font editFont) { - super(parent); - initDialog(parent, editFont); - } - - public FontDialog(Dialog parent, Font editFont) { - super(parent); - initDialog(parent, editFont); - } - - public FontDialog(Window parent, Font editFont) { - super(parent); - initDialog(parent, editFont); - } - - public FontDialog(Component parent, Font editFont) { - initDialog(parent, editFont); - } - - private void initDialog(Component parent, Font editFont) { - this.editFont = editFont; - this.messages = AppBeans.get(Messages.NAME); - - setLocationRelativeTo(parent); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - setTitle(messages.getMessage(getClass(), "FontDialog.title")); - - addWindowListener( - new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(FontDialog.this); - DesktopWindowManager wm = topLevelFrame.getWindowManager(); - - DialogWindow lastDialogWindow = wm.getLastDialogWindow(); - if (lastDialogWindow == null) { - topLevelFrame.activate(); - } else { - lastDialogWindow.enableWindow(); - } - } - } - ); - - initUI(); - } - - private void initUI() { - Configuration configuration = AppBeans.get(Configuration.NAME); - DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); - - setIconImage(null); - setIconImages(null); - setPreferredSize(new Dimension(400, 220)); - setSize(new Dimension(400, 220)); - setMinimumSize(new Dimension(380, 200)); - - JPanel contentPane = new JPanel(); - contentPane.setLayout(new BorderLayout(0, 5)); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - - // font properties panel - - JPanel fontPrefsPanel = new JPanel(); - fontPrefsPanel.setLayout(new BoxLayout(fontPrefsPanel, BoxLayout.X_AXIS)); - - fontFamilyBox = new JComboBox(); - fontFamilyBox.setPreferredSize(new Dimension(160, -1)); - String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); - fontFamilyBox.setModel(new DefaultComboBoxModel<>(availableFonts)); - - fontSizeBox = new JComboBox(); - fontSizeBox.setPreferredSize(new Dimension(60, -1)); - fontSizeBox.setMaximumSize(new Dimension(60, Integer.MAX_VALUE)); - fontSizeBox.setMinimumSize(new Dimension(60, 0)); - fontSizeBox.setModel(new ListComboBoxModel<>(desktopConfig.getAvailableFontSizes())); - - DesktopResources resources = App.getInstance().getResources(); - boldToggle = new JToggleButton(resources.getIcon("font/bold.png")); - italicToggle = new JToggleButton(resources.getIcon("font/italic.png")); - underlineToggle = new JToggleButton(resources.getIcon("font/underline.png")); - - fontPrefsPanel.add(fontFamilyBox); - fontPrefsPanel.add(fontSizeBox); - fontPrefsPanel.add(boldToggle); - fontPrefsPanel.add(italicToggle); - fontPrefsPanel.add(underlineToggle); - - if (editFont != null) { - fontFamilyBox.setSelectedItem(editFont.getFamily()); - fontSizeBox.setSelectedItem(editFont.getSize()); - // toggle buttons - Map attributes = editFont.getAttributes(); - - boldToggle.setSelected((editFont.getStyle() & Font.BOLD) == Font.BOLD); - italicToggle.setSelected((editFont.getStyle() & Font.ITALIC) == Font.ITALIC); - underlineToggle.setSelected(attributes.get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON); - } else { - fontFamilyBox.setSelectedIndex(0); - fontSizeBox.setSelectedIndex(0); - } - - initListeners(); - - contentPane.add(fontPrefsPanel, BorderLayout.NORTH); - - // preview panel - - JPanel previewPanel = new JPanel(); - previewPanel.setLayout(new GridBagLayout()); - previewPanel.setPreferredSize(new Dimension(-1, 120)); - previewPanel.setMinimumSize(new Dimension(0, 120)); - previewPanel.setSize(-1, 120); - - previewLabel = new JLabel("ABCDEFG abcdefg"); - previewPanel.add(previewLabel); - previewLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); - if (editFont != null) - previewLabel.setFont(editFont); - - CollapsiblePanel groupBox = new CollapsiblePanel(previewPanel); - groupBox.setCollapsible(false); - groupBox.setCaption(messages.getMessage(getClass(), "FontDialog.preview")); - - contentPane.add(groupBox, BorderLayout.CENTER); - - // buttons panel - - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS)); - - JButton okBtn = new JButton(new AbstractAction( - messages.getMessage(getClass(), "actions.Ok"), - resources.getIcon("icons/ok.png")) { - @Override - public void actionPerformed(ActionEvent e) { - result = compileFont(); - closeDialog(); - } - }); - okBtn.setPreferredSize(new Dimension(0, DesktopComponentsHelper.BUTTON_HEIGHT)); - - JButton cancelBtn = new JButton(new AbstractAction( - messages.getMessage(getClass(), "actions.Cancel"), - resources.getIcon("icons/cancel.png")) { - @Override - public void actionPerformed(ActionEvent e) { - closeDialog(); - } - }); - cancelBtn.setPreferredSize(new Dimension(0, DesktopComponentsHelper.BUTTON_HEIGHT)); - - buttonsPanel.add(okBtn); - buttonsPanel.add(cancelBtn); - - contentPane.add(buttonsPanel, BorderLayout.SOUTH); - - initToolTips(); - - setContentPane(contentPane); - pack(); - - applyLocation(); - } - - private void applyLocation() { - Point ownerLocation = getParent().getLocationOnScreen(); - int mainX = ownerLocation.x; - int mainY = ownerLocation.y; - - Dimension ownerSize = getParent().getSize(); - int mainWidth = ownerSize.width; - int mainHeight = ownerSize.height; - - Dimension size = getSize(); - int width = size.width; - int height = size.height; - - setLocation(mainX + mainWidth / 2 - width / 2, mainY + mainHeight / 2 - height / 2); - } - - private void initToolTips() { - fontFamilyBox.setToolTipText(messages.getMessage(getClass(), "FontDialog.font")); - fontSizeBox.setToolTipText(messages.getMessage(getClass(), "FontDialog.size")); - - boldToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.bold")); - italicToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.italic")); - underlineToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.underline")); - - DesktopToolTipManager.getInstance().registerTooltip(fontFamilyBox); - DesktopToolTipManager.getInstance().registerTooltip(fontSizeBox); - - DesktopToolTipManager.getInstance().registerTooltip(boldToggle); - DesktopToolTipManager.getInstance().registerTooltip(italicToggle); - DesktopToolTipManager.getInstance().registerTooltip(underlineToggle); - } - - private void closeDialog() { - WindowEvent windowClosing = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); - this.dispatchEvent(windowClosing); - } - - private void initListeners() { - ItemListener propertyBoxChangeListener = new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - previewLabel.setFont(compileFont()); - } - }; - - fontFamilyBox.addItemListener(propertyBoxChangeListener); - fontSizeBox.addItemListener(propertyBoxChangeListener); - - ChangeListener toggleListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - previewLabel.setFont(compileFont()); - } - }; - - boldToggle.addChangeListener(toggleListener); - italicToggle.addChangeListener(toggleListener); - underlineToggle.addChangeListener(toggleListener); - } - - public Font compileFont() { - int style = 0; - style |= boldToggle.isSelected() ? Font.BOLD : 0; - style |= italicToggle.isSelected() ? Font.ITALIC : 0; - Font font = new Font((String) fontFamilyBox.getSelectedItem(), style, (Integer) fontSizeBox.getSelectedItem()); - if (underlineToggle.isSelected()) { - Map attributes = new HashMap<>(); - attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); - font = font.deriveFont(attributes); - } - return font; - } - - public void open() { - TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(this); - DialogWindow lastDialogWindow = topLevelFrame.getWindowManager().getLastDialogWindow(); - if (lastDialogWindow == null) { - topLevelFrame.deactivate(null); - } else { - lastDialogWindow.disableWindow(null); - } - setVisible(true); - } - - public Font getResult() { - return result; - } - - public static FontDialog show(Component parent, Font editFont) { - FontDialog dialog; - if (parent instanceof JFrame) - dialog = new FontDialog((JFrame) parent, editFont); - else if (parent instanceof JDialog) - dialog = new FontDialog((JDialog) parent, editFont); - else if (parent instanceof JWindow) - dialog = new FontDialog((JWindow) parent, editFont); - else - dialog = new FontDialog(parent, editFont); - - return dialog; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.desktop.DesktopResources; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; +import org.jdesktop.swingx.combobox.ListComboBoxModel; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.*; +import java.awt.font.TextAttribute; +import java.util.HashMap; +import java.util.Map; + +public class FontDialog extends JDialog { + + private Font result; + private Font editFont; + + private JLabel previewLabel; + private JToggleButton boldToggle; + private JToggleButton italicToggle; + private JToggleButton underlineToggle; + private JComboBox fontSizeBox; + private JComboBox fontFamilyBox; + + private Messages messages; + + public FontDialog(Frame parent, Font editFont) { + super(parent); + initDialog(parent, editFont); + } + + public FontDialog(Dialog parent, Font editFont) { + super(parent); + initDialog(parent, editFont); + } + + public FontDialog(Window parent, Font editFont) { + super(parent); + initDialog(parent, editFont); + } + + public FontDialog(Component parent, Font editFont) { + initDialog(parent, editFont); + } + + private void initDialog(Component parent, Font editFont) { + this.editFont = editFont; + this.messages = AppBeans.get(Messages.NAME); + + setLocationRelativeTo(parent); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setTitle(messages.getMessage(getClass(), "FontDialog.title")); + + addWindowListener( + new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(FontDialog.this); + DesktopWindowManager wm = topLevelFrame.getWindowManager(); + + DialogWindow lastDialogWindow = wm.getLastDialogWindow(); + if (lastDialogWindow == null) { + topLevelFrame.activate(); + } else { + lastDialogWindow.enableWindow(); + } + } + } + ); + + initUI(); + } + + private void initUI() { + Configuration configuration = AppBeans.get(Configuration.NAME); + DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class); + + setIconImage(null); + setIconImages(null); + setPreferredSize(new Dimension(400, 220)); + setSize(new Dimension(400, 220)); + setMinimumSize(new Dimension(380, 200)); + + JPanel contentPane = new JPanel(); + contentPane.setLayout(new BorderLayout(0, 5)); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + + // font properties panel + + JPanel fontPrefsPanel = new JPanel(); + fontPrefsPanel.setLayout(new BoxLayout(fontPrefsPanel, BoxLayout.X_AXIS)); + + fontFamilyBox = new JComboBox(); + fontFamilyBox.setPreferredSize(new Dimension(160, -1)); + String[] availableFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + fontFamilyBox.setModel(new DefaultComboBoxModel<>(availableFonts)); + + fontSizeBox = new JComboBox(); + fontSizeBox.setPreferredSize(new Dimension(60, -1)); + fontSizeBox.setMaximumSize(new Dimension(60, Integer.MAX_VALUE)); + fontSizeBox.setMinimumSize(new Dimension(60, 0)); + fontSizeBox.setModel(new ListComboBoxModel<>(desktopConfig.getAvailableFontSizes())); + + DesktopResources resources = App.getInstance().getResources(); + boldToggle = new JToggleButton(resources.getIcon("font/bold.png")); + italicToggle = new JToggleButton(resources.getIcon("font/italic.png")); + underlineToggle = new JToggleButton(resources.getIcon("font/underline.png")); + + fontPrefsPanel.add(fontFamilyBox); + fontPrefsPanel.add(fontSizeBox); + fontPrefsPanel.add(boldToggle); + fontPrefsPanel.add(italicToggle); + fontPrefsPanel.add(underlineToggle); + + if (editFont != null) { + fontFamilyBox.setSelectedItem(editFont.getFamily()); + fontSizeBox.setSelectedItem(editFont.getSize()); + // toggle buttons + Map attributes = editFont.getAttributes(); + + boldToggle.setSelected((editFont.getStyle() & Font.BOLD) == Font.BOLD); + italicToggle.setSelected((editFont.getStyle() & Font.ITALIC) == Font.ITALIC); + underlineToggle.setSelected(attributes.get(TextAttribute.UNDERLINE) == TextAttribute.UNDERLINE_ON); + } else { + fontFamilyBox.setSelectedIndex(0); + fontSizeBox.setSelectedIndex(0); + } + + initListeners(); + + contentPane.add(fontPrefsPanel, BorderLayout.NORTH); + + // preview panel + + JPanel previewPanel = new JPanel(); + previewPanel.setLayout(new GridBagLayout()); + previewPanel.setPreferredSize(new Dimension(-1, 120)); + previewPanel.setMinimumSize(new Dimension(0, 120)); + previewPanel.setSize(-1, 120); + + previewLabel = new JLabel("ABCDEFG abcdefg"); + previewPanel.add(previewLabel); + previewLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); + if (editFont != null) + previewLabel.setFont(editFont); + + CollapsiblePanel groupBox = new CollapsiblePanel(previewPanel); + groupBox.setCollapsible(false); + groupBox.setCaption(messages.getMessage(getClass(), "FontDialog.preview")); + + contentPane.add(groupBox, BorderLayout.CENTER); + + // buttons panel + + JPanel buttonsPanel = new JPanel(); + buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS)); + + JButton okBtn = new JButton(new AbstractAction( + messages.getMessage(getClass(), "actions.Ok"), + resources.getIcon("icons/ok.png")) { + @Override + public void actionPerformed(ActionEvent e) { + result = compileFont(); + closeDialog(); + } + }); + okBtn.setPreferredSize(new Dimension(0, DesktopComponentsHelper.BUTTON_HEIGHT)); + + JButton cancelBtn = new JButton(new AbstractAction( + messages.getMessage(getClass(), "actions.Cancel"), + resources.getIcon("icons/cancel.png")) { + @Override + public void actionPerformed(ActionEvent e) { + closeDialog(); + } + }); + cancelBtn.setPreferredSize(new Dimension(0, DesktopComponentsHelper.BUTTON_HEIGHT)); + + buttonsPanel.add(okBtn); + buttonsPanel.add(cancelBtn); + + contentPane.add(buttonsPanel, BorderLayout.SOUTH); + + initToolTips(); + + setContentPane(contentPane); + pack(); + + applyLocation(); + } + + private void applyLocation() { + Point ownerLocation = getParent().getLocationOnScreen(); + int mainX = ownerLocation.x; + int mainY = ownerLocation.y; + + Dimension ownerSize = getParent().getSize(); + int mainWidth = ownerSize.width; + int mainHeight = ownerSize.height; + + Dimension size = getSize(); + int width = size.width; + int height = size.height; + + setLocation(mainX + mainWidth / 2 - width / 2, mainY + mainHeight / 2 - height / 2); + } + + private void initToolTips() { + fontFamilyBox.setToolTipText(messages.getMessage(getClass(), "FontDialog.font")); + fontSizeBox.setToolTipText(messages.getMessage(getClass(), "FontDialog.size")); + + boldToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.bold")); + italicToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.italic")); + underlineToggle.setToolTipText(messages.getMessage(getClass(), "FontDialog.underline")); + + DesktopToolTipManager.getInstance().registerTooltip(fontFamilyBox); + DesktopToolTipManager.getInstance().registerTooltip(fontSizeBox); + + DesktopToolTipManager.getInstance().registerTooltip(boldToggle); + DesktopToolTipManager.getInstance().registerTooltip(italicToggle); + DesktopToolTipManager.getInstance().registerTooltip(underlineToggle); + } + + private void closeDialog() { + WindowEvent windowClosing = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); + this.dispatchEvent(windowClosing); + } + + private void initListeners() { + ItemListener propertyBoxChangeListener = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + previewLabel.setFont(compileFont()); + } + }; + + fontFamilyBox.addItemListener(propertyBoxChangeListener); + fontSizeBox.addItemListener(propertyBoxChangeListener); + + ChangeListener toggleListener = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + previewLabel.setFont(compileFont()); + } + }; + + boldToggle.addChangeListener(toggleListener); + italicToggle.addChangeListener(toggleListener); + underlineToggle.addChangeListener(toggleListener); + } + + public Font compileFont() { + int style = 0; + style |= boldToggle.isSelected() ? Font.BOLD : 0; + style |= italicToggle.isSelected() ? Font.ITALIC : 0; + Font font = new Font((String) fontFamilyBox.getSelectedItem(), style, (Integer) fontSizeBox.getSelectedItem()); + if (underlineToggle.isSelected()) { + Map attributes = new HashMap<>(); + attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); + font = font.deriveFont(attributes); + } + return font; + } + + public void open() { + TopLevelFrame topLevelFrame = DesktopComponentsHelper.getTopLevelFrame(this); + DialogWindow lastDialogWindow = topLevelFrame.getWindowManager().getLastDialogWindow(); + if (lastDialogWindow == null) { + topLevelFrame.deactivate(null); + } else { + lastDialogWindow.disableWindow(null); + } + setVisible(true); + } + + public Font getResult() { + return result; + } + + public static FontDialog show(Component parent, Font editFont) { + FontDialog dialog; + if (parent instanceof JFrame) + dialog = new FontDialog((JFrame) parent, editFont); + else if (parent instanceof JDialog) + dialog = new FontDialog((JDialog) parent, editFont); + else if (parent instanceof JWindow) + dialog = new FontDialog((JWindow) parent, editFont); + else + dialog = new FontDialog(parent, editFont); + + return dialog; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/JXErrorPaneExt.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/JXErrorPaneExt.java index e56b3ca2c0..dc6260776b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/JXErrorPaneExt.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/JXErrorPaneExt.java @@ -1,179 +1,179 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.app.EmailService; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.TopLevelFrame; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.jdesktop.swingx.JXErrorPane; -import org.jdesktop.swingx.error.ErrorInfo; -import org.jdesktop.swingx.error.ErrorReporter; -import org.jdesktop.swingx.plaf.basic.BasicErrorPaneUI; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.SimpleDateFormat; -import java.util.Locale; - -public class JXErrorPaneExt extends JXErrorPane { - - protected ActionListener copyToClipboardListener; - - public JXErrorPaneExt() { - - Configuration configuration = AppBeans.get(Configuration.NAME); - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - Messages messages = AppBeans.get(Messages.NAME); - Locale locale = App.getInstance().getLocale(); - - UIManager.put("JXErrorPane.details_expand_text", - messages.getMainMessage("JXErrorPane.details_expand_text", locale)); - UIManager.put("JXErrorPane.details_contract_text", - messages.getMainMessage("JXErrorPane.details_contract_text", locale)); - UIManager.put("JXErrorPane.ok_button_text", - messages.getMainMessage("JXErrorPane.ok_button_text", locale)); - UIManager.put("JXErrorPane.fatal_button_text", - messages.getMainMessage("JXErrorPane.fatal_button_text", locale)); - UIManager.put("JXErrorPane.report_button_text", - messages.getMainMessage("JXErrorPane.report_button_text", locale)); - UIManager.put("JXErrorPane.copy_to_clipboard_button_text", - messages.getMainMessage("JXErrorPane.copy_to_clipboard_button_text", locale)); - - ErrorPaneUIExt ui = new ErrorPaneUIExt(); - setUI(ui); - - JButton copyButton = ui.getCopyToClipboardButton(); - copyToClipboardListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - TopLevelFrame mainFrame = App.getInstance().getMainFrame(); - mainFrame.showNotification(messages.getMainMessage("errorPane.copingSuccessful", locale), - Frame.NotificationType.TRAY); - } - }; - copyButton.addActionListener(copyToClipboardListener); - - UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - Security security = AppBeans.get(Security.NAME); - if (userSessionSource == null || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { - copyButton.setVisible(false); - } - - String supportEmail = null; - if (App.getInstance().getConnection().isConnected()) { - supportEmail = clientConfig.getSupportEmail(); - } - - if (StringUtils.isNotBlank(supportEmail)) { - setErrorReporter(new ErrorReporter() { - @Override - public void reportError(ErrorInfo info) throws NullPointerException { - sendSupportEmail(info); - ((ErrorPaneUIExt) getUI()).setEnabled(false); - } - }); - } - } - - private void sendSupportEmail(ErrorInfo jXErrorPaneInfo) { - - Configuration configuration = AppBeans.get(Configuration.NAME); - ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); - TopLevelFrame mainFrame = App.getInstance().getMainFrame(); - Messages messages = AppBeans.get(Messages.NAME); - Locale locale = App.getInstance().getLocale(); - - try { - TimeSource timeSource = AppBeans.get(TimeSource.NAME); - String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timeSource.currentTimestamp()); - - //noinspection StringBufferReplaceableByString - StringBuilder sb = new StringBuilder(""); - sb.append("

").append(date).append("

"); - sb.append("

").append(jXErrorPaneInfo.getBasicErrorMessage().replace("\n", "
")).append("

"); - sb.append("

").append(getStackTrace(jXErrorPaneInfo.getErrorException())).append("

"); - sb.append(""); - - UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - User user = userSessionSource.getUserSession().getUser(); - EmailInfo info = new EmailInfo( - clientConfig.getSupportEmail(), - "[" + clientConfig.getSystemID() + "] [" + user.getLogin() + "] Exception Report", - sb.toString()); - - if (user.getEmail() != null) { - info.setFrom(user.getEmail()); - } - - EmailService emailService = AppBeans.get(EmailService.NAME); - emailService.sendEmail(info); - - mainFrame.showNotification(messages.getMainMessage("errorPane.emailSent", locale), - Frame.NotificationType.TRAY); - } catch (Throwable e) { - mainFrame.showNotification(messages.getMainMessage("errorPane.emailSendingErr", locale), - Frame.NotificationType.ERROR); - } - } - - private String getStackTrace(Throwable throwable) { - if (throwable instanceof RemoteException) { - RemoteException re = (RemoteException) throwable; - for (int i = re.getCauses().size() - 1; i >= 0; i--) { - if (re.getCauses().get(i).getThrowable() != null) { - throwable = re.getCauses().get(i).getThrowable(); - break; - } - } - } - - String html = StringEscapeUtils.escapeHtml(ExceptionUtils.getStackTrace(throwable)); - html = StringUtils.replace(html, "\n", "
"); - html = StringUtils.replace(html, " ", " "); - html = StringUtils.replace(html, "\t", "    "); - - return html; - } - - public static class ErrorPaneUIExt extends BasicErrorPaneUI { - - public JButton getCopyToClipboardButton() { - return copyToClipboardButton; - } - - public void setEnabled(boolean enabled) { - if (reportButton != null) { - reportButton.setEnabled(enabled); - } - } - - @Override - protected void uninstallComponents() { - copyToClipboardButton.removeActionListener(copyToClipboardListener); - super.uninstallComponents(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.app.EmailService; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.TopLevelFrame; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.jdesktop.swingx.JXErrorPane; +import org.jdesktop.swingx.error.ErrorInfo; +import org.jdesktop.swingx.error.ErrorReporter; +import org.jdesktop.swingx.plaf.basic.BasicErrorPaneUI; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; +import java.util.Locale; + +public class JXErrorPaneExt extends JXErrorPane { + + protected ActionListener copyToClipboardListener; + + public JXErrorPaneExt() { + + Configuration configuration = AppBeans.get(Configuration.NAME); + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + Messages messages = AppBeans.get(Messages.NAME); + Locale locale = App.getInstance().getLocale(); + + UIManager.put("JXErrorPane.details_expand_text", + messages.getMainMessage("JXErrorPane.details_expand_text", locale)); + UIManager.put("JXErrorPane.details_contract_text", + messages.getMainMessage("JXErrorPane.details_contract_text", locale)); + UIManager.put("JXErrorPane.ok_button_text", + messages.getMainMessage("JXErrorPane.ok_button_text", locale)); + UIManager.put("JXErrorPane.fatal_button_text", + messages.getMainMessage("JXErrorPane.fatal_button_text", locale)); + UIManager.put("JXErrorPane.report_button_text", + messages.getMainMessage("JXErrorPane.report_button_text", locale)); + UIManager.put("JXErrorPane.copy_to_clipboard_button_text", + messages.getMainMessage("JXErrorPane.copy_to_clipboard_button_text", locale)); + + ErrorPaneUIExt ui = new ErrorPaneUIExt(); + setUI(ui); + + JButton copyButton = ui.getCopyToClipboardButton(); + copyToClipboardListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + TopLevelFrame mainFrame = App.getInstance().getMainFrame(); + mainFrame.showNotification(messages.getMainMessage("errorPane.copingSuccessful", locale), + Frame.NotificationType.TRAY); + } + }; + copyButton.addActionListener(copyToClipboardListener); + + UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + Security security = AppBeans.get(Security.NAME); + if (userSessionSource == null || !security.isSpecificPermitted("cuba.gui.showExceptionDetails")) { + copyButton.setVisible(false); + } + + String supportEmail = null; + if (App.getInstance().getConnection().isConnected()) { + supportEmail = clientConfig.getSupportEmail(); + } + + if (StringUtils.isNotBlank(supportEmail)) { + setErrorReporter(new ErrorReporter() { + @Override + public void reportError(ErrorInfo info) throws NullPointerException { + sendSupportEmail(info); + ((ErrorPaneUIExt) getUI()).setEnabled(false); + } + }); + } + } + + private void sendSupportEmail(ErrorInfo jXErrorPaneInfo) { + + Configuration configuration = AppBeans.get(Configuration.NAME); + ClientConfig clientConfig = configuration.getConfig(ClientConfig.class); + TopLevelFrame mainFrame = App.getInstance().getMainFrame(); + Messages messages = AppBeans.get(Messages.NAME); + Locale locale = App.getInstance().getLocale(); + + try { + TimeSource timeSource = AppBeans.get(TimeSource.NAME); + String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timeSource.currentTimestamp()); + + //noinspection StringBufferReplaceableByString + StringBuilder sb = new StringBuilder(""); + sb.append("

").append(date).append("

"); + sb.append("

").append(jXErrorPaneInfo.getBasicErrorMessage().replace("\n", "
")).append("

"); + sb.append("

").append(getStackTrace(jXErrorPaneInfo.getErrorException())).append("

"); + sb.append(""); + + UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + User user = userSessionSource.getUserSession().getUser(); + EmailInfo info = new EmailInfo( + clientConfig.getSupportEmail(), + "[" + clientConfig.getSystemID() + "] [" + user.getLogin() + "] Exception Report", + sb.toString()); + + if (user.getEmail() != null) { + info.setFrom(user.getEmail()); + } + + EmailService emailService = AppBeans.get(EmailService.NAME); + emailService.sendEmail(info); + + mainFrame.showNotification(messages.getMainMessage("errorPane.emailSent", locale), + Frame.NotificationType.TRAY); + } catch (Throwable e) { + mainFrame.showNotification(messages.getMainMessage("errorPane.emailSendingErr", locale), + Frame.NotificationType.ERROR); + } + } + + private String getStackTrace(Throwable throwable) { + if (throwable instanceof RemoteException) { + RemoteException re = (RemoteException) throwable; + for (int i = re.getCauses().size() - 1; i >= 0; i--) { + if (re.getCauses().get(i).getThrowable() != null) { + throwable = re.getCauses().get(i).getThrowable(); + break; + } + } + } + + String html = StringEscapeUtils.escapeHtml(ExceptionUtils.getStackTrace(throwable)); + html = StringUtils.replace(html, "\n", "
"); + html = StringUtils.replace(html, " ", " "); + html = StringUtils.replace(html, "\t", "    "); + + return html; + } + + public static class ErrorPaneUIExt extends BasicErrorPaneUI { + + public JButton getCopyToClipboardButton() { + return copyToClipboardButton; + } + + public void setEnabled(boolean enabled) { + if (reportButton != null) { + reportButton.setEnabled(enabled); + } + } + + @Override + protected void uninstallComponents() { + copyToClipboardButton.removeActionListener(copyToClipboardListener); + super.uninstallComponents(); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/LoginProperties.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/LoginProperties.java index 68ceb511a1..563be491a5 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/LoginProperties.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/LoginProperties.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; - -public class LoginProperties { - - private Logger log = LoggerFactory.getLogger(LoginProperties.class); - - protected Properties properties = new Properties(); - - protected String dataDir; - - protected static final String FILE_NAME = "login.properties"; - protected static final String LOGIN = "login"; - protected static final String LOCALE = "locale"; - - public LoginProperties() { - dataDir = AppBeans.get(Configuration.NAME, Configuration.class).getConfig(GlobalConfig.class).getDataDir(); - loadProperties(); - } - - public void save(String login, String locale) { - properties.setProperty(LOGIN, login); - properties.setProperty(LOCALE, locale); - saveProperties(); - } - - public String loadLastLogin() { - return properties.getProperty(LOGIN); - } - - public String loadLastLocale() { - return properties.getProperty(LOCALE); - } - - protected void loadProperties() { - File propertiesFile = new File(dataDir, FILE_NAME); - try { - if (propertiesFile.exists()) { - FileInputStream stream = FileUtils.openInputStream(propertiesFile); - try { - properties.load(stream); - } finally { - IOUtils.closeQuietly(stream); - } - } - } catch (IOException e) { - log.error("Error loading login properties", e); - } - } - - protected void saveProperties() { - File propertiesFile = new File(dataDir, "login.properties"); - try { - FileOutputStream stream = FileUtils.openOutputStream(propertiesFile); - try { - properties.store(stream, "Login properties"); - } finally { - IOUtils.closeQuietly(stream); - } - } catch (IOException e) { - log.error("Error saving login properties", e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +public class LoginProperties { + + private Logger log = LoggerFactory.getLogger(LoginProperties.class); + + protected Properties properties = new Properties(); + + protected String dataDir; + + protected static final String FILE_NAME = "login.properties"; + protected static final String LOGIN = "login"; + protected static final String LOCALE = "locale"; + + public LoginProperties() { + dataDir = AppBeans.get(Configuration.NAME, Configuration.class).getConfig(GlobalConfig.class).getDataDir(); + loadProperties(); + } + + public void save(String login, String locale) { + properties.setProperty(LOGIN, login); + properties.setProperty(LOCALE, locale); + saveProperties(); + } + + public String loadLastLogin() { + return properties.getProperty(LOGIN); + } + + public String loadLastLocale() { + return properties.getProperty(LOCALE); + } + + protected void loadProperties() { + File propertiesFile = new File(dataDir, FILE_NAME); + try { + if (propertiesFile.exists()) { + FileInputStream stream = FileUtils.openInputStream(propertiesFile); + try { + properties.load(stream); + } finally { + IOUtils.closeQuietly(stream); + } + } + } catch (IOException e) { + log.error("Error loading login properties", e); + } + } + + protected void saveProperties() { + File propertiesFile = new File(dataDir, "login.properties"); + try { + FileOutputStream stream = FileUtils.openOutputStream(propertiesFile); + try { + properties.store(stream, "Login properties"); + } finally { + IOUtils.closeQuietly(stream); + } + } catch (IOException e) { + log.error("Error saving login properties", e); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/MainWindowProperties.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/MainWindowProperties.java index 7d4d307a86..636c3dabcf 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/MainWindowProperties.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/MainWindowProperties.java @@ -1,106 +1,106 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import java.awt.*; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Properties; - -public class MainWindowProperties { - - private final Logger log = LoggerFactory.getLogger(MainWindowProperties.class); - - private JFrame frame; - - public MainWindowProperties(JFrame frame) { - this.frame = frame; - } - - public void save() { - Properties properties = new Properties(); - saveProperties(properties); - try { - File file = new File(AppBeans.get(Configuration.class).getConfig(GlobalConfig.class).getDataDir(), "main-window.properties"); - FileOutputStream stream = FileUtils.openOutputStream(file); - try { - properties.store(stream, "Main window properties"); - } finally { - IOUtils.closeQuietly(stream); - } - } catch (IOException e) { - log.error("Error saving main window location", e); - } - } - - protected void saveProperties(Properties properties) { - if (frame.getExtendedState() == Frame.MAXIMIZED_BOTH) { - properties.setProperty("maximized", "true"); - } else { - properties.setProperty("x", String.valueOf((int)frame.getBounds().getX())); - properties.setProperty("y", String.valueOf((int)frame.getBounds().getY())); - properties.setProperty("width", String.valueOf((int)frame.getBounds().getWidth())); - properties.setProperty("height", String.valueOf((int)frame.getBounds().getHeight())); - } - } - - public void load() { - Properties properties = new Properties(); - try { - Configuration configuration = AppBeans.get(Configuration.NAME); - File file = new File(configuration.getConfig(GlobalConfig.class).getDataDir(), "main-window.properties"); - if (file.exists()) { - FileInputStream stream = FileUtils.openInputStream(file); - try { - properties.load(stream); - } finally { - IOUtils.closeQuietly(stream); - } - } - } catch (IOException e) { - log.error("Error loading main window location", e); - } - loadProperties(properties); - } - - protected void loadProperties(Properties properties) { - Boolean maximized = Boolean.valueOf(properties.getProperty("maximized", "false")); - if (maximized) { - frame.setExtendedState(Frame.MAXIMIZED_BOTH); - } - int x = Integer.parseInt(properties.getProperty("x", "0")); - int y = Integer.parseInt(properties.getProperty("y", "0")); - int width = Integer.parseInt(properties.getProperty("width", "1000")); - int height = Integer.parseInt(properties.getProperty("height", "700")); - - frame.setBounds(x, y, width, height); - if (x == 0 && y == 0) - frame.setLocationRelativeTo(null); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +public class MainWindowProperties { + + private final Logger log = LoggerFactory.getLogger(MainWindowProperties.class); + + private JFrame frame; + + public MainWindowProperties(JFrame frame) { + this.frame = frame; + } + + public void save() { + Properties properties = new Properties(); + saveProperties(properties); + try { + File file = new File(AppBeans.get(Configuration.class).getConfig(GlobalConfig.class).getDataDir(), "main-window.properties"); + FileOutputStream stream = FileUtils.openOutputStream(file); + try { + properties.store(stream, "Main window properties"); + } finally { + IOUtils.closeQuietly(stream); + } + } catch (IOException e) { + log.error("Error saving main window location", e); + } + } + + protected void saveProperties(Properties properties) { + if (frame.getExtendedState() == Frame.MAXIMIZED_BOTH) { + properties.setProperty("maximized", "true"); + } else { + properties.setProperty("x", String.valueOf((int)frame.getBounds().getX())); + properties.setProperty("y", String.valueOf((int)frame.getBounds().getY())); + properties.setProperty("width", String.valueOf((int)frame.getBounds().getWidth())); + properties.setProperty("height", String.valueOf((int)frame.getBounds().getHeight())); + } + } + + public void load() { + Properties properties = new Properties(); + try { + Configuration configuration = AppBeans.get(Configuration.NAME); + File file = new File(configuration.getConfig(GlobalConfig.class).getDataDir(), "main-window.properties"); + if (file.exists()) { + FileInputStream stream = FileUtils.openInputStream(file); + try { + properties.load(stream); + } finally { + IOUtils.closeQuietly(stream); + } + } + } catch (IOException e) { + log.error("Error loading main window location", e); + } + loadProperties(properties); + } + + protected void loadProperties(Properties properties) { + Boolean maximized = Boolean.valueOf(properties.getProperty("maximized", "false")); + if (maximized) { + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + } + int x = Integer.parseInt(properties.getProperty("x", "0")); + int y = Integer.parseInt(properties.getProperty("y", "0")); + int width = Integer.parseInt(properties.getProperty("width", "1000")); + int height = Integer.parseInt(properties.getProperty("height", "700")); + + frame.setBounds(x, y, width, height); + if (x == 0 && y == 0) + frame.setLocationRelativeTo(null); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/MenuBuilder.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/MenuBuilder.java index 63a08ee75e..7e3dc96790 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/MenuBuilder.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/MenuBuilder.java @@ -1,218 +1,218 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; -import com.haulmont.cuba.gui.components.KeyCombination; -import com.haulmont.cuba.gui.config.MenuCommand; -import com.haulmont.cuba.gui.config.MenuConfig; -import com.haulmont.cuba.gui.config.MenuItem; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.collections4.CollectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.swing.*; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public class MenuBuilder { - - private Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - - private UserSession userSession; - private JMenuBar menuBar; - private MenuConfig menuConfig; - - public MenuBuilder(UserSession userSession, JMenuBar menuBar) { - this.userSession = userSession; - this.menuBar = menuBar; - menuConfig = AppBeans.get(MenuConfig.NAME); - } - - public void build() { - List rootItems = menuConfig.getRootItems(); - for (MenuItem item : rootItems) { - if (item.isPermitted(userSession)) { - createMenuBarItem(menuBar, item); - } - } - } - - private void createMenuBarItem(JMenuBar menuBar, MenuItem item) { - String caption = menuConfig.getItemCaption(item.getId()); - if (!item.getChildren().isEmpty() || item.isMenu()) { - final JMenu jMenu = new JMenu(caption); - jMenu.addMenuListener(new MenuListener() { - @Override - public void menuSelected(MenuEvent e) { - jMenu.requestFocus(); - } - - @Override - public void menuDeselected(MenuEvent e) { - } - - @Override - public void menuCanceled(MenuEvent e) { - } - }); - jMenu.setName(item.getId()); - menuBar.add(jMenu); - createSubMenu(jMenu, item); - } else { - JMenuItem jMenuItem = new JMenuItem(caption); - jMenuItem.setName(item.getId()); - //todo remove hardcoded border - jMenuItem.setBorder(BorderFactory.createEmptyBorder(1, 4, 2, 4)); - assignShortcut(jMenuItem, item); - jMenuItem.setMaximumSize(new Dimension(jMenuItem.getPreferredSize().width, - jMenuItem.getMaximumSize().height)); - assignCommand(jMenuItem, item); - menuBar.add(jMenuItem); - } - } - - private void assignCommand(final JMenuItem jMenuItem, MenuItem item) { - final MenuCommand command = new MenuCommand(item); - jMenuItem.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - command.execute(); - - StringBuilder menuPath = new StringBuilder(); - formatMenuPath(item, menuPath); - userActionsLog.trace("Action \"{}\" was performed using menu item {}", command.getCommandDescription(), menuPath.toString()); - } - }); - } - - private void createSubMenu(JMenu jMenu, MenuItem item) { - List itemChildren = new ArrayList<>(item.getChildren()); - CollectionUtils.filter(itemChildren, object -> object.isPermitted(userSession)); - - List items = new ArrayList<>(); - - // prepare menu items - for (MenuItem child : itemChildren) { - if (child.getChildren().isEmpty()) { - if (child.isSeparator()) { - items.add(new MenuItemContainer()); - } else { - JMenuItem jMenuItem = new JMenuItem(menuConfig.getItemCaption(child.getId())); - jMenuItem.setName(child.getId()); - assignCommand(jMenuItem, child); - assignShortcut(jMenuItem, child); - items.add(new MenuItemContainer(jMenuItem)); - } - } else { - JMenu jChildMenu = new JMenu(menuConfig.getItemCaption(child.getId())); - createSubMenu(jChildMenu, child); - if (!isMenuEmpty(jChildMenu)) { - items.add(new MenuItemContainer(jChildMenu)); - } - } - } - - // remove unnecessary separators - if (!items.isEmpty()) { - Iterator iterator = items.iterator(); - JMenuItem menuItem = getNextMenuItem(iterator); - boolean useSeparator = false; - - while (menuItem != null) { - if (useSeparator) - jMenu.addSeparator(); - - jMenu.add(menuItem); - - useSeparator = false; - menuItem = null; - - if (iterator.hasNext()) { - MenuItemContainer itemContainer = iterator.next(); - if (!itemContainer.isSeparator()) - menuItem = itemContainer.getMenuItem(); - else { - menuItem = getNextMenuItem(iterator); - useSeparator = true; - } - } - } - } - } - - private JMenuItem getNextMenuItem(Iterator iterator) { - JMenuItem item = null; - while (iterator.hasNext() && item == null) { - MenuItemContainer cMenuItem = iterator.next(); - if (!cMenuItem.isSeparator()) - item = cMenuItem.getMenuItem(); - } - return item; - } - - private static class MenuItemContainer { - private JMenuItem menuItem = null; - - private MenuItemContainer() { - } - - public MenuItemContainer(JMenuItem menuItem) { - this.menuItem = menuItem; - } - - public JMenuItem getMenuItem() { - return menuItem; - } - - public boolean isSeparator() { - return this.menuItem == null; - } - } - - private boolean isMenuEmpty(JMenu jMenu) { - return jMenu.getSubElements().length == 0; - } - - private void assignShortcut(JMenuItem jMenuItem, MenuItem item) { - if (item.getShortcut() != null) { - KeyCombination.Key key = item.getShortcut().getKey(); - KeyCombination.Modifier[] modifiers = item.getShortcut().getModifiers(); - KeyCombination combo = new KeyCombination(key, modifiers); - jMenuItem.setAccelerator(DesktopComponentsHelper.convertKeyCombination(combo)); - } - } - - private void formatMenuPath(MenuItem menuItem, StringBuilder stringBuilder) { - if (menuItem.getParent() != null) { - formatMenuPath(menuItem.getParent(), stringBuilder); - } - - stringBuilder.append(menuItem.getId()); - stringBuilder.append("->"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; +import com.haulmont.cuba.gui.components.KeyCombination; +import com.haulmont.cuba.gui.config.MenuCommand; +import com.haulmont.cuba.gui.config.MenuConfig; +import com.haulmont.cuba.gui.config.MenuItem; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class MenuBuilder { + + private Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + + private UserSession userSession; + private JMenuBar menuBar; + private MenuConfig menuConfig; + + public MenuBuilder(UserSession userSession, JMenuBar menuBar) { + this.userSession = userSession; + this.menuBar = menuBar; + menuConfig = AppBeans.get(MenuConfig.NAME); + } + + public void build() { + List rootItems = menuConfig.getRootItems(); + for (MenuItem item : rootItems) { + if (item.isPermitted(userSession)) { + createMenuBarItem(menuBar, item); + } + } + } + + private void createMenuBarItem(JMenuBar menuBar, MenuItem item) { + String caption = menuConfig.getItemCaption(item.getId()); + if (!item.getChildren().isEmpty() || item.isMenu()) { + final JMenu jMenu = new JMenu(caption); + jMenu.addMenuListener(new MenuListener() { + @Override + public void menuSelected(MenuEvent e) { + jMenu.requestFocus(); + } + + @Override + public void menuDeselected(MenuEvent e) { + } + + @Override + public void menuCanceled(MenuEvent e) { + } + }); + jMenu.setName(item.getId()); + menuBar.add(jMenu); + createSubMenu(jMenu, item); + } else { + JMenuItem jMenuItem = new JMenuItem(caption); + jMenuItem.setName(item.getId()); + //todo remove hardcoded border + jMenuItem.setBorder(BorderFactory.createEmptyBorder(1, 4, 2, 4)); + assignShortcut(jMenuItem, item); + jMenuItem.setMaximumSize(new Dimension(jMenuItem.getPreferredSize().width, + jMenuItem.getMaximumSize().height)); + assignCommand(jMenuItem, item); + menuBar.add(jMenuItem); + } + } + + private void assignCommand(final JMenuItem jMenuItem, MenuItem item) { + final MenuCommand command = new MenuCommand(item); + jMenuItem.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + command.execute(); + + StringBuilder menuPath = new StringBuilder(); + formatMenuPath(item, menuPath); + userActionsLog.trace("Action \"{}\" was performed using menu item {}", command.getCommandDescription(), menuPath.toString()); + } + }); + } + + private void createSubMenu(JMenu jMenu, MenuItem item) { + List itemChildren = new ArrayList<>(item.getChildren()); + CollectionUtils.filter(itemChildren, object -> object.isPermitted(userSession)); + + List items = new ArrayList<>(); + + // prepare menu items + for (MenuItem child : itemChildren) { + if (child.getChildren().isEmpty()) { + if (child.isSeparator()) { + items.add(new MenuItemContainer()); + } else { + JMenuItem jMenuItem = new JMenuItem(menuConfig.getItemCaption(child.getId())); + jMenuItem.setName(child.getId()); + assignCommand(jMenuItem, child); + assignShortcut(jMenuItem, child); + items.add(new MenuItemContainer(jMenuItem)); + } + } else { + JMenu jChildMenu = new JMenu(menuConfig.getItemCaption(child.getId())); + createSubMenu(jChildMenu, child); + if (!isMenuEmpty(jChildMenu)) { + items.add(new MenuItemContainer(jChildMenu)); + } + } + } + + // remove unnecessary separators + if (!items.isEmpty()) { + Iterator iterator = items.iterator(); + JMenuItem menuItem = getNextMenuItem(iterator); + boolean useSeparator = false; + + while (menuItem != null) { + if (useSeparator) + jMenu.addSeparator(); + + jMenu.add(menuItem); + + useSeparator = false; + menuItem = null; + + if (iterator.hasNext()) { + MenuItemContainer itemContainer = iterator.next(); + if (!itemContainer.isSeparator()) + menuItem = itemContainer.getMenuItem(); + else { + menuItem = getNextMenuItem(iterator); + useSeparator = true; + } + } + } + } + } + + private JMenuItem getNextMenuItem(Iterator iterator) { + JMenuItem item = null; + while (iterator.hasNext() && item == null) { + MenuItemContainer cMenuItem = iterator.next(); + if (!cMenuItem.isSeparator()) + item = cMenuItem.getMenuItem(); + } + return item; + } + + private static class MenuItemContainer { + private JMenuItem menuItem = null; + + private MenuItemContainer() { + } + + public MenuItemContainer(JMenuItem menuItem) { + this.menuItem = menuItem; + } + + public JMenuItem getMenuItem() { + return menuItem; + } + + public boolean isSeparator() { + return this.menuItem == null; + } + } + + private boolean isMenuEmpty(JMenu jMenu) { + return jMenu.getSubElements().length == 0; + } + + private void assignShortcut(JMenuItem jMenuItem, MenuItem item) { + if (item.getShortcut() != null) { + KeyCombination.Key key = item.getShortcut().getKey(); + KeyCombination.Modifier[] modifiers = item.getShortcut().getModifiers(); + KeyCombination combo = new KeyCombination(key, modifiers); + jMenuItem.setAccelerator(DesktopComponentsHelper.convertKeyCombination(combo)); + } + } + + private void formatMenuPath(MenuItem menuItem, StringBuilder stringBuilder) { + if (menuItem.getParent() != null) { + formatMenuPath(menuItem.getParent(), stringBuilder); + } + + stringBuilder.append(menuItem.getId()); + stringBuilder.append("->"); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/WindowBreadCrumbs.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/WindowBreadCrumbs.java index 2281c69fb8..bb36b9fde0 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/WindowBreadCrumbs.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/WindowBreadCrumbs.java @@ -1,120 +1,120 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys; - -import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; -import com.haulmont.cuba.gui.components.Window; -import org.apache.commons.lang.StringUtils; -import org.jdesktop.swingx.JXHyperlink; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.Serializable; -import java.util.*; - -public class WindowBreadCrumbs extends JPanel { - - public interface Listener extends Serializable { - void windowClick(Window window); - } - - protected LinkedList windows = new LinkedList<>(); - protected Map btn2win = new HashMap<>(); - - protected Set listeners = new HashSet<>(); - - public WindowBreadCrumbs() { - FlowLayout layout = new FlowLayout(FlowLayout.LEFT, 5, 5); - setLayout(layout); - setBorder(BorderFactory.createLineBorder(Color.gray)); - setVisible(false); - } - - public Window getCurrentWindow() { - if (windows.isEmpty()) - return null; - else - return windows.getLast(); - } - - public void addWindow(Window window) { - windows.add(window); - update(); - if (windows.size() > 1) - setVisible(true); - } - - public void removeWindow() { - if (!windows.isEmpty()) { - windows.removeLast(); - update(); - } - if (windows.size() <= 1) - setVisible(false); - } - - public void addListener(Listener listener) { - listeners.add(listener); - } - - public void removeListener(Listener listener) { - listeners.remove(listener); - } - - public void clearListeners() { - listeners.clear(); - } - - private void fireListeners(Window window) { - for (Listener listener : listeners) { - listener.windowClick(window); - } - } - - public void update() { - removeAll(); - btn2win.clear(); - for (Iterator it = windows.iterator(); it.hasNext();) { - Window window = it.next(); - JButton button = new JXHyperlink(); - button.setFocusable(false); - button.setText(StringUtils.trimToEmpty(window.getCaption())); - button.addActionListener(new ValidationAwareActionListener() { - @Override - public void actionPerformedAfterValidation(ActionEvent e) { - JButton btn = (JButton) e.getSource(); - Window win = btn2win.get(btn); - if (win != null) { - fireListeners(win); - } - } - }); - - btn2win.put(button, window); - - if (it.hasNext()) { - add(button); - JLabel separatorLab = new JLabel(">"); - add(separatorLab); - } else { - add(new JLabel(window.getCaption())); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys; + +import com.haulmont.cuba.desktop.sys.validation.ValidationAwareActionListener; +import com.haulmont.cuba.gui.components.Window; +import org.apache.commons.lang.StringUtils; +import org.jdesktop.swingx.JXHyperlink; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.Serializable; +import java.util.*; + +public class WindowBreadCrumbs extends JPanel { + + public interface Listener extends Serializable { + void windowClick(Window window); + } + + protected LinkedList windows = new LinkedList<>(); + protected Map btn2win = new HashMap<>(); + + protected Set listeners = new HashSet<>(); + + public WindowBreadCrumbs() { + FlowLayout layout = new FlowLayout(FlowLayout.LEFT, 5, 5); + setLayout(layout); + setBorder(BorderFactory.createLineBorder(Color.gray)); + setVisible(false); + } + + public Window getCurrentWindow() { + if (windows.isEmpty()) + return null; + else + return windows.getLast(); + } + + public void addWindow(Window window) { + windows.add(window); + update(); + if (windows.size() > 1) + setVisible(true); + } + + public void removeWindow() { + if (!windows.isEmpty()) { + windows.removeLast(); + update(); + } + if (windows.size() <= 1) + setVisible(false); + } + + public void addListener(Listener listener) { + listeners.add(listener); + } + + public void removeListener(Listener listener) { + listeners.remove(listener); + } + + public void clearListeners() { + listeners.clear(); + } + + private void fireListeners(Window window) { + for (Listener listener : listeners) { + listener.windowClick(window); + } + } + + public void update() { + removeAll(); + btn2win.clear(); + for (Iterator it = windows.iterator(); it.hasNext();) { + Window window = it.next(); + JButton button = new JXHyperlink(); + button.setFocusable(false); + button.setText(StringUtils.trimToEmpty(window.getCaption())); + button.addActionListener(new ValidationAwareActionListener() { + @Override + public void actionPerformedAfterValidation(ActionEvent e) { + JButton btn = (JButton) e.getSource(); + Window win = btn2win.get(btn); + if (win != null) { + fireListeners(win); + } + } + }); + + btn2win.put(button, window); + + if (it.hasNext()) { + add(button); + JLabel separatorLab = new JLabel(">"); + add(separatorLab); + } else { + add(new JLabel(window.getCaption())); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/BoxLayoutAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/BoxLayoutAdapter.java index 5016da73b2..4d6443ee1f 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/BoxLayoutAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/BoxLayoutAdapter.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import java.awt.*; - -public abstract class BoxLayoutAdapter extends LayoutAdapter { - - public abstract Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component); - - public enum FlowDirection { X, Y } - - protected FlowDirection direction = FlowDirection.X; - - protected Component expandedComponent; - - // if true, should let children components gain more size than minimal. If false, then shrink them to minimal - protected boolean expandLayout = false; - - public static BoxLayoutAdapter create(JComponent container) { - MigBoxLayoutAdapter layoutAdapter = new MigBoxLayoutAdapter(container); - container.setLayout(layoutAdapter.getLayout()); - return layoutAdapter; - } - - public static BoxLayoutAdapter create(LayoutManager layout, JComponent container) { - if (layout instanceof MigLayout) { - MigBoxLayoutAdapter layoutAdapter = new MigBoxLayoutAdapter((MigLayout) layout, container); - container.setLayout(layoutAdapter.getLayout()); - return layoutAdapter; - } else { - throw new UnsupportedOperationException("Unsupported layout manager: " + layout); - } - } - - public void expand(Component component) { - expand(component, null, null); - } - - public void resetExpanded() { - expandedComponent = null; - update(); - } - - public void expand(Component component, String height, String width) { - expandedComponent = component; - update(); - } - - public void setFlowDirection(BoxLayoutAdapter.FlowDirection direction) { - this.direction = direction; - update(); - } - - public FlowDirection getFlowDirection() { - return direction; - } - - public abstract void updateConstraints(JComponent component, Object constraints); - - public boolean isExpandLayout() { - return expandLayout; - } - - public void setExpandLayout(boolean expandLayout) { - this.expandLayout = expandLayout; - update(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import net.miginfocom.swing.MigLayout; + +import javax.swing.*; +import java.awt.*; + +public abstract class BoxLayoutAdapter extends LayoutAdapter { + + public abstract Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component); + + public enum FlowDirection { X, Y } + + protected FlowDirection direction = FlowDirection.X; + + protected Component expandedComponent; + + // if true, should let children components gain more size than minimal. If false, then shrink them to minimal + protected boolean expandLayout = false; + + public static BoxLayoutAdapter create(JComponent container) { + MigBoxLayoutAdapter layoutAdapter = new MigBoxLayoutAdapter(container); + container.setLayout(layoutAdapter.getLayout()); + return layoutAdapter; + } + + public static BoxLayoutAdapter create(LayoutManager layout, JComponent container) { + if (layout instanceof MigLayout) { + MigBoxLayoutAdapter layoutAdapter = new MigBoxLayoutAdapter((MigLayout) layout, container); + container.setLayout(layoutAdapter.getLayout()); + return layoutAdapter; + } else { + throw new UnsupportedOperationException("Unsupported layout manager: " + layout); + } + } + + public void expand(Component component) { + expand(component, null, null); + } + + public void resetExpanded() { + expandedComponent = null; + update(); + } + + public void expand(Component component, String height, String width) { + expandedComponent = component; + update(); + } + + public void setFlowDirection(BoxLayoutAdapter.FlowDirection direction) { + this.direction = direction; + update(); + } + + public FlowDirection getFlowDirection() { + return direction; + } + + public abstract void updateConstraints(JComponent component, Object constraints); + + public boolean isExpandLayout() { + return expandLayout; + } + + public void setExpandLayout(boolean expandLayout) { + this.expandLayout = expandLayout; + update(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/GridLayoutAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/GridLayoutAdapter.java index adb1680310..cbc64c5d53 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/GridLayoutAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/GridLayoutAdapter.java @@ -1,100 +1,100 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import java.awt.*; -import java.util.Arrays; - -public abstract class GridLayoutAdapter extends LayoutAdapter { - - protected int rowCount; - protected int colCount; - - protected float[] columnRatio; - protected float[] rowRatio; - - public static GridLayoutAdapter create(JComponent container) { - MigGridLayoutAdapter layoutAdapter = new MigGridLayoutAdapter(container); - container.setLayout(layoutAdapter.getLayout()); - return layoutAdapter; - } - - public static GridLayoutAdapter create(LayoutManager layout, JComponent container) { - if (layout instanceof MigLayout) { - MigGridLayoutAdapter layoutAdapter = new MigGridLayoutAdapter((MigLayout) layout, container); - container.setLayout(layoutAdapter.getLayout()); - return layoutAdapter; - } - else - throw new UnsupportedOperationException("Unsupported layout manager: " + layout); - } - - public int getRows() { - return rowCount; - } - - public void setRows(int rows) { - rowCount = rows; - - rowRatio = new float[rows]; - Arrays.fill(rowRatio, 1.0f); - - update(); - } - - public int getColumns() { - return colCount; - } - - public void setColumns(int columns) { - colCount = columns; - columnRatio = new float[columns]; - //Arrays.fill(columnRatio, 1.0f); // 0.0 by default - - update(); - } - - public abstract Object getConstraints( - com.haulmont.cuba.gui.components.Component component, int col, int row, int col2, int row2); - - public abstract Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component, - int col, int row, int col2, int row2 - ); - - public abstract void updateConstraints(JComponent component, Object constraints); - - public void setColumnExpandRatio(int col, float ratio) { - columnRatio[col] = ratio; - update(); - } - - public float getColumnExpandRatio(int col) { - return columnRatio[col]; - } - - public float getRowExpandRatio(int col) { - return rowRatio[col]; - } - - public void setRowExpandRatio(int col, float ratio) { - rowRatio[col] = ratio; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import net.miginfocom.swing.MigLayout; + +import javax.swing.*; +import java.awt.*; +import java.util.Arrays; + +public abstract class GridLayoutAdapter extends LayoutAdapter { + + protected int rowCount; + protected int colCount; + + protected float[] columnRatio; + protected float[] rowRatio; + + public static GridLayoutAdapter create(JComponent container) { + MigGridLayoutAdapter layoutAdapter = new MigGridLayoutAdapter(container); + container.setLayout(layoutAdapter.getLayout()); + return layoutAdapter; + } + + public static GridLayoutAdapter create(LayoutManager layout, JComponent container) { + if (layout instanceof MigLayout) { + MigGridLayoutAdapter layoutAdapter = new MigGridLayoutAdapter((MigLayout) layout, container); + container.setLayout(layoutAdapter.getLayout()); + return layoutAdapter; + } + else + throw new UnsupportedOperationException("Unsupported layout manager: " + layout); + } + + public int getRows() { + return rowCount; + } + + public void setRows(int rows) { + rowCount = rows; + + rowRatio = new float[rows]; + Arrays.fill(rowRatio, 1.0f); + + update(); + } + + public int getColumns() { + return colCount; + } + + public void setColumns(int columns) { + colCount = columns; + columnRatio = new float[columns]; + //Arrays.fill(columnRatio, 1.0f); // 0.0 by default + + update(); + } + + public abstract Object getConstraints( + com.haulmont.cuba.gui.components.Component component, int col, int row, int col2, int row2); + + public abstract Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component, + int col, int row, int col2, int row2 + ); + + public abstract void updateConstraints(JComponent component, Object constraints); + + public void setColumnExpandRatio(int col, float ratio) { + columnRatio[col] = ratio; + update(); + } + + public float getColumnExpandRatio(int col) { + return columnRatio[col]; + } + + public float getRowExpandRatio(int col) { + return rowRatio[col]; + } + + public void setRowExpandRatio(int col, float ratio) { + rowRatio[col] = ratio; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/LayoutAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/LayoutAdapter.java index 93c494e216..ef96823bf1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/LayoutAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/LayoutAdapter.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import com.haulmont.cuba.gui.components.MarginInfo; - -import java.awt.*; - -public abstract class LayoutAdapter - implements - com.haulmont.cuba.gui.components.Component.Margin, - com.haulmont.cuba.gui.components.Component.Spacing -{ - - protected boolean[] margins = new boolean[4]; - protected boolean spacing; - - public static boolean isDebug() { - String property = System.getProperty("cuba.desktop.debugLayouts"); - return Boolean.valueOf(property); - } - - public abstract LayoutManager getLayout(); - - protected abstract void update(); - - @Override - public void setMargin(MarginInfo marginInfo) { - margins[0] = marginInfo.hasTop(); - margins[1] = marginInfo.hasRight(); - margins[2] = marginInfo.hasBottom(); - margins[3] = marginInfo.hasLeft(); - update(); - } - - @Override - public MarginInfo getMargin() { - return new MarginInfo(margins[0], margins[1], margins[2], margins[3]); - } - - @Override - public void setSpacing(boolean enabled) { - spacing = enabled; - update(); - } - - @Override - public boolean getSpacing() { - return spacing; - } - - /* - * Get a constraints for java.awt.Container.add(java.awt.Component, Object constraints) method - */ - public Object getConstraints(com.haulmont.cuba.gui.components.Component component) { - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import com.haulmont.cuba.gui.components.MarginInfo; + +import java.awt.*; + +public abstract class LayoutAdapter + implements + com.haulmont.cuba.gui.components.Component.Margin, + com.haulmont.cuba.gui.components.Component.Spacing +{ + + protected boolean[] margins = new boolean[4]; + protected boolean spacing; + + public static boolean isDebug() { + String property = System.getProperty("cuba.desktop.debugLayouts"); + return Boolean.valueOf(property); + } + + public abstract LayoutManager getLayout(); + + protected abstract void update(); + + @Override + public void setMargin(MarginInfo marginInfo) { + margins[0] = marginInfo.hasTop(); + margins[1] = marginInfo.hasRight(); + margins[2] = marginInfo.hasBottom(); + margins[3] = marginInfo.hasLeft(); + update(); + } + + @Override + public MarginInfo getMargin() { + return new MarginInfo(margins[0], margins[1], margins[2], margins[3]); + } + + @Override + public void setSpacing(boolean enabled) { + spacing = enabled; + update(); + } + + @Override + public boolean getSpacing() { + return spacing; + } + + /* + * Get a constraints for java.awt.Container.add(java.awt.Component, Object constraints) method + */ + public Object getConstraints(com.haulmont.cuba.gui.components.Component component) { + return null; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigBoxLayoutAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigBoxLayoutAdapter.java index ba6b22b2f4..3a48c730f2 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigBoxLayoutAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigBoxLayoutAdapter.java @@ -1,156 +1,156 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import net.miginfocom.layout.AC; -import net.miginfocom.layout.CC; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang.StringUtils; - -import javax.swing.*; -import java.awt.*; - -public class MigBoxLayoutAdapter extends BoxLayoutAdapter { - - protected MigLayout layout; - protected JComponent container; - - public MigBoxLayoutAdapter(JComponent container) { - this(new MigLayout(), container); - } - - public MigBoxLayoutAdapter(MigLayout layout, JComponent container) { - this.layout = layout; - this.container = container; - update(); - } - - @Override - public LayoutManager getLayout() { - return layout; - } - - @Override - protected void update() { - updateLayoutConstraints(false); - } - - private void updateLayoutConstraints(boolean resetExpanded) { - LC lc = new LC(); - lc.hideMode(2); // Invisible components will not participate in the layout at all and it will for instance not take up a grid cell - lc.fill(); // always give all space to components, otherwise align doesn't work - AC rowConstr = new AC(); - AC colConstr = new AC(); - - if (direction.equals(FlowDirection.X)) { - rowConstr.align("top"); - lc.flowX(); - if (expandedComponent != null || resetExpanded) { - adjustExpanding(lc, colConstr); - } - } else { - lc.flowY(); - if (expandedComponent != null || resetExpanded) { - adjustExpanding(lc, rowConstr); - } - } - - lc.setInsets(MigLayoutHelper.makeInsets(margins)); - - if (!spacing) { - if (direction.equals(FlowDirection.X)) { - lc.gridGapX("0"); - } else { - lc.gridGapY("0"); - } - } - - if (isDebug()) - lc.debug(1000); - - layout.setLayoutConstraints(lc); - layout.setRowConstraints(rowConstr); - layout.setColumnConstraints(colConstr); - } - - @Override - public void resetExpanded() { - expandedComponent = null; - updateLayoutConstraints(true); - } - - private void adjustExpanding(LC lc, AC ac) { - Component[] components = container.getComponents(); - for (int i = 0; i < components.length; i++) { - if (expandedComponent == null - || expandedComponent == components[i]) { - ac.fill(i); - } else { - ac.size("min!", i); - } - } - lc.fill(); - } - - @Override - public Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component) { - CC cc = new CC(); - cc.split(2); - cc.width("min!"); - cc.height("min!"); - MigLayoutHelper.applyAlignment(cc, component.getAlignment()); - return cc; - } - - @Override - public void expand(Component component, String height, String width) { - super.expand(component, height, width); - - Object cc = layout.getComponentConstraints(component); - if (cc instanceof CC) { - if (direction == null || direction == BoxLayoutAdapter.FlowDirection.X - && (StringUtils.isEmpty(height) || "-1px".equals(height) || height.endsWith("%"))) { - MigLayoutHelper.applyWidth((CC) cc, 100, com.haulmont.cuba.gui.components.Component.UNITS_PERCENTAGE, true); - } - if (direction == null || direction == BoxLayoutAdapter.FlowDirection.Y - && (StringUtils.isEmpty(width) || "-1px".equals(width) || width.endsWith("%"))) { - MigLayoutHelper.applyHeight((CC) cc, 100, com.haulmont.cuba.gui.components.Component.UNITS_PERCENTAGE, true); - } - - } else - cc = MigLayoutHelper.getExpandConstraints(width, height, direction); - layout.setComponentConstraints(component, cc); - } - - @Override - public void updateConstraints(JComponent component, Object constraints) { - if (component == expandedComponent) { - expand(component); - } else { - layout.setComponentConstraints(component, constraints); - update(); - } - } - - @Override - public CC getConstraints(com.haulmont.cuba.gui.components.Component component) { - CC constraints = MigLayoutHelper.getConstraints(component); - return constraints; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import net.miginfocom.layout.AC; +import net.miginfocom.layout.CC; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang.StringUtils; + +import javax.swing.*; +import java.awt.*; + +public class MigBoxLayoutAdapter extends BoxLayoutAdapter { + + protected MigLayout layout; + protected JComponent container; + + public MigBoxLayoutAdapter(JComponent container) { + this(new MigLayout(), container); + } + + public MigBoxLayoutAdapter(MigLayout layout, JComponent container) { + this.layout = layout; + this.container = container; + update(); + } + + @Override + public LayoutManager getLayout() { + return layout; + } + + @Override + protected void update() { + updateLayoutConstraints(false); + } + + private void updateLayoutConstraints(boolean resetExpanded) { + LC lc = new LC(); + lc.hideMode(2); // Invisible components will not participate in the layout at all and it will for instance not take up a grid cell + lc.fill(); // always give all space to components, otherwise align doesn't work + AC rowConstr = new AC(); + AC colConstr = new AC(); + + if (direction.equals(FlowDirection.X)) { + rowConstr.align("top"); + lc.flowX(); + if (expandedComponent != null || resetExpanded) { + adjustExpanding(lc, colConstr); + } + } else { + lc.flowY(); + if (expandedComponent != null || resetExpanded) { + adjustExpanding(lc, rowConstr); + } + } + + lc.setInsets(MigLayoutHelper.makeInsets(margins)); + + if (!spacing) { + if (direction.equals(FlowDirection.X)) { + lc.gridGapX("0"); + } else { + lc.gridGapY("0"); + } + } + + if (isDebug()) + lc.debug(1000); + + layout.setLayoutConstraints(lc); + layout.setRowConstraints(rowConstr); + layout.setColumnConstraints(colConstr); + } + + @Override + public void resetExpanded() { + expandedComponent = null; + updateLayoutConstraints(true); + } + + private void adjustExpanding(LC lc, AC ac) { + Component[] components = container.getComponents(); + for (int i = 0; i < components.length; i++) { + if (expandedComponent == null + || expandedComponent == components[i]) { + ac.fill(i); + } else { + ac.size("min!", i); + } + } + lc.fill(); + } + + @Override + public Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component) { + CC cc = new CC(); + cc.split(2); + cc.width("min!"); + cc.height("min!"); + MigLayoutHelper.applyAlignment(cc, component.getAlignment()); + return cc; + } + + @Override + public void expand(Component component, String height, String width) { + super.expand(component, height, width); + + Object cc = layout.getComponentConstraints(component); + if (cc instanceof CC) { + if (direction == null || direction == BoxLayoutAdapter.FlowDirection.X + && (StringUtils.isEmpty(height) || "-1px".equals(height) || height.endsWith("%"))) { + MigLayoutHelper.applyWidth((CC) cc, 100, com.haulmont.cuba.gui.components.Component.UNITS_PERCENTAGE, true); + } + if (direction == null || direction == BoxLayoutAdapter.FlowDirection.Y + && (StringUtils.isEmpty(width) || "-1px".equals(width) || width.endsWith("%"))) { + MigLayoutHelper.applyHeight((CC) cc, 100, com.haulmont.cuba.gui.components.Component.UNITS_PERCENTAGE, true); + } + + } else + cc = MigLayoutHelper.getExpandConstraints(width, height, direction); + layout.setComponentConstraints(component, cc); + } + + @Override + public void updateConstraints(JComponent component, Object constraints) { + if (component == expandedComponent) { + expand(component); + } else { + layout.setComponentConstraints(component, constraints); + update(); + } + } + + @Override + public CC getConstraints(com.haulmont.cuba.gui.components.Component component) { + CC constraints = MigLayoutHelper.getConstraints(component); + return constraints; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigGridLayoutAdapter.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigGridLayoutAdapter.java index 15b734a0d6..e2f92524f5 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigGridLayoutAdapter.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigGridLayoutAdapter.java @@ -1,144 +1,144 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import net.miginfocom.layout.AC; -import net.miginfocom.layout.CC; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import java.awt.*; - -public class MigGridLayoutAdapter extends GridLayoutAdapter { - - protected MigLayout layout; - protected JComponent container; - - public MigGridLayoutAdapter(JComponent container) { - this(new MigLayout(), container); - } - - public MigGridLayoutAdapter(MigLayout layout, JComponent container) { - this.layout = layout; - this.container = container; - update(); - } - - @Override - public LayoutManager getLayout() { - return layout; - } - - @Override - protected void update() { - LC lc = new LC(); - lc.setWrapAfter(getColumns()); - lc.hideMode(2); // The size of an invisible component will be set to 0, 0 and the gaps will also be set to 0 around it. - lc.fill(); - - lc.setInsets(MigLayoutHelper.makeInsets(margins)); - - if (!spacing) { - lc.gridGap("0", "0"); - } - - if (isDebug()) - lc.debug(1000); - - layout.setLayoutConstraints(lc); - - AC rowConstr = new AC(); - rowConstr.align("top"); // left-top align by default - // todo add them when they will be needed. Now seem to bug a little - /*for (int i = 0; i < rowCount; i++) { - rowConstr.grow(rowRatio[i], i); - }*/ - layout.setRowConstraints(rowConstr); - - AC colConstr = new AC(); - for (int i = 0; i < colCount; i++) { - float ratio = columnRatio[i]; - colConstr.grow(ratio, i); - colConstr.shrink(ratio != 0 ? (float) Math.sqrt(1.0f / ratio) : 100.0f, i); - } - layout.setColumnConstraints(colConstr); - } - - @Override - public CC getConstraints(com.haulmont.cuba.gui.components.Component component) { - CC defaultContraints = MigLayoutHelper.getConstraints(component); - - JComponent composition = DesktopComponentsHelper.getComposition(component); - if (composition.getParent() == container) { - // fill up span x span y - if (layout.getComponentConstraints(composition) instanceof CC) { - CC componentConstraints = (CC) layout.getComponentConstraints(composition); - defaultContraints.setCellX(componentConstraints.getCellX()); - defaultContraints.setCellY(componentConstraints.getCellY()); - defaultContraints.setSpanX(componentConstraints.getSpanX()); - defaultContraints.setSpanY(componentConstraints.getSpanY()); - } - } - - return defaultContraints; - } - - @Override - public CC getConstraints(com.haulmont.cuba.gui.components.Component component, int col, int row, int col2, int row2) { - int spanX = col2 - col + 1; - int spanY = row2 - row + 1; - - CC constraints = MigLayoutHelper.getConstraints(component); - constraints.cell(col, row, spanX, spanY); - - return constraints; - } - - @Override - public Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component, - int col, int row, int col2, int row2) { - CC constraints = new CC(); - constraints.cell(col, row); - constraints.split(2); - constraints.flowY(); - constraints.width("min!"); - constraints.height("min!"); - MigLayoutHelper.applyAlignment(constraints, component.getAlignment()); - return constraints; - } - - @Override - public void updateConstraints(JComponent component, Object constraints) { - // todo delete, evidently no needed - /*if (layout.isManagingComponent(component) - && layout.getComponentConstraints(component) instanceof CC - && constraints instanceof CC) { - // trying to keep the same cell and row for component - CC current = (CC) layout.getComponentConstraints(component); - int col = current.getCellX(); - int row = current.getCellY(); - int spanX = current.getSpanX(); - int spanY = current.getSpanY(); - - ((CC) constraints).cell(col, row, spanX, spanY); - }*/ - layout.setComponentConstraints(component, constraints); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import net.miginfocom.layout.AC; +import net.miginfocom.layout.CC; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; + +import javax.swing.*; +import java.awt.*; + +public class MigGridLayoutAdapter extends GridLayoutAdapter { + + protected MigLayout layout; + protected JComponent container; + + public MigGridLayoutAdapter(JComponent container) { + this(new MigLayout(), container); + } + + public MigGridLayoutAdapter(MigLayout layout, JComponent container) { + this.layout = layout; + this.container = container; + update(); + } + + @Override + public LayoutManager getLayout() { + return layout; + } + + @Override + protected void update() { + LC lc = new LC(); + lc.setWrapAfter(getColumns()); + lc.hideMode(2); // The size of an invisible component will be set to 0, 0 and the gaps will also be set to 0 around it. + lc.fill(); + + lc.setInsets(MigLayoutHelper.makeInsets(margins)); + + if (!spacing) { + lc.gridGap("0", "0"); + } + + if (isDebug()) + lc.debug(1000); + + layout.setLayoutConstraints(lc); + + AC rowConstr = new AC(); + rowConstr.align("top"); // left-top align by default + // todo add them when they will be needed. Now seem to bug a little + /*for (int i = 0; i < rowCount; i++) { + rowConstr.grow(rowRatio[i], i); + }*/ + layout.setRowConstraints(rowConstr); + + AC colConstr = new AC(); + for (int i = 0; i < colCount; i++) { + float ratio = columnRatio[i]; + colConstr.grow(ratio, i); + colConstr.shrink(ratio != 0 ? (float) Math.sqrt(1.0f / ratio) : 100.0f, i); + } + layout.setColumnConstraints(colConstr); + } + + @Override + public CC getConstraints(com.haulmont.cuba.gui.components.Component component) { + CC defaultContraints = MigLayoutHelper.getConstraints(component); + + JComponent composition = DesktopComponentsHelper.getComposition(component); + if (composition.getParent() == container) { + // fill up span x span y + if (layout.getComponentConstraints(composition) instanceof CC) { + CC componentConstraints = (CC) layout.getComponentConstraints(composition); + defaultContraints.setCellX(componentConstraints.getCellX()); + defaultContraints.setCellY(componentConstraints.getCellY()); + defaultContraints.setSpanX(componentConstraints.getSpanX()); + defaultContraints.setSpanY(componentConstraints.getSpanY()); + } + } + + return defaultContraints; + } + + @Override + public CC getConstraints(com.haulmont.cuba.gui.components.Component component, int col, int row, int col2, int row2) { + int spanX = col2 - col + 1; + int spanY = row2 - row + 1; + + CC constraints = MigLayoutHelper.getConstraints(component); + constraints.cell(col, row, spanX, spanY); + + return constraints; + } + + @Override + public Object getCaptionConstraints(com.haulmont.cuba.gui.components.Component component, + int col, int row, int col2, int row2) { + CC constraints = new CC(); + constraints.cell(col, row); + constraints.split(2); + constraints.flowY(); + constraints.width("min!"); + constraints.height("min!"); + MigLayoutHelper.applyAlignment(constraints, component.getAlignment()); + return constraints; + } + + @Override + public void updateConstraints(JComponent component, Object constraints) { + // todo delete, evidently no needed + /*if (layout.isManagingComponent(component) + && layout.getComponentConstraints(component) instanceof CC + && constraints instanceof CC) { + // trying to keep the same cell and row for component + CC current = (CC) layout.getComponentConstraints(component); + int col = current.getCellX(); + int row = current.getCellY(); + int spanX = current.getSpanX(); + int spanY = current.getSpanY(); + + ((CC) constraints).cell(col, row, spanX, spanY); + }*/ + layout.setComponentConstraints(component, constraints); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigLayoutHelper.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigLayoutHelper.java index 1efaea3549..8918e41331 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigLayoutHelper.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/layout/MigLayoutHelper.java @@ -1,163 +1,163 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.layout; - -import com.haulmont.cuba.desktop.gui.components.AutoExpanding; -import com.haulmont.cuba.gui.components.AbstractFrame; -import com.haulmont.cuba.gui.components.Component; -import net.miginfocom.layout.CC; -import net.miginfocom.layout.UnitValue; -import org.apache.commons.lang.StringUtils; - -public class MigLayoutHelper { - - public static UnitValue[] makeInsets(boolean[] margins) { - UnitValue[] unitValues = new UnitValue[4]; - - // at cuba it's top, right, bottom, left - // at MigLayout it's top, left, bottom, right - unitValues[0] = makeInsetValue(margins[0]); - unitValues[1] = makeInsetValue(margins[3]); - unitValues[2] = makeInsetValue(margins[2]); - unitValues[3] = makeInsetValue(margins[1]); - - return unitValues; - } - - private static UnitValue makeInsetValue(boolean margin) { - return margin ? null : new UnitValue(0); - } - - public static CC getExpandConstraints(String width, String height, BoxLayoutAdapter.FlowDirection direction) { - CC cc = new CC(); - - if (direction == null || direction == BoxLayoutAdapter.FlowDirection.X - && (StringUtils.isEmpty(height) || "-1px".equals(height) || height.endsWith("%"))) { - applyWidth(cc, 100, Component.UNITS_PERCENTAGE, true); - } - if (direction == null || direction == BoxLayoutAdapter.FlowDirection.Y - && (StringUtils.isEmpty(width) || "-1px".equals(width) || width.endsWith("%"))) { - applyHeight(cc, 100, Component.UNITS_PERCENTAGE, true); - } - - return cc; - } - - public static CC getConstraints(Component component) { - boolean expandX = false; - boolean expandY = false; - - // for latter comparing with AutoExpanding - if (component instanceof AbstractFrame) { - component = (Component) ((AbstractFrame) component).getComponent(); - } - - if (component instanceof AutoExpanding) { - expandX = ((AutoExpanding) component).expandsWidth(); - expandY = ((AutoExpanding) component).expandsHeight(); - } - - int width = (int) component.getWidth(); - int widthUnits = component.getWidthUnits(); - - int height = (int) component.getHeight(); - int heightUnits = component.getHeightUnits(); - - CC cc = new CC(); - - applyWidth(cc, width, widthUnits, expandX); - applyHeight(cc, height, heightUnits, expandY); - - applyAlignment(cc, component.getAlignment()); - return cc; - } - - public static void applyAlignment(CC cc, Component.Alignment align) { - if (align == null) { - align = Component.Alignment.TOP_LEFT; // same as for web - } - - switch (align) { - case TOP_RIGHT: - cc.alignX("right").alignY("top"); - break; - case TOP_LEFT: - cc.alignX("left").alignY("top"); - break; - case TOP_CENTER: - cc.alignX("50%").alignY("top"); - break; - case MIDDLE_RIGHT: - cc.alignX("right").alignY("50%"); - break; - case MIDDLE_LEFT: - cc.alignX("left").alignY("50%"); - break; - case MIDDLE_CENTER: - cc.alignX("50%").alignY("50%"); - break; - case BOTTOM_RIGHT: - cc.alignX("right").alignY("bottom"); - break; - case BOTTOM_LEFT: - cc.alignX("left").alignY("bottom"); - break; - case BOTTOM_CENTER: - cc.alignX("50%").alignY("bottom"); - break; - } - } - - public static void applyHeight(CC constraints, int height, int heightUnits, boolean expand) { - if (height == -1) { // own size - constraints.growY(0.0f); - } else if (heightUnits == Component.UNITS_PERCENTAGE) { - constraints.height(height + "%"); - } else if (height != 0 && heightUnits == Component.UNITS_PIXELS) { - constraints.growY(0.0f); - constraints.height(height + "!"); // min, pref, max size as specified - } else { - if (expand) { - constraints.growY(); - constraints.growPrioY(99); // lower grow priority - constraints.height("100%"); // preffered size to full container - } else { - constraints.growY(0.0f); - } - } - } - - public static void applyWidth(CC constraints, int width, int widthUnits, boolean expand) { - if (width == -1) { // own size - constraints.growX(0); - } else if (widthUnits == Component.UNITS_PERCENTAGE) { - constraints.width(width + "%"); - } else if (width != 0 && widthUnits == Component.UNITS_PIXELS) { - constraints.growX(0); - constraints.width(width + "!"); // min, pref, max size as specified - } else { - if (expand) { - constraints.growX(); - constraints.growPrioX(99); // lower grow priority - constraints.width("100%"); // preffered size to full container - } else { - constraints.growX(0); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.layout; + +import com.haulmont.cuba.desktop.gui.components.AutoExpanding; +import com.haulmont.cuba.gui.components.AbstractFrame; +import com.haulmont.cuba.gui.components.Component; +import net.miginfocom.layout.CC; +import net.miginfocom.layout.UnitValue; +import org.apache.commons.lang.StringUtils; + +public class MigLayoutHelper { + + public static UnitValue[] makeInsets(boolean[] margins) { + UnitValue[] unitValues = new UnitValue[4]; + + // at cuba it's top, right, bottom, left + // at MigLayout it's top, left, bottom, right + unitValues[0] = makeInsetValue(margins[0]); + unitValues[1] = makeInsetValue(margins[3]); + unitValues[2] = makeInsetValue(margins[2]); + unitValues[3] = makeInsetValue(margins[1]); + + return unitValues; + } + + private static UnitValue makeInsetValue(boolean margin) { + return margin ? null : new UnitValue(0); + } + + public static CC getExpandConstraints(String width, String height, BoxLayoutAdapter.FlowDirection direction) { + CC cc = new CC(); + + if (direction == null || direction == BoxLayoutAdapter.FlowDirection.X + && (StringUtils.isEmpty(height) || "-1px".equals(height) || height.endsWith("%"))) { + applyWidth(cc, 100, Component.UNITS_PERCENTAGE, true); + } + if (direction == null || direction == BoxLayoutAdapter.FlowDirection.Y + && (StringUtils.isEmpty(width) || "-1px".equals(width) || width.endsWith("%"))) { + applyHeight(cc, 100, Component.UNITS_PERCENTAGE, true); + } + + return cc; + } + + public static CC getConstraints(Component component) { + boolean expandX = false; + boolean expandY = false; + + // for latter comparing with AutoExpanding + if (component instanceof AbstractFrame) { + component = (Component) ((AbstractFrame) component).getComponent(); + } + + if (component instanceof AutoExpanding) { + expandX = ((AutoExpanding) component).expandsWidth(); + expandY = ((AutoExpanding) component).expandsHeight(); + } + + int width = (int) component.getWidth(); + int widthUnits = component.getWidthUnits(); + + int height = (int) component.getHeight(); + int heightUnits = component.getHeightUnits(); + + CC cc = new CC(); + + applyWidth(cc, width, widthUnits, expandX); + applyHeight(cc, height, heightUnits, expandY); + + applyAlignment(cc, component.getAlignment()); + return cc; + } + + public static void applyAlignment(CC cc, Component.Alignment align) { + if (align == null) { + align = Component.Alignment.TOP_LEFT; // same as for web + } + + switch (align) { + case TOP_RIGHT: + cc.alignX("right").alignY("top"); + break; + case TOP_LEFT: + cc.alignX("left").alignY("top"); + break; + case TOP_CENTER: + cc.alignX("50%").alignY("top"); + break; + case MIDDLE_RIGHT: + cc.alignX("right").alignY("50%"); + break; + case MIDDLE_LEFT: + cc.alignX("left").alignY("50%"); + break; + case MIDDLE_CENTER: + cc.alignX("50%").alignY("50%"); + break; + case BOTTOM_RIGHT: + cc.alignX("right").alignY("bottom"); + break; + case BOTTOM_LEFT: + cc.alignX("left").alignY("bottom"); + break; + case BOTTOM_CENTER: + cc.alignX("50%").alignY("bottom"); + break; + } + } + + public static void applyHeight(CC constraints, int height, int heightUnits, boolean expand) { + if (height == -1) { // own size + constraints.growY(0.0f); + } else if (heightUnits == Component.UNITS_PERCENTAGE) { + constraints.height(height + "%"); + } else if (height != 0 && heightUnits == Component.UNITS_PIXELS) { + constraints.growY(0.0f); + constraints.height(height + "!"); // min, pref, max size as specified + } else { + if (expand) { + constraints.growY(); + constraints.growPrioY(99); // lower grow priority + constraints.height("100%"); // preffered size to full container + } else { + constraints.growY(0.0f); + } + } + } + + public static void applyWidth(CC constraints, int width, int widthUnits, boolean expand) { + if (width == -1) { // own size + constraints.growX(0); + } else if (widthUnits == Component.UNITS_PERCENTAGE) { + constraints.width(width + "%"); + } else if (width != 0 && widthUnits == Component.UNITS_PIXELS) { + constraints.growX(0); + constraints.width(width + "!"); // min, pref, max size as specified + } else { + if (expand) { + constraints.growX(); + constraints.growPrioX(99); // lower grow priority + constraints.width("100%"); // preffered size to full container + } else { + constraints.growX(0); + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages.properties b/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages.properties index 2b8913343b..2159d6c166 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages.properties @@ -1,26 +1,26 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -FontDialog.title=Font preferences for selected table -FontDialog.preview=Preview - -FontDialog.bold=Bold -FontDialog.italic=Italic -FontDialog.underline=Underline - -FontDialog.font=Font family +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +FontDialog.title=Font preferences for selected table +FontDialog.preview=Preview + +FontDialog.bold=Bold +FontDialog.italic=Italic +FontDialog.underline=Underline + +FontDialog.font=Font family FontDialog.size=Size \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages_ru.properties b/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages_ru.properties index e13d4cce2a..04f1034f9e 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages_ru.properties +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/messages_ru.properties @@ -1,26 +1,26 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -FontDialog.title=Настройки шрифта для выбранной таблицы -FontDialog.preview=Предпросмотр - -FontDialog.bold=Полужирный -FontDialog.italic=Курсив -FontDialog.underline=Подчёркнутый - -FontDialog.font=Шрифт +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +FontDialog.title=Настройки шрифта для выбранной таблицы +FontDialog.preview=Предпросмотр + +FontDialog.bold=Полужирный +FontDialog.italic=Курсив +FontDialog.underline=Подчёркнутый + +FontDialog.font=Шрифт FontDialog.size=Размер \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareAction.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareAction.java index 7a92479709..0ba0b7c8a1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareAction.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareAction.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.validation; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; - -public abstract class ValidationAwareAction extends AbstractAction { - @Override - public void actionPerformed(final ActionEvent e) { - final RootPaneContainer window; - if (e.getSource() instanceof Component) { - window = DesktopComponentsHelper.getSwingWindow((Component) e.getSource()); - } else { - window = null; - } - - ValidationAlertHolder.runIfValid(new Runnable() { - @Override - public void run() { - if (window == null - || window.getGlassPane() == null - || !window.getGlassPane().isVisible()) { - // check modal dialogs on the front of current component - actionPerformedAfterValidation(e); - } - } - }); - } - - public abstract void actionPerformedAfterValidation(ActionEvent e); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.validation; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; + +public abstract class ValidationAwareAction extends AbstractAction { + @Override + public void actionPerformed(final ActionEvent e) { + final RootPaneContainer window; + if (e.getSource() instanceof Component) { + window = DesktopComponentsHelper.getSwingWindow((Component) e.getSource()); + } else { + window = null; + } + + ValidationAlertHolder.runIfValid(new Runnable() { + @Override + public void run() { + if (window == null + || window.getGlassPane() == null + || !window.getGlassPane().isVisible()) { + // check modal dialogs on the front of current component + actionPerformedAfterValidation(e); + } + } + }); + } + + public abstract void actionPerformedAfterValidation(ActionEvent e); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareActionListener.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareActionListener.java index 7e7d4d4da5..93c76fad84 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareActionListener.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareActionListener.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.validation; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public abstract class ValidationAwareActionListener implements ActionListener { - - @Override - public void actionPerformed(final ActionEvent e) { - ValidationAlertHolder.runIfValid(new Runnable() { - @Override - public void run() { - actionPerformedAfterValidation(e); - } - }); - } - - public abstract void actionPerformedAfterValidation(ActionEvent e); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.validation; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public abstract class ValidationAwareActionListener implements ActionListener { + + @Override + public void actionPerformed(final ActionEvent e) { + ValidationAlertHolder.runIfValid(new Runnable() { + @Override + public void run() { + actionPerformedAfterValidation(e); + } + }); + } + + public abstract void actionPerformedAfterValidation(ActionEvent e); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareWindowClosingListener.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareWindowClosingListener.java index e04d45b18f..e7f9b0b0ac 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareWindowClosingListener.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/validation/ValidationAwareWindowClosingListener.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.validation; - -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -public abstract class ValidationAwareWindowClosingListener extends WindowAdapter { - - @Override - public void windowClosing(final WindowEvent e) { - ValidationAlertHolder.runIfValid(new Runnable() { - @Override - public void run() { - windowClosingAfterValidation(e); - } - }); - } - - public abstract void windowClosingAfterValidation(WindowEvent e); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.validation; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public abstract class ValidationAwareWindowClosingListener extends WindowAdapter { + + @Override + public void windowClosing(final WindowEvent e) { + ValidationAlertHolder.runIfValid(new Runnable() { + @Override + public void run() { + windowClosingAfterValidation(e); + } + }); + } + + public abstract void windowClosingAfterValidation(WindowEvent e); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/CollapsiblePanel.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/CollapsiblePanel.java index b47f37a2a2..39ad01aacd 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/CollapsiblePanel.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/CollapsiblePanel.java @@ -1,497 +1,497 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import com.haulmont.cuba.desktop.App; -import org.apache.commons.compress.utils.IOUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.swing.*; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * Panel with border and collapse/expand button - */ -public class CollapsiblePanel extends JPanel { - - protected static final int COLLAPSED_HEIGHT = 10; - - protected boolean expanded = true; - protected boolean collapsable = false; - - protected JComponent composition; - protected JButton titleBtn; - - protected boolean borderVisible = true; - - protected Dimension preferredSize; - - protected java.util.List postPaintActions = new LinkedList<>(); - - public interface CollapseListener extends java.util.EventListener { - - void collapsed(); - - void expanded(); - } - - private java.util.List collapseListeners; - - private Icon expandedIcon; - private Icon collapsedIcon; - - public CollapsiblePanel(JComponent composition) { - this.composition = composition; - - titleBtn = new JButton(); - titleBtn.setBorder(BorderFactory.createEmptyBorder(0, 3, 5, 3)); - titleBtn.setVerticalTextPosition(AbstractButton.CENTER); - titleBtn.setHorizontalTextPosition(AbstractButton.RIGHT); - titleBtn.setMargin(new Insets(0, 0, 3, 0)); - - titleBtn.setFont(getTitleFont()); - titleBtn.setFocusable(false); - titleBtn.setContentAreaFilled(false); - titleBtn.setVisible(false); - - titleBtn.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (isCollapsable()) - setExpanded(!isExpanded()); - } - }); - - // Add icons - loadIcons(); - refreshTitleIcon(); - - setLayout(new BorderLayout()); - add(titleBtn, BorderLayout.CENTER); - add(composition, BorderLayout.CENTER); - - setBorder(createBorderImplementation()); - - preferredSize = getPreferredSize(); - - placeTitleComponent(); - } - - private Font getTitleFont() { - UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); - if (lafDefaults.getFont("CollapsiblePanel.font") != null) { // take it from desktop theme - return lafDefaults.getFont("CollapsiblePanel.font"); - } - return lafDefaults.getFont("Panel.font"); - } - - private void refreshTitleIcon() { - if (collapsable) { - if (expanded) { - titleBtn.setIcon(expandedIcon); - } else { - titleBtn.setIcon(collapsedIcon); - } - } else { - titleBtn.setIcon(null); - } - } - - private void placeTitleComponent() { - Insets insets = getInsets(); - Rectangle containerRectangle = getBounds(); - if (borderVisible) { - Rectangle componentRectangle = ((CollapsibleTitledBorder) getBorder()).getComponentRect(containerRectangle, insets); - titleBtn.setBounds(componentRectangle); - } else { - Dimension compD = titleBtn.getPreferredSize(); - Rectangle compR = new Rectangle(20 - insets.left, 0, compD.width, compD.height); - titleBtn.setBounds(compR); - } - } - - @Override - public Dimension getPreferredSize() { - int preferredHeight = super.getPreferredSize().height; - int preferredWidth = titleBtn.getPreferredSize().width + titleBtn.getBounds().x * 2; - - if (preferredWidth > super.getPreferredSize().width) { - return new Dimension(preferredWidth, preferredHeight); - } - - return super.getPreferredSize(); - } - - protected void loadIcons() { - App app = App.getInstance(); - if (app != null) { - expandedIcon = app.getResources().getIcon("components/groupbox/item-expanded.png"); - collapsedIcon = app.getResources().getIcon("components/groupbox/item-collapsed.png"); - } else { - // fallback for unit tests - expandedIcon = readIcon("components/groupbox/item-expanded.png"); - collapsedIcon = readIcon("components/groupbox/item-collapsed.png"); - } - } - - protected ImageIcon readIcon(String iconPath) { - try { - String iconResourcePath = "/com/haulmont/cuba/desktop/res/nimbus/" + iconPath; - return new ImageIcon(IOUtils.toByteArray(getClass().getResourceAsStream(iconResourcePath))); - } catch (IOException e) { - throw new RuntimeException("Unable to read icon", e); - } - } - - protected void expandPanel() { - composition.setVisible(true); - - postPaintActions.add(new Runnable() { - @Override - public void run() { - titleBtn.setIcon(expandedIcon); - setPreferredSize(preferredSize); - updateUI(); - } - }); - - fireExpandListeners(); - - repaint(); - } - - private void collapsePanel() { - composition.setVisible(false); - - postPaintActions.add(new Runnable() { - @Override - public void run() { - int collapsedWidth = getWidth(); - int collapsedHeight = COLLAPSED_HEIGHT; - - preferredSize = getPreferredSize(); - - titleBtn.setIcon(collapsedIcon); - setPreferredSize(new Dimension(collapsedWidth, collapsedHeight)); - updateUI(); - } - }); - - fireCollapseListeners(); - - repaint(); - } - - @Override - public void paint(Graphics g) { - super.paint(g); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - for (Runnable action : postPaintActions) { - action.run(); - } - - postPaintActions.clear(); - } - }); - } - - public boolean isExpanded() { - return !collapsable || expanded; - } - - public void setExpanded(boolean expanded) { - if (this.expanded != expanded) { - this.expanded = expanded; - if (collapsable) { - if (expanded) { - expandPanel(); - } else { - collapsePanel(); - } - } - } - } - - public boolean isCollapsable() { - return collapsable; - } - - public void setCollapsible(boolean collapsable) { - if (this.collapsable != collapsable) { - if (!collapsable && !expanded) { - setExpanded(true); - } - this.collapsable = collapsable; - - revalidate(); - repaint(); - - postPaintActions.add(new Runnable() { - @Override - public void run() { - refreshTitleIcon(); - placeTitleComponent(); - - titleBtn.validate(); - titleBtn.repaint(); - } - }); - } - } - - public boolean isBorderVisible() { - return borderVisible; - } - - public void setBorderVisible(boolean borderVisible) { - this.borderVisible = borderVisible; - if (borderVisible) { - setBorder(createBorderImplementation()); - placeTitleComponent(); - } else { - if (titleBtn.isVisible()) { - this.setBorder(new EmptyBorder(12, 2, 2, 2)); - } else { - this.setBorder(new EmptyBorder(0, 0, 0, 0)); - } - placeTitleComponent(); - } - this.repaint(); - } - - private CollapsibleTitledBorder createBorderImplementation() { - Border border = LineBorder.createGrayLineBorder(); - return new CollapsibleTitledBorder(border, titleBtn); - } - - public JComponent getComposition() { - return composition; - } - - public void setComposition(JComponent composition) { - this.composition = composition; - updateUI(); - placeTitleComponent(); - } - - public String getCaption() { - return titleBtn.getText(); - } - - public void setCaption(String caption) { - if (StringUtils.isEmpty(caption)) - titleBtn.setVisible(false); - else - titleBtn.setVisible(true); - - titleBtn.setText(caption); - setBorderVisible(borderVisible); - } - - public void addCollapseListener(CollapseListener collapseListener) { - if (collapseListeners == null) - collapseListeners = new ArrayList<>(); - collapseListeners.add(collapseListener); - } - - public void removeCollapseListener(CollapseListener collapseListener) { - if (collapseListeners != null) { - collapseListeners.remove(collapseListener); - if (collapseListeners.isEmpty()) - collapseListeners = null; - } - } - - protected void fireExpandListeners() { - if (collapseListeners != null) { - for (final CollapsiblePanel.CollapseListener collapseListener : collapseListeners) { - collapseListener.expanded(); - } - } - } - - protected void fireCollapseListeners() { - if (collapseListeners != null) { - for (final CollapsiblePanel.CollapseListener collapseListener : collapseListeners) { - collapseListener.collapsed(); - } - } - } - - protected class CollapsibleTitledBorder extends TitledBorder { - - private JButton titleComponent; - - public CollapsibleTitledBorder(Border border) { - this(border, null, LEFT, TOP); - } - - public CollapsibleTitledBorder(@Nullable Border border, JButton titleButton) { - this(border, titleButton, LEFT, TOP); - } - - public CollapsibleTitledBorder(@Nullable Border border, @Nullable JButton titleButton, int titleJustification, int titlePosition) { - super(border, null, titleJustification, titlePosition, null, null); - this.titleComponent = titleButton; - if (border == null) { - this.border = super.getBorder(); - } - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - if (!borderVisible) - return; - - if (StringUtils.isEmpty(getCaption())) { - super.paintBorder(c, g, x, y, width, height); - return; - } - - Rectangle borderR = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING, width - (EDGE_SPACING * 2), height - (EDGE_SPACING * 2)); - Insets borderInsets = new Insets(3, 3, 3, 3); - - Rectangle rect = new Rectangle(x, y, width, height); - Insets insets = getBorderInsets(c); - Rectangle compR = getComponentRect(rect, insets); - int diff; - switch (titlePosition) { - case ABOVE_TOP: - diff = compR.height + TEXT_SPACING; - borderR.y += diff; - borderR.height -= diff; - break; - case TOP: - case DEFAULT_POSITION: - diff = insets.top / 2 - borderInsets.top - EDGE_SPACING; - borderR.y += diff; - borderR.height -= diff; - break; - case BELOW_TOP: - case ABOVE_BOTTOM: - break; - case BOTTOM: - diff = insets.bottom / 2 - borderInsets.bottom - EDGE_SPACING; - borderR.height -= diff; - break; - case BELOW_BOTTOM: - diff = compR.height + TEXT_SPACING; - borderR.height -= diff; - break; - } - border.paintBorder(c, g, borderR.x, borderR.y, borderR.width, borderR.height); - Color col = g.getColor(); - g.setColor(c.getBackground()); - g.fillRect(compR.x, compR.y, compR.width, compR.height); - g.setColor(col); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - Insets borderInsets = (Insets) UIManager.getLookAndFeelDefaults().get("CollapsiblePanel.borderInsets"); - if (borderInsets == null) { - borderInsets = new Insets(10, 3, 3, 3); - } - insets.top = EDGE_SPACING + TEXT_SPACING + borderInsets.top; - insets.right = EDGE_SPACING + TEXT_SPACING + borderInsets.right; - insets.bottom = EDGE_SPACING + TEXT_SPACING + borderInsets.bottom; - insets.left = EDGE_SPACING + TEXT_SPACING + borderInsets.left; - - if (c == null || titleComponent == null) { - return insets; - } - - int compHeight = titleComponent.getPreferredSize().height; - - switch (titlePosition) { - case ABOVE_TOP: - insets.top += compHeight + TEXT_SPACING; - break; - case TOP: - case DEFAULT_POSITION: - insets.top += (compHeight / 2 - TEXT_SPACING); - break; - case BELOW_TOP: - insets.top += compHeight + TEXT_SPACING; - break; - case ABOVE_BOTTOM: - insets.bottom += compHeight + TEXT_SPACING; - break; - case BOTTOM: - insets.bottom += Math.max(compHeight, borderInsets.bottom) - borderInsets.bottom; - break; - case BELOW_BOTTOM: - insets.bottom += compHeight + TEXT_SPACING; - break; - } - return insets; - } - - public Rectangle getComponentRect(Rectangle rect, Insets borderInsets) { - Dimension compD = titleComponent.getPreferredSize(); - Rectangle compR = new Rectangle(0, 0, compD.width, compD.height); - switch (titlePosition) { - case ABOVE_TOP: - compR.y = EDGE_SPACING; - break; - case TOP: - case DEFAULT_POSITION: - compR.y = EDGE_SPACING + (borderInsets.top - EDGE_SPACING - TEXT_SPACING * 0 - compD.height) / 2; - break; - case BELOW_TOP: - compR.y = borderInsets.top - compD.height - TEXT_SPACING; - break; - case ABOVE_BOTTOM: - compR.y = rect.height - borderInsets.bottom + TEXT_SPACING; - break; - case BOTTOM: - compR.y = rect.height - borderInsets.bottom + TEXT_SPACING + (borderInsets.bottom - EDGE_SPACING - TEXT_SPACING - compD.height) / 2; - break; - case BELOW_BOTTOM: - compR.y = rect.height - compD.height - EDGE_SPACING; - break; - } - switch (titleJustification) { - case LEFT: - case DEFAULT_JUSTIFICATION: - compR.x = TEXT_INSET_H + borderInsets.left - EDGE_SPACING; - break; - case RIGHT: - compR.x = rect.width - borderInsets.right - TEXT_INSET_H - compR.width; - break; - case CENTER: - compR.x = (rect.width - compR.width) / 2; - break; - } - return compR; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import com.haulmont.cuba.desktop.App; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Panel with border and collapse/expand button + */ +public class CollapsiblePanel extends JPanel { + + protected static final int COLLAPSED_HEIGHT = 10; + + protected boolean expanded = true; + protected boolean collapsable = false; + + protected JComponent composition; + protected JButton titleBtn; + + protected boolean borderVisible = true; + + protected Dimension preferredSize; + + protected java.util.List postPaintActions = new LinkedList<>(); + + public interface CollapseListener extends java.util.EventListener { + + void collapsed(); + + void expanded(); + } + + private java.util.List collapseListeners; + + private Icon expandedIcon; + private Icon collapsedIcon; + + public CollapsiblePanel(JComponent composition) { + this.composition = composition; + + titleBtn = new JButton(); + titleBtn.setBorder(BorderFactory.createEmptyBorder(0, 3, 5, 3)); + titleBtn.setVerticalTextPosition(AbstractButton.CENTER); + titleBtn.setHorizontalTextPosition(AbstractButton.RIGHT); + titleBtn.setMargin(new Insets(0, 0, 3, 0)); + + titleBtn.setFont(getTitleFont()); + titleBtn.setFocusable(false); + titleBtn.setContentAreaFilled(false); + titleBtn.setVisible(false); + + titleBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (isCollapsable()) + setExpanded(!isExpanded()); + } + }); + + // Add icons + loadIcons(); + refreshTitleIcon(); + + setLayout(new BorderLayout()); + add(titleBtn, BorderLayout.CENTER); + add(composition, BorderLayout.CENTER); + + setBorder(createBorderImplementation()); + + preferredSize = getPreferredSize(); + + placeTitleComponent(); + } + + private Font getTitleFont() { + UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); + if (lafDefaults.getFont("CollapsiblePanel.font") != null) { // take it from desktop theme + return lafDefaults.getFont("CollapsiblePanel.font"); + } + return lafDefaults.getFont("Panel.font"); + } + + private void refreshTitleIcon() { + if (collapsable) { + if (expanded) { + titleBtn.setIcon(expandedIcon); + } else { + titleBtn.setIcon(collapsedIcon); + } + } else { + titleBtn.setIcon(null); + } + } + + private void placeTitleComponent() { + Insets insets = getInsets(); + Rectangle containerRectangle = getBounds(); + if (borderVisible) { + Rectangle componentRectangle = ((CollapsibleTitledBorder) getBorder()).getComponentRect(containerRectangle, insets); + titleBtn.setBounds(componentRectangle); + } else { + Dimension compD = titleBtn.getPreferredSize(); + Rectangle compR = new Rectangle(20 - insets.left, 0, compD.width, compD.height); + titleBtn.setBounds(compR); + } + } + + @Override + public Dimension getPreferredSize() { + int preferredHeight = super.getPreferredSize().height; + int preferredWidth = titleBtn.getPreferredSize().width + titleBtn.getBounds().x * 2; + + if (preferredWidth > super.getPreferredSize().width) { + return new Dimension(preferredWidth, preferredHeight); + } + + return super.getPreferredSize(); + } + + protected void loadIcons() { + App app = App.getInstance(); + if (app != null) { + expandedIcon = app.getResources().getIcon("components/groupbox/item-expanded.png"); + collapsedIcon = app.getResources().getIcon("components/groupbox/item-collapsed.png"); + } else { + // fallback for unit tests + expandedIcon = readIcon("components/groupbox/item-expanded.png"); + collapsedIcon = readIcon("components/groupbox/item-collapsed.png"); + } + } + + protected ImageIcon readIcon(String iconPath) { + try { + String iconResourcePath = "/com/haulmont/cuba/desktop/res/nimbus/" + iconPath; + return new ImageIcon(IOUtils.toByteArray(getClass().getResourceAsStream(iconResourcePath))); + } catch (IOException e) { + throw new RuntimeException("Unable to read icon", e); + } + } + + protected void expandPanel() { + composition.setVisible(true); + + postPaintActions.add(new Runnable() { + @Override + public void run() { + titleBtn.setIcon(expandedIcon); + setPreferredSize(preferredSize); + updateUI(); + } + }); + + fireExpandListeners(); + + repaint(); + } + + private void collapsePanel() { + composition.setVisible(false); + + postPaintActions.add(new Runnable() { + @Override + public void run() { + int collapsedWidth = getWidth(); + int collapsedHeight = COLLAPSED_HEIGHT; + + preferredSize = getPreferredSize(); + + titleBtn.setIcon(collapsedIcon); + setPreferredSize(new Dimension(collapsedWidth, collapsedHeight)); + updateUI(); + } + }); + + fireCollapseListeners(); + + repaint(); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + for (Runnable action : postPaintActions) { + action.run(); + } + + postPaintActions.clear(); + } + }); + } + + public boolean isExpanded() { + return !collapsable || expanded; + } + + public void setExpanded(boolean expanded) { + if (this.expanded != expanded) { + this.expanded = expanded; + if (collapsable) { + if (expanded) { + expandPanel(); + } else { + collapsePanel(); + } + } + } + } + + public boolean isCollapsable() { + return collapsable; + } + + public void setCollapsible(boolean collapsable) { + if (this.collapsable != collapsable) { + if (!collapsable && !expanded) { + setExpanded(true); + } + this.collapsable = collapsable; + + revalidate(); + repaint(); + + postPaintActions.add(new Runnable() { + @Override + public void run() { + refreshTitleIcon(); + placeTitleComponent(); + + titleBtn.validate(); + titleBtn.repaint(); + } + }); + } + } + + public boolean isBorderVisible() { + return borderVisible; + } + + public void setBorderVisible(boolean borderVisible) { + this.borderVisible = borderVisible; + if (borderVisible) { + setBorder(createBorderImplementation()); + placeTitleComponent(); + } else { + if (titleBtn.isVisible()) { + this.setBorder(new EmptyBorder(12, 2, 2, 2)); + } else { + this.setBorder(new EmptyBorder(0, 0, 0, 0)); + } + placeTitleComponent(); + } + this.repaint(); + } + + private CollapsibleTitledBorder createBorderImplementation() { + Border border = LineBorder.createGrayLineBorder(); + return new CollapsibleTitledBorder(border, titleBtn); + } + + public JComponent getComposition() { + return composition; + } + + public void setComposition(JComponent composition) { + this.composition = composition; + updateUI(); + placeTitleComponent(); + } + + public String getCaption() { + return titleBtn.getText(); + } + + public void setCaption(String caption) { + if (StringUtils.isEmpty(caption)) + titleBtn.setVisible(false); + else + titleBtn.setVisible(true); + + titleBtn.setText(caption); + setBorderVisible(borderVisible); + } + + public void addCollapseListener(CollapseListener collapseListener) { + if (collapseListeners == null) + collapseListeners = new ArrayList<>(); + collapseListeners.add(collapseListener); + } + + public void removeCollapseListener(CollapseListener collapseListener) { + if (collapseListeners != null) { + collapseListeners.remove(collapseListener); + if (collapseListeners.isEmpty()) + collapseListeners = null; + } + } + + protected void fireExpandListeners() { + if (collapseListeners != null) { + for (final CollapsiblePanel.CollapseListener collapseListener : collapseListeners) { + collapseListener.expanded(); + } + } + } + + protected void fireCollapseListeners() { + if (collapseListeners != null) { + for (final CollapsiblePanel.CollapseListener collapseListener : collapseListeners) { + collapseListener.collapsed(); + } + } + } + + protected class CollapsibleTitledBorder extends TitledBorder { + + private JButton titleComponent; + + public CollapsibleTitledBorder(Border border) { + this(border, null, LEFT, TOP); + } + + public CollapsibleTitledBorder(@Nullable Border border, JButton titleButton) { + this(border, titleButton, LEFT, TOP); + } + + public CollapsibleTitledBorder(@Nullable Border border, @Nullable JButton titleButton, int titleJustification, int titlePosition) { + super(border, null, titleJustification, titlePosition, null, null); + this.titleComponent = titleButton; + if (border == null) { + this.border = super.getBorder(); + } + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + if (!borderVisible) + return; + + if (StringUtils.isEmpty(getCaption())) { + super.paintBorder(c, g, x, y, width, height); + return; + } + + Rectangle borderR = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING, width - (EDGE_SPACING * 2), height - (EDGE_SPACING * 2)); + Insets borderInsets = new Insets(3, 3, 3, 3); + + Rectangle rect = new Rectangle(x, y, width, height); + Insets insets = getBorderInsets(c); + Rectangle compR = getComponentRect(rect, insets); + int diff; + switch (titlePosition) { + case ABOVE_TOP: + diff = compR.height + TEXT_SPACING; + borderR.y += diff; + borderR.height -= diff; + break; + case TOP: + case DEFAULT_POSITION: + diff = insets.top / 2 - borderInsets.top - EDGE_SPACING; + borderR.y += diff; + borderR.height -= diff; + break; + case BELOW_TOP: + case ABOVE_BOTTOM: + break; + case BOTTOM: + diff = insets.bottom / 2 - borderInsets.bottom - EDGE_SPACING; + borderR.height -= diff; + break; + case BELOW_BOTTOM: + diff = compR.height + TEXT_SPACING; + borderR.height -= diff; + break; + } + border.paintBorder(c, g, borderR.x, borderR.y, borderR.width, borderR.height); + Color col = g.getColor(); + g.setColor(c.getBackground()); + g.fillRect(compR.x, compR.y, compR.width, compR.height); + g.setColor(col); + } + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + Insets borderInsets = (Insets) UIManager.getLookAndFeelDefaults().get("CollapsiblePanel.borderInsets"); + if (borderInsets == null) { + borderInsets = new Insets(10, 3, 3, 3); + } + insets.top = EDGE_SPACING + TEXT_SPACING + borderInsets.top; + insets.right = EDGE_SPACING + TEXT_SPACING + borderInsets.right; + insets.bottom = EDGE_SPACING + TEXT_SPACING + borderInsets.bottom; + insets.left = EDGE_SPACING + TEXT_SPACING + borderInsets.left; + + if (c == null || titleComponent == null) { + return insets; + } + + int compHeight = titleComponent.getPreferredSize().height; + + switch (titlePosition) { + case ABOVE_TOP: + insets.top += compHeight + TEXT_SPACING; + break; + case TOP: + case DEFAULT_POSITION: + insets.top += (compHeight / 2 - TEXT_SPACING); + break; + case BELOW_TOP: + insets.top += compHeight + TEXT_SPACING; + break; + case ABOVE_BOTTOM: + insets.bottom += compHeight + TEXT_SPACING; + break; + case BOTTOM: + insets.bottom += Math.max(compHeight, borderInsets.bottom) - borderInsets.bottom; + break; + case BELOW_BOTTOM: + insets.bottom += compHeight + TEXT_SPACING; + break; + } + return insets; + } + + public Rectangle getComponentRect(Rectangle rect, Insets borderInsets) { + Dimension compD = titleComponent.getPreferredSize(); + Rectangle compR = new Rectangle(0, 0, compD.width, compD.height); + switch (titlePosition) { + case ABOVE_TOP: + compR.y = EDGE_SPACING; + break; + case TOP: + case DEFAULT_POSITION: + compR.y = EDGE_SPACING + (borderInsets.top - EDGE_SPACING - TEXT_SPACING * 0 - compD.height) / 2; + break; + case BELOW_TOP: + compR.y = borderInsets.top - compD.height - TEXT_SPACING; + break; + case ABOVE_BOTTOM: + compR.y = rect.height - borderInsets.bottom + TEXT_SPACING; + break; + case BOTTOM: + compR.y = rect.height - borderInsets.bottom + TEXT_SPACING + (borderInsets.bottom - EDGE_SPACING - TEXT_SPACING - compD.height) / 2; + break; + case BELOW_BOTTOM: + compR.y = rect.height - compD.height - EDGE_SPACING; + break; + } + switch (titleJustification) { + case LEFT: + case DEFAULT_JUSTIFICATION: + compR.x = TEXT_INSET_H + borderInsets.left - EDGE_SPACING; + break; + case RIGHT: + compR.x = rect.width - borderInsets.right - TEXT_INSET_H - compR.width; + break; + case CENTER: + compR.x = (rect.width - compR.width) / 2; + break; + } + return compR; + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/CustomDatePickerUI.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/CustomDatePickerUI.java index 33b46e8d41..febf19e5fd 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/CustomDatePickerUI.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/CustomDatePickerUI.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl.DatePicker; - -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import org.jdesktop.swingx.JXDatePicker; -import org.jdesktop.swingx.plaf.basic.BasicDatePickerUI; - -import javax.swing.*; -import java.awt.*; - -public class CustomDatePickerUI extends BasicDatePickerUI { - @Override - protected JButton createPopupButton() { - JButton b = new JButton(); - b.setName("popupButton"); - b.setRolloverEnabled(false); - b.setMargin(new Insets(0, 3, 0, 3)); - App app = App.getInstance(); - if (app != null) { - b.setIcon(app.getResources().getIcon("/components/datefield/open-button.png")); - } - b.setFocusable(false); - b.setPreferredSize(new Dimension(22, DesktopComponentsHelper.BUTTON_HEIGHT)); - return b; - } - - @Override - protected void installKeyboardActions() { - super.installKeyboardActions(); - ActionMap pickerMap = datePicker.getActionMap(); - pickerMap.remove(JXDatePicker.CANCEL_KEY); - InputMap pickerInputMap = datePicker.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - pickerInputMap.remove(KeyStroke.getKeyStroke("ESCAPE")); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl.DatePicker; + +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import org.jdesktop.swingx.JXDatePicker; +import org.jdesktop.swingx.plaf.basic.BasicDatePickerUI; + +import javax.swing.*; +import java.awt.*; + +public class CustomDatePickerUI extends BasicDatePickerUI { + @Override + protected JButton createPopupButton() { + JButton b = new JButton(); + b.setName("popupButton"); + b.setRolloverEnabled(false); + b.setMargin(new Insets(0, 3, 0, 3)); + App app = App.getInstance(); + if (app != null) { + b.setIcon(app.getResources().getIcon("/components/datefield/open-button.png")); + } + b.setFocusable(false); + b.setPreferredSize(new Dimension(22, DesktopComponentsHelper.BUTTON_HEIGHT)); + return b; + } + + @Override + protected void installKeyboardActions() { + super.installKeyboardActions(); + ActionMap pickerMap = datePicker.getActionMap(); + pickerMap.remove(JXDatePicker.CANCEL_KEY); + InputMap pickerInputMap = datePicker.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + pickerInputMap.remove(KeyStroke.getKeyStroke("ESCAPE")); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePicker.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePicker.java index 461bc5452a..8a37713ff4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePicker.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePicker.java @@ -1,184 +1,184 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl.DatePicker; - -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.components.Frame; -import org.apache.commons.lang.ObjectUtils; -import org.jdesktop.swingx.JXDatePicker; -import org.jdesktop.swingx.calendar.DatePickerFormatter; -import org.jdesktop.swingx.util.Contract; - -import javax.swing.*; -import javax.swing.text.DefaultFormatterFactory; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.text.DateFormat; -import java.text.MessageFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -public class DatePicker extends JXDatePicker { - protected String format; - - private static final char PLACE_HOLDER = '_'; - - public DatePicker(){ - super(); - setUI(new CustomDatePickerUI()); - } - - @Override - public void setEditor(final JFormattedTextField editor) { - final int ENTER_CODE = 10; - - editor.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == '\u007F' && editor.getCaretPosition() < format.length()) { - editor.setCaretPosition(editor.getCaretPosition() + 1); - } - } - - @Override - public void keyPressed(KeyEvent event) { - if (ENTER_CODE == event.getKeyCode()) - try { - editor.commitEdit(); - } catch (ParseException e) { - // - } - } - }); - - editor.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - editor.setCaretPosition(0); - } - }); - - super.setEditor(editor); - - if (format == null) { - setFormats(Datatypes.getFormatStrings(AppBeans.get(UserSessionSource.class).getLocale()).getDateFormat()); - } else - setFormats(format); - } - - @Override - public void setLinkDay(Date linkDay) { - MessageFormat todayFormat = new MessageFormat(AppBeans.get(Messages.class).getMessage("com.haulmont.cuba.desktop", "DatePicker.linkFormat")); - todayFormat.setFormat(0, new SimpleDateFormat(Datatypes.getFormatStrings(AppBeans.get(UserSessionSource.class).getLocale()).getDateFormat())); - setLinkFormat(todayFormat); - super.setLinkDay(linkDay); - } - - @Override - public void setFormats(String... formats) { - super.setFormats(formats); - format = formats[0]; - Object prevVal = getEditor().getValue(); - if (prevVal == null) { - getEditor().setText(getMask(format)); - } - getEditor().setDocument(new DatePickerDocument(getEditor(), format, getMask(format), PLACE_HOLDER)); - if (prevVal != null) - getEditor().setValue(prevVal); - } - - @Override - public void setFormats(DateFormat... formats) { - if (formats != null) { - Contract.asNotNull(formats, "the array of formats " + "must not contain null elements"); - } - DateFormat[] old = getFormats(); - for (DateFormat format : formats) { - format.setLenient(false); - } - getEditor().setFormatterFactory(new DefaultFormatterFactory( - new DatePicker.CustomDatePickerFormatter(formats, getLocale()))); - firePropertyChange("formats", old, getFormats()); - } - - protected String getMask(String format) { - StringBuilder mask = new StringBuilder(format); - for (int i = 0; i < mask.length(); i++) { - char current = mask.charAt(i); - current = Character.toLowerCase(current); - if (current == 'd' || current == 'm' || current == 'y') { - mask.setCharAt(i, PLACE_HOLDER); - } - } - return mask.toString(); - } - - @Override - public DateFormat[] getFormats() { - if (getEditor() != null) { - return super.getFormats(); - } else - return new DateFormat[0]; - } - - public class CustomDatePickerFormatter extends DatePickerFormatter { - @Override - public void install(final JFormattedTextField ftf) { - try { - if (valueToString(ftf.getValue()) == null && format != null) { - ftf.setText(getMask(format)); - return; - } - } catch (ParseException e) { - ftf.setText(getMask(format)); - } - super.install(ftf); - ftf.setCaretPosition(0); - } - - public CustomDatePickerFormatter(DateFormat formats[], Locale locale) { - super(formats, locale); - } - - @Override - public Object stringToValue(String text) throws ParseException { - if (text == null || text.trim().length() == 0 || ObjectUtils.equals(getMask(format), text)) { - return null; - } - try { - return super.stringToValue(text); - } catch (ParseException e) { - DesktopComponentsHelper.getTopLevelFrame(getParent()).showNotification( - AppBeans.get(Messages.class).getMessage(AppConfig.getMessagesPack(), "validationFail"), - Frame.NotificationType.TRAY - ); - cancelEdit(); - throw e; - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl.DatePicker; + +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.components.Frame; +import org.apache.commons.lang.ObjectUtils; +import org.jdesktop.swingx.JXDatePicker; +import org.jdesktop.swingx.calendar.DatePickerFormatter; +import org.jdesktop.swingx.util.Contract; + +import javax.swing.*; +import javax.swing.text.DefaultFormatterFactory; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class DatePicker extends JXDatePicker { + protected String format; + + private static final char PLACE_HOLDER = '_'; + + public DatePicker(){ + super(); + setUI(new CustomDatePickerUI()); + } + + @Override + public void setEditor(final JFormattedTextField editor) { + final int ENTER_CODE = 10; + + editor.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\u007F' && editor.getCaretPosition() < format.length()) { + editor.setCaretPosition(editor.getCaretPosition() + 1); + } + } + + @Override + public void keyPressed(KeyEvent event) { + if (ENTER_CODE == event.getKeyCode()) + try { + editor.commitEdit(); + } catch (ParseException e) { + // + } + } + }); + + editor.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + editor.setCaretPosition(0); + } + }); + + super.setEditor(editor); + + if (format == null) { + setFormats(Datatypes.getFormatStrings(AppBeans.get(UserSessionSource.class).getLocale()).getDateFormat()); + } else + setFormats(format); + } + + @Override + public void setLinkDay(Date linkDay) { + MessageFormat todayFormat = new MessageFormat(AppBeans.get(Messages.class).getMessage("com.haulmont.cuba.desktop", "DatePicker.linkFormat")); + todayFormat.setFormat(0, new SimpleDateFormat(Datatypes.getFormatStrings(AppBeans.get(UserSessionSource.class).getLocale()).getDateFormat())); + setLinkFormat(todayFormat); + super.setLinkDay(linkDay); + } + + @Override + public void setFormats(String... formats) { + super.setFormats(formats); + format = formats[0]; + Object prevVal = getEditor().getValue(); + if (prevVal == null) { + getEditor().setText(getMask(format)); + } + getEditor().setDocument(new DatePickerDocument(getEditor(), format, getMask(format), PLACE_HOLDER)); + if (prevVal != null) + getEditor().setValue(prevVal); + } + + @Override + public void setFormats(DateFormat... formats) { + if (formats != null) { + Contract.asNotNull(formats, "the array of formats " + "must not contain null elements"); + } + DateFormat[] old = getFormats(); + for (DateFormat format : formats) { + format.setLenient(false); + } + getEditor().setFormatterFactory(new DefaultFormatterFactory( + new DatePicker.CustomDatePickerFormatter(formats, getLocale()))); + firePropertyChange("formats", old, getFormats()); + } + + protected String getMask(String format) { + StringBuilder mask = new StringBuilder(format); + for (int i = 0; i < mask.length(); i++) { + char current = mask.charAt(i); + current = Character.toLowerCase(current); + if (current == 'd' || current == 'm' || current == 'y') { + mask.setCharAt(i, PLACE_HOLDER); + } + } + return mask.toString(); + } + + @Override + public DateFormat[] getFormats() { + if (getEditor() != null) { + return super.getFormats(); + } else + return new DateFormat[0]; + } + + public class CustomDatePickerFormatter extends DatePickerFormatter { + @Override + public void install(final JFormattedTextField ftf) { + try { + if (valueToString(ftf.getValue()) == null && format != null) { + ftf.setText(getMask(format)); + return; + } + } catch (ParseException e) { + ftf.setText(getMask(format)); + } + super.install(ftf); + ftf.setCaretPosition(0); + } + + public CustomDatePickerFormatter(DateFormat formats[], Locale locale) { + super(formats, locale); + } + + @Override + public Object stringToValue(String text) throws ParseException { + if (text == null || text.trim().length() == 0 || ObjectUtils.equals(getMask(format), text)) { + return null; + } + try { + return super.stringToValue(text); + } catch (ParseException e) { + DesktopComponentsHelper.getTopLevelFrame(getParent()).showNotification( + AppBeans.get(Messages.class).getMessage(AppConfig.getMessagesPack(), "validationFail"), + Frame.NotificationType.TRAY + ); + cancelEdit(); + throw e; + } + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePickerDocument.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePickerDocument.java index 85e3c81688..6e8b1f17a7 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePickerDocument.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/DatePicker/DatePickerDocument.java @@ -1,297 +1,297 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl.DatePicker; - -import javax.swing.*; -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.PlainDocument; - -public class DatePickerDocument extends PlainDocument { - private static final int MAX_DAYS = 31; - - protected char placeHolder; - protected JTextField field; - protected String mask; - protected String dateFormat; - - private int month0 = -1; - private int month1 = -1; - private int day0 = -1; - private int day1 = -1; - - public DatePickerDocument(final JTextField field, String dateFormat, String mask, char placeHolder) { - this.field = field; - this.dateFormat = dateFormat; - parseFormat(dateFormat); - this.mask = mask; - this.placeHolder = placeHolder; - - try { - super.insertString(0, mask, null); - } catch (BadLocationException e) { - //offset in insertString == 0 - } - } - - private void parseFormat(String format) { - for (int i = 0; i < format.length(); i++) { - char current = format.charAt(i); - switch (current) { - case 'd': - if (day0 == -1) - day0 = i; - else day1 = i; - break; - case 'M': - if (month0 == -1) - month0 = i; - else month1 = i; - break; - } - } - } - - @Override - public void replace(int offset, int length, String text, - AttributeSet attrs) throws BadLocationException { - if (length == 0 && (text == null || text.length() == 0)) { - return; - } - - if (text == null && length == mask.length()) - return; - - writeLock(); - try { - if (length > 0) { - int removeLength; - if (text != null && text.length() < length) { - removeLength = text.length(); - } else removeLength = length; - remove(offset, removeLength); - } - if (getText(0, 1).equals("\n")) - super.insertString(offset, calculateFormattedString(offset, text), null); - else { - String formattedString = calculateFormattedString(offset, text); - internalReplace(offset, formattedString.length(), formattedString, null); - } - } finally { - writeUnlock(); - } - } - - private void internalReplace(int offset, int length, String text, - AttributeSet attrs) throws BadLocationException { - if (length == 0 && (text == null || text.length() == 0)) { - return; - } - - writeLock(); - try { - if (length > 0) { - super.remove(offset, length); - } - if (text != null && text.length() > 0) { - super.insertString(offset, text, attrs); - } - } finally { - writeUnlock(); - } - } - - @Override - public void remove(int offs, int len) throws BadLocationException { - super.remove(offs, len); - super.insertString(offs, mask.substring(offs, offs + len), null); - field.setCaretPosition(offs); - } - - private String calculateFormattedString(int offset, String text) throws BadLocationException { - if (text == null) - return mask; - StringBuilder result; - - int endPosition; - if (offset + text.length() > mask.length()) - endPosition = mask.length(); - else - endPosition = offset + text.length(); - - result = new StringBuilder(mask.substring(offset, endPosition)); - int i = 0; - int shift = 0; - boolean inserted = false; - while (i + offset < mask.length() && i < text.length()) { - if ((mask.charAt(i + offset) == placeHolder)) { - if ((Character.isDigit(text.charAt(i)))) { - int digit = Integer.parseInt(text.substring(i, i + 1)); - - if (i + offset == month0) { - if (digit > 1) { - if (text.length() == 1) { - result.deleteCharAt(i + shift); - shift--; - } else { - if (result.length() > i + shift) - result.setCharAt(i + shift, '1'); - else result.insert(i + shift, '1'); - } - inserted = true; - } else if (digit == 1) { - char c = getText(month1, 1).charAt(0); - int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(month1, 1)) : 0; - if (digit2 > 2) { - if (result.length() > i + shift + 1) - result.setCharAt(i + shift + 1, '0'); - else result.insert(i + shift + 1, '0'); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - field.setCaretPosition(field.getCaretPosition() - 1); - } - }); - } - } - if (!inserted) - result.setCharAt(i + shift, text.charAt(i)); - - } else if (i + offset == month1) { - int prevDigit; - try { - if (offset <= month0) { - prevDigit = Integer.parseInt(result.substring(month0 - offset, month0 - offset + 1)); - } else { - prevDigit = Integer.parseInt(getText(month0, 1)); - } - } catch (NumberFormatException e) { - prevDigit = 0; - } - if (prevDigit == 1) { - if (digit > 2) { - if (result.length() == 1) - result.deleteCharAt(0); - else - result.setCharAt(i + shift, '0'); - } else result.setCharAt(i + shift, text.charAt(i)); - } else - result.setCharAt(i + shift, text.charAt(i)); - inserted = true; - } else if (i + offset == day0) { - if (result.length() == 1) { - if (digit > MAX_DAYS / 10) { - result.deleteCharAt(0); - shift--; - } else if (digit == MAX_DAYS / 10) { - char c = getText(day1, 1).charAt(0); - int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(day1, 1)) : 0; - if (digit2 > MAX_DAYS % 10) { - result.setCharAt(i + shift, text.charAt(i)); - result.insert(i + shift + 1, '0'); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - field.setCaretPosition(field.getCaretPosition() - 1); - } - }); - } else result.setCharAt(i + shift, text.charAt(i)); - } else result.setCharAt(i + shift, text.charAt(i)); - } else result.setCharAt(i + shift, text.charAt(i)); - } else if (i + offset == day1) { - if (result.length() == 1) { - char c = getText(day0, 1).charAt(0); - int prevDigit = Character.isDigit(c) ? Integer.parseInt(getText(day0, 1)) : 0; - if (prevDigit * 10 + digit > MAX_DAYS) { - result.deleteCharAt(0); - shift--; - } else result.setCharAt(i + shift, text.charAt(i)); - } else result.setCharAt(i + shift, text.charAt(i)); - } else { - result.setCharAt(i + shift, text.charAt(i)); - } - } else { - if (result.length() == 1) { - result.deleteCharAt(0); - shift--; - } else { - result.setCharAt(i + shift, placeHolder); - } - } - } else if ((mask.charAt(i + offset) != placeHolder) && (Character.isDigit(text.charAt(i)))) { - int digit = Integer.parseInt(text.substring(i, i + 1)); - if (i + offset + 1 == month0) { - if (digit > 1) { - if (result.length() > i + 1) - result.deleteCharAt(i + 1 + shift); - } else if (digit == 1 && result.length() == 1) { - char c = getText(month1, 1).charAt(0); - int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(month1, 1)) : 0; - if (digit2 > 2) { - result.insert(i + 1 + shift, text.charAt(i)); - result.insert(i + shift + 1 + 1, '0'); - shift++; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - field.setCaretPosition(field.getCaretPosition() - 1); - } - }); - } else { - result.insert(i + 1 + shift, text.charAt(i)); - shift++; - } - } else { - result.insert(i + 1 + shift, text.charAt(i)); - shift++; - } - } else if (i + offset + 1 == day0) { - if (digit > MAX_DAYS / 10) { - if (result.length() > i + 1) - result.deleteCharAt(i + 1 + shift); - } else if (digit == MAX_DAYS / 10 && result.length() == 1) { - char c = getText(day1, 1).charAt(0); - int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(day1, 1)) : 0; - if (digit2 > MAX_DAYS % 10) { - result.insert(i + shift + 1, text.charAt(i)); - result.insert(i + shift + 2, '0'); - shift++; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - field.setCaretPosition(field.getCaretPosition() - 1); - } - }); - } else { - result.insert(i + shift + 1, text.charAt(i)); - shift++; - } - } else { - result.insert(i + 1 + shift, text.charAt(i)); - shift++; - } - } else { - result.insert(i + 1 + shift, text.charAt(i)); - shift++; - } - } - i++; - } - return result.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl.DatePicker; + +import javax.swing.*; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +public class DatePickerDocument extends PlainDocument { + private static final int MAX_DAYS = 31; + + protected char placeHolder; + protected JTextField field; + protected String mask; + protected String dateFormat; + + private int month0 = -1; + private int month1 = -1; + private int day0 = -1; + private int day1 = -1; + + public DatePickerDocument(final JTextField field, String dateFormat, String mask, char placeHolder) { + this.field = field; + this.dateFormat = dateFormat; + parseFormat(dateFormat); + this.mask = mask; + this.placeHolder = placeHolder; + + try { + super.insertString(0, mask, null); + } catch (BadLocationException e) { + //offset in insertString == 0 + } + } + + private void parseFormat(String format) { + for (int i = 0; i < format.length(); i++) { + char current = format.charAt(i); + switch (current) { + case 'd': + if (day0 == -1) + day0 = i; + else day1 = i; + break; + case 'M': + if (month0 == -1) + month0 = i; + else month1 = i; + break; + } + } + } + + @Override + public void replace(int offset, int length, String text, + AttributeSet attrs) throws BadLocationException { + if (length == 0 && (text == null || text.length() == 0)) { + return; + } + + if (text == null && length == mask.length()) + return; + + writeLock(); + try { + if (length > 0) { + int removeLength; + if (text != null && text.length() < length) { + removeLength = text.length(); + } else removeLength = length; + remove(offset, removeLength); + } + if (getText(0, 1).equals("\n")) + super.insertString(offset, calculateFormattedString(offset, text), null); + else { + String formattedString = calculateFormattedString(offset, text); + internalReplace(offset, formattedString.length(), formattedString, null); + } + } finally { + writeUnlock(); + } + } + + private void internalReplace(int offset, int length, String text, + AttributeSet attrs) throws BadLocationException { + if (length == 0 && (text == null || text.length() == 0)) { + return; + } + + writeLock(); + try { + if (length > 0) { + super.remove(offset, length); + } + if (text != null && text.length() > 0) { + super.insertString(offset, text, attrs); + } + } finally { + writeUnlock(); + } + } + + @Override + public void remove(int offs, int len) throws BadLocationException { + super.remove(offs, len); + super.insertString(offs, mask.substring(offs, offs + len), null); + field.setCaretPosition(offs); + } + + private String calculateFormattedString(int offset, String text) throws BadLocationException { + if (text == null) + return mask; + StringBuilder result; + + int endPosition; + if (offset + text.length() > mask.length()) + endPosition = mask.length(); + else + endPosition = offset + text.length(); + + result = new StringBuilder(mask.substring(offset, endPosition)); + int i = 0; + int shift = 0; + boolean inserted = false; + while (i + offset < mask.length() && i < text.length()) { + if ((mask.charAt(i + offset) == placeHolder)) { + if ((Character.isDigit(text.charAt(i)))) { + int digit = Integer.parseInt(text.substring(i, i + 1)); + + if (i + offset == month0) { + if (digit > 1) { + if (text.length() == 1) { + result.deleteCharAt(i + shift); + shift--; + } else { + if (result.length() > i + shift) + result.setCharAt(i + shift, '1'); + else result.insert(i + shift, '1'); + } + inserted = true; + } else if (digit == 1) { + char c = getText(month1, 1).charAt(0); + int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(month1, 1)) : 0; + if (digit2 > 2) { + if (result.length() > i + shift + 1) + result.setCharAt(i + shift + 1, '0'); + else result.insert(i + shift + 1, '0'); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + field.setCaretPosition(field.getCaretPosition() - 1); + } + }); + } + } + if (!inserted) + result.setCharAt(i + shift, text.charAt(i)); + + } else if (i + offset == month1) { + int prevDigit; + try { + if (offset <= month0) { + prevDigit = Integer.parseInt(result.substring(month0 - offset, month0 - offset + 1)); + } else { + prevDigit = Integer.parseInt(getText(month0, 1)); + } + } catch (NumberFormatException e) { + prevDigit = 0; + } + if (prevDigit == 1) { + if (digit > 2) { + if (result.length() == 1) + result.deleteCharAt(0); + else + result.setCharAt(i + shift, '0'); + } else result.setCharAt(i + shift, text.charAt(i)); + } else + result.setCharAt(i + shift, text.charAt(i)); + inserted = true; + } else if (i + offset == day0) { + if (result.length() == 1) { + if (digit > MAX_DAYS / 10) { + result.deleteCharAt(0); + shift--; + } else if (digit == MAX_DAYS / 10) { + char c = getText(day1, 1).charAt(0); + int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(day1, 1)) : 0; + if (digit2 > MAX_DAYS % 10) { + result.setCharAt(i + shift, text.charAt(i)); + result.insert(i + shift + 1, '0'); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + field.setCaretPosition(field.getCaretPosition() - 1); + } + }); + } else result.setCharAt(i + shift, text.charAt(i)); + } else result.setCharAt(i + shift, text.charAt(i)); + } else result.setCharAt(i + shift, text.charAt(i)); + } else if (i + offset == day1) { + if (result.length() == 1) { + char c = getText(day0, 1).charAt(0); + int prevDigit = Character.isDigit(c) ? Integer.parseInt(getText(day0, 1)) : 0; + if (prevDigit * 10 + digit > MAX_DAYS) { + result.deleteCharAt(0); + shift--; + } else result.setCharAt(i + shift, text.charAt(i)); + } else result.setCharAt(i + shift, text.charAt(i)); + } else { + result.setCharAt(i + shift, text.charAt(i)); + } + } else { + if (result.length() == 1) { + result.deleteCharAt(0); + shift--; + } else { + result.setCharAt(i + shift, placeHolder); + } + } + } else if ((mask.charAt(i + offset) != placeHolder) && (Character.isDigit(text.charAt(i)))) { + int digit = Integer.parseInt(text.substring(i, i + 1)); + if (i + offset + 1 == month0) { + if (digit > 1) { + if (result.length() > i + 1) + result.deleteCharAt(i + 1 + shift); + } else if (digit == 1 && result.length() == 1) { + char c = getText(month1, 1).charAt(0); + int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(month1, 1)) : 0; + if (digit2 > 2) { + result.insert(i + 1 + shift, text.charAt(i)); + result.insert(i + shift + 1 + 1, '0'); + shift++; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + field.setCaretPosition(field.getCaretPosition() - 1); + } + }); + } else { + result.insert(i + 1 + shift, text.charAt(i)); + shift++; + } + } else { + result.insert(i + 1 + shift, text.charAt(i)); + shift++; + } + } else if (i + offset + 1 == day0) { + if (digit > MAX_DAYS / 10) { + if (result.length() > i + 1) + result.deleteCharAt(i + 1 + shift); + } else if (digit == MAX_DAYS / 10 && result.length() == 1) { + char c = getText(day1, 1).charAt(0); + int digit2 = Character.isDigit(c) ? Integer.parseInt(getText(day1, 1)) : 0; + if (digit2 > MAX_DAYS % 10) { + result.insert(i + shift + 1, text.charAt(i)); + result.insert(i + shift + 2, '0'); + shift++; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + field.setCaretPosition(field.getCaretPosition() - 1); + } + }); + } else { + result.insert(i + shift + 1, text.charAt(i)); + shift++; + } + } else { + result.insert(i + 1 + shift, text.charAt(i)); + shift++; + } + } else { + result.insert(i + 1 + shift, text.charAt(i)); + shift++; + } + } + i++; + } + return result.toString(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ExtendedComboBox.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ExtendedComboBox.java index 3bddb7ea7b..dd5ccdc57c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ExtendedComboBox.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ExtendedComboBox.java @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import javax.swing.*; -import java.awt.*; - -public class ExtendedComboBox extends JComboBox implements Flushable { - - private static final int MAX_LIST_WIDTH = 350; - - private boolean layingOut = false; - private int widestLength = 0; - - private boolean hideButton = false; - - public ExtendedComboBox() { - } - - public void updatePopupWidth() { - widestLength = getWidestItemWidth(); - } - - @Override - public void addItem(Object anObject) { - super.addItem(anObject); - updatePopupWidth(); - } - - @Override - public void insertItemAt(Object anObject, int index) { - super.insertItemAt(anObject, index); - updatePopupWidth(); - } - - @Override - public void removeItem(Object anObject) { - super.removeItem(anObject); - updatePopupWidth(); - } - - @Override - public void removeAllItems() { - super.removeAllItems(); - updatePopupWidth(); - } - - @Override - public void removeItemAt(int anIndex) { - super.removeItemAt(anIndex); - updatePopupWidth(); - } - - @Override - public Dimension getSize() { - Dimension dim = super.getSize(); - if (!layingOut) { - dim.width = Math.max(widestLength, dim.width); - dim.width = Math.min(MAX_LIST_WIDTH, dim.width); - dim.width = Math.max(getWidth(), dim.width); - } - return dim; - } - - public void setButtonVisible(boolean buttonVisible) { - for (Component child : getComponents()) { - if (child instanceof JButton) { - child.setVisible(buttonVisible); - break; - } - } - } - - @Override - public void setEnabled(boolean b) { - if (b == isEnabled()) { - return; - } - - setButtonVisible(!hideButton); - - super.setEnabled(b); - } - - private int getWidestItemWidth() { - if (isVisible() && !layingOut) { - int numOfItems = this.getItemCount(); - Font font = this.getFont(); - FontMetrics metrics = this.getFontMetrics(font); - int widest = 0; - for (int i = 0; i < numOfItems; i++) { - Object item = this.getItemAt(i); - if (item != null) { - String itemString = item.toString(); - if (itemString == null) - itemString = ""; - - int lineWidth = metrics.stringWidth(itemString); - widest = Math.max(widest, lineWidth); - } - } - if (this.getItemCount() > 7) - widest += 12; - return widest + 15; - } else - return getWidth(); - } - - @Override - public void doLayout() { - try { - layingOut = true; - super.doLayout(); - } finally { - layingOut = false; - } - } - - @Override - public void setBackground(Color bg) { - super.setBackground(bg); - if (getEditor() != null && getEditor().getEditorComponent() != null) { - getEditor().getEditorComponent().setBackground(bg); - } - } - - public boolean isHideButton() { - return hideButton; - } - - public void setHideButton(boolean hideButton) { - this.hideButton = hideButton; - } - - @Override - public void flushValue() { - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import javax.swing.*; +import java.awt.*; + +public class ExtendedComboBox extends JComboBox implements Flushable { + + private static final int MAX_LIST_WIDTH = 350; + + private boolean layingOut = false; + private int widestLength = 0; + + private boolean hideButton = false; + + public ExtendedComboBox() { + } + + public void updatePopupWidth() { + widestLength = getWidestItemWidth(); + } + + @Override + public void addItem(Object anObject) { + super.addItem(anObject); + updatePopupWidth(); + } + + @Override + public void insertItemAt(Object anObject, int index) { + super.insertItemAt(anObject, index); + updatePopupWidth(); + } + + @Override + public void removeItem(Object anObject) { + super.removeItem(anObject); + updatePopupWidth(); + } + + @Override + public void removeAllItems() { + super.removeAllItems(); + updatePopupWidth(); + } + + @Override + public void removeItemAt(int anIndex) { + super.removeItemAt(anIndex); + updatePopupWidth(); + } + + @Override + public Dimension getSize() { + Dimension dim = super.getSize(); + if (!layingOut) { + dim.width = Math.max(widestLength, dim.width); + dim.width = Math.min(MAX_LIST_WIDTH, dim.width); + dim.width = Math.max(getWidth(), dim.width); + } + return dim; + } + + public void setButtonVisible(boolean buttonVisible) { + for (Component child : getComponents()) { + if (child instanceof JButton) { + child.setVisible(buttonVisible); + break; + } + } + } + + @Override + public void setEnabled(boolean b) { + if (b == isEnabled()) { + return; + } + + setButtonVisible(!hideButton); + + super.setEnabled(b); + } + + private int getWidestItemWidth() { + if (isVisible() && !layingOut) { + int numOfItems = this.getItemCount(); + Font font = this.getFont(); + FontMetrics metrics = this.getFontMetrics(font); + int widest = 0; + for (int i = 0; i < numOfItems; i++) { + Object item = this.getItemAt(i); + if (item != null) { + String itemString = item.toString(); + if (itemString == null) + itemString = ""; + + int lineWidth = metrics.stringWidth(itemString); + widest = Math.max(widest, lineWidth); + } + } + if (this.getItemCount() > 7) + widest += 12; + return widest + 15; + } else + return getWidth(); + } + + @Override + public void doLayout() { + try { + layingOut = true; + super.doLayout(); + } finally { + layingOut = false; + } + } + + @Override + public void setBackground(Color bg) { + super.setBackground(bg); + if (getEditor() != null && getEditor().getEditorComponent() != null) { + getEditor().getEditorComponent().setBackground(bg); + } + } + + public boolean isHideButton() { + return hideButton; + } + + public void setHideButton(boolean hideButton) { + this.hideButton = hideButton; + } + + @Override + public void flushValue() { + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Flushable.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Flushable.java index 0e3b644a47..6781d97f77 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Flushable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Flushable.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -/** - * Interface for components that can flush value - * - */ -public interface Flushable { - - void flushValue(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +/** + * Interface for components that can flush value + * + */ +public interface Flushable { + + void flushValue(); +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusHelper.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusHelper.java index 7e60fa09df..c10300ab1d 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusHelper.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusHelper.java @@ -1,74 +1,74 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import java.awt.*; - -public abstract class FocusHelper { - - public static void moveFocusToNextControl() { - Component focusOwner = getFocusedComponent(); - moveFocusToNextControl(focusOwner); - } - - public static Component getFocusedComponent() { - KeyboardFocusManager focusManager = - KeyboardFocusManager.getCurrentKeyboardFocusManager(); - - return focusManager.getFocusOwner(); - } - - public static void moveFocusToNextControl(Component focusOwner) { - KeyboardFocusManager focusManager = - KeyboardFocusManager.getCurrentKeyboardFocusManager(); - - Container currentFocusCycleRoot = - focusManager.getCurrentFocusCycleRoot(); - - FocusTraversalPolicy policy = - focusManager.getDefaultFocusTraversalPolicy(); - - if (currentFocusCycleRoot != null || focusOwner != null) { - Component componentAfter = - policy.getComponentAfter(currentFocusCycleRoot, focusOwner); - componentAfter.requestFocus(); - } - } - - public static void moveFocusToPrevControl(Component focusOwner) { - KeyboardFocusManager focusManager = - KeyboardFocusManager.getCurrentKeyboardFocusManager(); - - Container currentFocusCycleRoot = - focusManager.getCurrentFocusCycleRoot(); - - FocusTraversalPolicy policy = - focusManager.getDefaultFocusTraversalPolicy(); - - if (currentFocusCycleRoot != null || focusOwner != null) { - Component componentBefore = - policy.getComponentBefore(currentFocusCycleRoot, focusOwner); - componentBefore.requestFocus(); - } - } - - public static void moveFocusToPrevControl() { - Component focusOwner = getFocusedComponent(); - moveFocusToPrevControl(focusOwner); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import java.awt.*; + +public abstract class FocusHelper { + + public static void moveFocusToNextControl() { + Component focusOwner = getFocusedComponent(); + moveFocusToNextControl(focusOwner); + } + + public static Component getFocusedComponent() { + KeyboardFocusManager focusManager = + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + + return focusManager.getFocusOwner(); + } + + public static void moveFocusToNextControl(Component focusOwner) { + KeyboardFocusManager focusManager = + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + + Container currentFocusCycleRoot = + focusManager.getCurrentFocusCycleRoot(); + + FocusTraversalPolicy policy = + focusManager.getDefaultFocusTraversalPolicy(); + + if (currentFocusCycleRoot != null || focusOwner != null) { + Component componentAfter = + policy.getComponentAfter(currentFocusCycleRoot, focusOwner); + componentAfter.requestFocus(); + } + } + + public static void moveFocusToPrevControl(Component focusOwner) { + KeyboardFocusManager focusManager = + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + + Container currentFocusCycleRoot = + focusManager.getCurrentFocusCycleRoot(); + + FocusTraversalPolicy policy = + focusManager.getDefaultFocusTraversalPolicy(); + + if (currentFocusCycleRoot != null || focusOwner != null) { + Component componentBefore = + policy.getComponentBefore(currentFocusCycleRoot, focusOwner); + componentBefore.requestFocus(); + } + } + + public static void moveFocusToPrevControl() { + Component focusOwner = getFocusedComponent(); + moveFocusToPrevControl(focusOwner); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableComponent.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableComponent.java index ea3904e6e2..ee78a3bfc7 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableComponent.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableComponent.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -/** - * Marker interface for swing components with manual focus ability - * - */ -public interface FocusableComponent { - - void focus(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +/** + * Marker interface for swing components with manual focus ability + * + */ +public interface FocusableComponent { + + void focus(); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableTable.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableTable.java index 72b63940e2..256c615df4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableTable.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/FocusableTable.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -public interface FocusableTable { - - TableFocusManager getFocusManager(); - - void setFocusManager(TableFocusManager focusManager); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +public interface FocusableTable { + + TableFocusManager getFocusManager(); + + void setFocusManager(TableFocusManager focusManager); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTableExt.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTableExt.java index bd2e540df6..4f47232f5c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTableExt.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTableExt.java @@ -1,59 +1,59 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import org.jdesktop.swingx.JXTable; - -import javax.swing.*; -import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; - -public class JXTableExt extends JXTable implements FocusableTable { - - protected TableFocusManager focusManager = new TableFocusManager(this); - - @Override - protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - // ctrl shift keys are not handled by table - if (focusManager.isDisabledKeys(e)) { - return false; - } - - if (focusManager.processKeyBinding(ks, e, condition, pressed)) - return true; - else - return super.processKeyBinding(ks, e, condition, pressed); - } - - @Override - protected void processFocusEvent(FocusEvent e) { - focusManager.processFocusEvent(e); - - super.processFocusEvent(e); - } - - @Override - public TableFocusManager getFocusManager() { - return focusManager; - } - - @Override - public void setFocusManager(TableFocusManager focusManager) { - this.focusManager = focusManager; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import org.jdesktop.swingx.JXTable; + +import javax.swing.*; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; + +public class JXTableExt extends JXTable implements FocusableTable { + + protected TableFocusManager focusManager = new TableFocusManager(this); + + @Override + protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + // ctrl shift keys are not handled by table + if (focusManager.isDisabledKeys(e)) { + return false; + } + + if (focusManager.processKeyBinding(ks, e, condition, pressed)) + return true; + else + return super.processKeyBinding(ks, e, condition, pressed); + } + + @Override + protected void processFocusEvent(FocusEvent e) { + focusManager.processFocusEvent(e); + + super.processFocusEvent(e); + } + + @Override + public TableFocusManager getFocusManager() { + return focusManager; + } + + @Override + public void setFocusManager(TableFocusManager focusManager) { + this.focusManager = focusManager; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTreeTableExt.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTreeTableExt.java index 0162fde664..61274a5a9c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTreeTableExt.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/JXTreeTableExt.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import org.jdesktop.swingx.JXTreeTable; -import org.jdesktop.swingx.treetable.TreeTableModel; - -import javax.swing.*; -import javax.swing.tree.TreePath; -import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.LinkedHashSet; - -public class JXTreeTableExt extends JXTreeTable implements FocusableTable { - - protected HashSet expandedPaths; - - protected TableFocusManager focusManager = new TableFocusManager(this); - - @Override - protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - // ctrl shift keys are not handled by table - if (focusManager.isDisabledKeys(e)) { - return false; - } - - if (focusManager.processKeyBinding(ks, e, condition, pressed)) - return true; - else - return super.processKeyBinding(ks, e, condition, pressed); - } - - @Override - protected void processFocusEvent(FocusEvent e) { - focusManager.processFocusEvent(e); - super.processFocusEvent(e); - } - - public void backupExpandedNodes() { - expandedPaths = new LinkedHashSet<>(); - - TreeTableModel treeTableModel = getTreeTableModel(); - TreePath rootPath = new TreePath(treeTableModel.getRoot()); - Enumeration expandedDescendants = getExpandedDescendants(rootPath); - - if (expandedDescendants != null) { - while (expandedDescendants.hasMoreElements()) { - expandedPaths.add((TreePath) expandedDescendants.nextElement()); - } - } - } - - public void restoreExpandedNodes() { - if ((expandedPaths != null) && (!expandedPaths.isEmpty())) { - for (TreePath expandedPath : expandedPaths) { - int pathRow = getRowForPath(expandedPath); - if (pathRow >= 0) { - expandPath(expandedPath); - } - } - } - expandedPaths = null; - } - - @Override - public TableFocusManager getFocusManager() { - return focusManager; - } - - @Override - public void setFocusManager(TableFocusManager focusManager) { - this.focusManager = focusManager; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.treetable.TreeTableModel; + +import javax.swing.*; +import javax.swing.tree.TreePath; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.LinkedHashSet; + +public class JXTreeTableExt extends JXTreeTable implements FocusableTable { + + protected HashSet expandedPaths; + + protected TableFocusManager focusManager = new TableFocusManager(this); + + @Override + protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + // ctrl shift keys are not handled by table + if (focusManager.isDisabledKeys(e)) { + return false; + } + + if (focusManager.processKeyBinding(ks, e, condition, pressed)) + return true; + else + return super.processKeyBinding(ks, e, condition, pressed); + } + + @Override + protected void processFocusEvent(FocusEvent e) { + focusManager.processFocusEvent(e); + super.processFocusEvent(e); + } + + public void backupExpandedNodes() { + expandedPaths = new LinkedHashSet<>(); + + TreeTableModel treeTableModel = getTreeTableModel(); + TreePath rootPath = new TreePath(treeTableModel.getRoot()); + Enumeration expandedDescendants = getExpandedDescendants(rootPath); + + if (expandedDescendants != null) { + while (expandedDescendants.hasMoreElements()) { + expandedPaths.add((TreePath) expandedDescendants.nextElement()); + } + } + } + + public void restoreExpandedNodes() { + if ((expandedPaths != null) && (!expandedPaths.isEmpty())) { + for (TreePath expandedPath : expandedPaths) { + int pathRow = getRowForPath(expandedPath); + if (pathRow >= 0) { + expandPath(expandedPath); + } + } + } + expandedPaths = null; + } + + @Override + public TableFocusManager getFocusManager() { + return focusManager; + } + + @Override + public void setFocusManager(TableFocusManager focusManager) { + this.focusManager = focusManager; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Picker.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Picker.java index 7cea1efb0f..4e6842bc2b 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Picker.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/Picker.java @@ -1,136 +1,136 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Picker extends JComponent implements FocusableComponent { - - protected JPanel contentPanel; - protected JComponent editor; - protected JPanel actionsPanel; - protected boolean enabled = true; - - protected List buttons = new ArrayList<>(); - - public Picker() { - setLayout(new BorderLayout()); - setPreferredSize(new Dimension(150, DesktopComponentsHelper.FIELD_HEIGHT)); - - initContentPanel(); - add(contentPanel, BorderLayout.CENTER); - - initEditor(); - contentPanel.add(editor, BorderLayout.CENTER); - - initActionsPanel(); - contentPanel.add(actionsPanel, BorderLayout.EAST); - } - - @Override - public void setBackground(Color bg) { - super.setBackground(bg); - - contentPanel.setBackground(bg); - actionsPanel.setBackground(bg); - } - - protected void initContentPanel() { - contentPanel = new JPanel(new BorderLayout()); - } - - protected void initEditor() { - JTextField textField = new JTextField(); - textField.setEditable(false); - editor = textField; - } - - public JComponent getEditor() { - return editor; - } - - public JComponent getInputField(){ - return editor; - } - - protected void initActionsPanel() { - actionsPanel = new JPanel(new MigLayout("hidemode 2, ins 0 0 0 0, gap 0")); - for (JButton button : buttons) { - actionsPanel.add(button); - } - } - - public List getButtons() { - return Collections.unmodifiableList(buttons); - } - - public void addButton(JButton button, int index) { - if (buttons.contains(button)) - return; - - button.setPreferredSize(new Dimension(22, DesktopComponentsHelper.FIELD_HEIGHT)); - button.setMaximumSize(new Dimension(22, Integer.MAX_VALUE)); - - buttons.add(index, button); - actionsPanel.add(button, index); - } - - public void removeButton(JButton button) { - buttons.remove(button); - actionsPanel.remove(button); - } - - public Object getValue() { - return ((JTextField) editor).getText(); - } - - public void setValue(Object value) { - ((JTextField) editor).setText((String) value); - } - - @Override - public void setEnabled(boolean enabled) { - this.enabled = enabled; - editor.setEnabled(enabled); - for (JButton btn : getButtons()) { - btn.setEnabled(enabled); - } - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void requestFocus(){ - editor.requestFocus(); - } - - @Override - public void focus() { - requestFocus(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import net.miginfocom.swing.MigLayout; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Picker extends JComponent implements FocusableComponent { + + protected JPanel contentPanel; + protected JComponent editor; + protected JPanel actionsPanel; + protected boolean enabled = true; + + protected List buttons = new ArrayList<>(); + + public Picker() { + setLayout(new BorderLayout()); + setPreferredSize(new Dimension(150, DesktopComponentsHelper.FIELD_HEIGHT)); + + initContentPanel(); + add(contentPanel, BorderLayout.CENTER); + + initEditor(); + contentPanel.add(editor, BorderLayout.CENTER); + + initActionsPanel(); + contentPanel.add(actionsPanel, BorderLayout.EAST); + } + + @Override + public void setBackground(Color bg) { + super.setBackground(bg); + + contentPanel.setBackground(bg); + actionsPanel.setBackground(bg); + } + + protected void initContentPanel() { + contentPanel = new JPanel(new BorderLayout()); + } + + protected void initEditor() { + JTextField textField = new JTextField(); + textField.setEditable(false); + editor = textField; + } + + public JComponent getEditor() { + return editor; + } + + public JComponent getInputField(){ + return editor; + } + + protected void initActionsPanel() { + actionsPanel = new JPanel(new MigLayout("hidemode 2, ins 0 0 0 0, gap 0")); + for (JButton button : buttons) { + actionsPanel.add(button); + } + } + + public List getButtons() { + return Collections.unmodifiableList(buttons); + } + + public void addButton(JButton button, int index) { + if (buttons.contains(button)) + return; + + button.setPreferredSize(new Dimension(22, DesktopComponentsHelper.FIELD_HEIGHT)); + button.setMaximumSize(new Dimension(22, Integer.MAX_VALUE)); + + buttons.add(index, button); + actionsPanel.add(button, index); + } + + public void removeButton(JButton button) { + buttons.remove(button); + actionsPanel.remove(button); + } + + public Object getValue() { + return ((JTextField) editor).getText(); + } + + public void setValue(Object value) { + ((JTextField) editor).setText((String) value); + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + editor.setEnabled(enabled); + for (JButton btn : getButtons()) { + btn.setEnabled(enabled); + } + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void requestFocus(){ + editor.requestFocus(); + } + + @Override + public void focus() { + requestFocus(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/TableFocusManager.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/TableFocusManager.java index 0097897555..1c5418e4a6 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/TableFocusManager.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/TableFocusManager.java @@ -1,410 +1,410 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import sun.awt.CausedFocusEvent; - -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import java.awt.*; -import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; -import java.util.Set; - -/** - *

Handle focus traversing in table

- *

Supports focus forward, backward, up and down navigation

- * Keys: - *
    - *
  • TAB - next cell/control
  • - *
  • SHIFT+TAB - previous cell/control
  • - *
  • CTRL+TAB - next component after table
  • - *
  • CTRL+SHIFT+TAB - previous component before table
  • - *
- */ -public class TableFocusManager { - - protected JTable impl; - - public TableFocusManager(JTable impl) { - this.impl = impl; - } - - public boolean isDisabledKeys(KeyEvent e) { - return (e.getModifiers() & KeyEvent.CTRL_MASK) > 0 && (e.getModifiers() & KeyEvent.SHIFT_MASK) > 0; - } - - public boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - Set forwardKeys = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalKeys( - KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); - Set backwardKeys = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalKeys( - KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); - if (forwardKeys.contains(ks)) { - if ((e.getModifiers() & KeyEvent.CTRL_MASK) > 0) - moveFocusToNextControl(); - else - nextFocusElement(); - return true; - } else if (backwardKeys.contains(ks)) { - if ((e.getModifiers() & KeyEvent.CTRL_MASK) > 0) - moveFocusToPrevControl(); - else - prevFocusElement(); - return true; - } else if (e.getModifiers() == 0) { -// if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP ) { -// impl.getSelectionModel().setValueIsAdjusting(pressed); -// } - - return processExtraKeyBinding(ks, e, condition, pressed); - } - - return false; - } - - protected boolean processExtraKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - if (e.getKeyCode() == KeyEvent.VK_UP && pressed) { - nextUpElement(); - return true; - } else if (e.getKeyCode() == KeyEvent.VK_DOWN && pressed) { - nextDownElement(); - return true; - } else if (e.getKeyCode() == KeyEvent.VK_LEFT && pressed) { - prevFocusElement(); - return true; - } else if (e.getKeyCode() == KeyEvent.VK_RIGHT && pressed) { - nextFocusElement(); - return true; - } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE && pressed) { - impl.requestFocus(); - impl.editingCanceled(new ChangeEvent(this)); - // allow handle ESCAPE in window - return false; - } else { - return false; - } - } - - public void processFocusEvent(FocusEvent e) { - if (e.getID() == FocusEvent.FOCUS_GAINED) { - if (e instanceof CausedFocusEvent) { - if (((CausedFocusEvent) e).getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) { - if (impl.getModel().getRowCount() > 0) { - // if focus from cell editor - if (e.getSource() == impl && impl.getSelectedRow() >= 0) { - int selectedColumn = impl.getSelectedColumn(); - focusTo(impl.getSelectedRow(), selectedColumn >= 0 ? selectedColumn : 0); - } else - moveToStart(0, 0); - } else - impl.transferFocus(); - - } else if (((CausedFocusEvent) e).getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) { - if (impl.getModel().getRowCount() > 0) { - moveToEnd(impl.getRowCount() - 1, impl.getColumnCount() - 1); - } else - impl.transferFocusBackward(); - } - } - } - } - - /** - * Navigate down throw Table rows - */ - protected void nextDownElement() { - int editingColumn = getActiveColumn(); - int editingRow = getActiveRow(); - int nextRow = editingRow + 1; - if (editingRow == -1) { - return; - } - if (editingColumn == -1) { - editingColumn = 0; - } - if (nextRow > impl.getRowCount() - 1) { - nextRow = 0; - } - moveToStart(nextRow, editingColumn); - } - - /** - * Navigate up throw Table rows - */ - protected void nextUpElement() { - int editingColumn = getActiveColumn(); - int editingRow = getActiveRow(); - int nextRow = editingRow - 1; - if (editingRow == -1) { - return; - } - if (editingColumn == -1) { - editingColumn = 0; - } - if (nextRow == -1) { - nextRow = impl.getRowCount() - 1; - } - moveToStart(nextRow, editingColumn); - } - - /** - * Navigate to prev active control or cell in table - */ - public void prevFocusElement() { - int selectedColumn = getActiveColumn(); - int selectedRow = getActiveRow(); - int prevColumn = selectedColumn - 1; - int prevRow = selectedRow; - if (selectedColumn == -1) { - selectedColumn = 0; - } - - if (selectedRow == -1) { - if (impl.getModel().getRowCount() > 0) { - moveToEnd(impl.getRowCount() - 1, impl.getColumnCount() - 1); - } else - moveFocusToPrevControl(); - return; - } - - if (selectedColumn == 0) { - prevColumn = impl.getColumnCount() - 1; - prevRow = selectedRow - 1; - } - - JComponent activeComponent = getActiveComponent(); - boolean wasMoved = false; - if (activeComponent != null) { - wasMoved = moveFocusPrevIntoComponent(activeComponent); - } - - if (!wasMoved) { - if (prevRow < 0) - impl.transferFocusBackward(); - else - moveToEnd(prevRow, prevColumn); - } - } - - /** - * Navigate to previous active control or cell in table - */ - public void nextFocusElement() { - int selectedColumn = getActiveColumn(); - int selectedRow = getActiveRow(); - int nextColumn = selectedColumn + 1; - int nextRow = selectedRow; - if (selectedColumn == -1) { - selectedColumn = 0; - } - - if (selectedRow == -1) { - if (impl.getModel().getRowCount() > 0) { - moveToStart(0, 0); - } else - moveFocusToNextControl(); - - return; - } - if (selectedColumn == impl.getColumnCount() - 1) { - nextColumn = 0; - nextRow = selectedRow + 1; - } - - JComponent activeComponent = getActiveComponent(); - boolean wasMoved = false; - if (activeComponent != null) { - wasMoved = moveFocusNextIntoComponent(activeComponent); - } - - if (!wasMoved) { - if (nextRow > impl.getRowCount() - 1) - impl.transferFocus(); - else - moveToStart(nextRow, nextColumn); - } - } - - /** - * Focus first cell in specified row - * - * @param selectedRow Focused row - */ - public void focusSelectedRow(int selectedRow) { - if (impl.getModel().getRowCount() > 0) { - focusTo(selectedRow, 0); - } else { - moveFocusToNextControl(); - } - } - - /** - * Scroll to first cell in specified row - * - * @param selectedRow row - */ - public void scrollToSelectedRow(int selectedRow) { - if (impl.getModel().getRowCount() > 0) { - scrollTo(selectedRow, 0); - } - } - - protected void moveTo(int row, int col) { - Component editorComp = impl.getEditorComponent(); - - if (editorComp != null) { - editorComp.dispatchEvent(new FocusEvent(editorComp, FocusEvent.FOCUS_LOST, false, impl)); - } - impl.scrollRectToVisible(impl.getCellRect(row, col, true)); - - if (row >= 0 && col >= 0) - impl.requestFocus(); - - impl.getSelectionModel().setSelectionInterval(row, row); - impl.getColumnModel().getSelectionModel().setSelectionInterval(col, col); - impl.editCellAt( - impl.getSelectedRow(), - impl.getSelectedColumn() - ); - } - - protected void focusTo(int row, int col) { - if (row >= 0) { - impl.requestFocus(); - - impl.getSelectionModel().setSelectionInterval(row, row); - impl.getColumnModel().getSelectionModel().setSelectionInterval(col, col); - - scrollTo(row, col); - } - } - - protected void scrollTo(int row, int col) { - if (row >= 0) { - Rectangle cellRect = impl.getCellRect(row, col, true); - impl.scrollRectToVisible(cellRect); - } - } - - protected void moveToStart(int row, int col) { - moveTo(row, col); - JComponent newEditorComp = (JComponent) impl.getEditorComponent(); - - if (newEditorComp != null) { - newEditorComp.requestFocusInWindow(); - KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); - Component component = defaultFocusTraversalPolicy.getFirstComponent(newEditorComp); - - if (component != null) - component.requestFocus(); - } - } - - protected void moveToEnd(int row, int col) { - moveTo(row, col); - JComponent newEditorComp = (JComponent) impl.getEditorComponent(); - - if (newEditorComp != null) { - newEditorComp.requestFocusInWindow(); - KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); - Component component = defaultFocusTraversalPolicy.getLastComponent(newEditorComp); - - if (component != null) - component.requestFocus(); - } - } - - protected JComponent getActiveComponent() { - return (JComponent) impl.getEditorComponent(); - } - - protected int getActiveColumn() { - int editingColumn = impl.getEditingColumn(); - int selectedColumn = impl.getSelectedColumn(); - if (editingColumn < 0) - return selectedColumn; - else - return editingColumn; - } - - protected int getActiveRow() { - int editingRow = impl.getEditingColumn() == -1 ? -1 : impl.getEditingRow(); - int selectedRow = impl.getSelectedRow(); - if (editingRow < 0) - return selectedRow; - else - return editingRow; - } - - protected boolean moveFocusNextIntoComponent(Container activeComponent) { - KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Component focusOwner = focusManager.getFocusOwner(); - FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); - Component lastComponent = defaultFocusTraversalPolicy.getLastComponent(activeComponent); - if (focusOwner != null && - lastComponent != null && - lastComponent != focusOwner) { - if (focusOwner == impl) { - Component component = defaultFocusTraversalPolicy.getFirstComponent(activeComponent); - if (component != null) - component.requestFocus(); - else - moveFocusToNextControl(); - } else { - moveFocusToNextControl(); - } - - return true; - } - - return false; - } - - protected boolean moveFocusPrevIntoComponent(JComponent activeComponent) { - KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Component focusOwner = focusManager.getFocusOwner(); - FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); - Component firstComponent = defaultFocusTraversalPolicy.getFirstComponent(activeComponent); - if (focusOwner != null && - firstComponent != null && - firstComponent != focusOwner) { - if (focusOwner == impl) { - Component component = defaultFocusTraversalPolicy.getLastComponent(activeComponent); - if (component != null) - component.requestFocus(); - else - moveFocusToPrevControl(); - } else - moveFocusToPrevControl(); - - return true; - } - - return false; - } - - protected void moveFocusToNextControl() { - FocusHelper.moveFocusToNextControl(); - } - - protected void moveFocusToPrevControl() { - FocusHelper.moveFocusToPrevControl(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import sun.awt.CausedFocusEvent; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.Set; + +/** + *

Handle focus traversing in table

+ *

Supports focus forward, backward, up and down navigation

+ * Keys: + *
    + *
  • TAB - next cell/control
  • + *
  • SHIFT+TAB - previous cell/control
  • + *
  • CTRL+TAB - next component after table
  • + *
  • CTRL+SHIFT+TAB - previous component before table
  • + *
+ */ +public class TableFocusManager { + + protected JTable impl; + + public TableFocusManager(JTable impl) { + this.impl = impl; + } + + public boolean isDisabledKeys(KeyEvent e) { + return (e.getModifiers() & KeyEvent.CTRL_MASK) > 0 && (e.getModifiers() & KeyEvent.SHIFT_MASK) > 0; + } + + public boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + Set forwardKeys = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalKeys( + KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + Set backwardKeys = KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalKeys( + KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + if (forwardKeys.contains(ks)) { + if ((e.getModifiers() & KeyEvent.CTRL_MASK) > 0) + moveFocusToNextControl(); + else + nextFocusElement(); + return true; + } else if (backwardKeys.contains(ks)) { + if ((e.getModifiers() & KeyEvent.CTRL_MASK) > 0) + moveFocusToPrevControl(); + else + prevFocusElement(); + return true; + } else if (e.getModifiers() == 0) { +// if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP ) { +// impl.getSelectionModel().setValueIsAdjusting(pressed); +// } + + return processExtraKeyBinding(ks, e, condition, pressed); + } + + return false; + } + + protected boolean processExtraKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { + if (e.getKeyCode() == KeyEvent.VK_UP && pressed) { + nextUpElement(); + return true; + } else if (e.getKeyCode() == KeyEvent.VK_DOWN && pressed) { + nextDownElement(); + return true; + } else if (e.getKeyCode() == KeyEvent.VK_LEFT && pressed) { + prevFocusElement(); + return true; + } else if (e.getKeyCode() == KeyEvent.VK_RIGHT && pressed) { + nextFocusElement(); + return true; + } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE && pressed) { + impl.requestFocus(); + impl.editingCanceled(new ChangeEvent(this)); + // allow handle ESCAPE in window + return false; + } else { + return false; + } + } + + public void processFocusEvent(FocusEvent e) { + if (e.getID() == FocusEvent.FOCUS_GAINED) { + if (e instanceof CausedFocusEvent) { + if (((CausedFocusEvent) e).getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) { + if (impl.getModel().getRowCount() > 0) { + // if focus from cell editor + if (e.getSource() == impl && impl.getSelectedRow() >= 0) { + int selectedColumn = impl.getSelectedColumn(); + focusTo(impl.getSelectedRow(), selectedColumn >= 0 ? selectedColumn : 0); + } else + moveToStart(0, 0); + } else + impl.transferFocus(); + + } else if (((CausedFocusEvent) e).getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) { + if (impl.getModel().getRowCount() > 0) { + moveToEnd(impl.getRowCount() - 1, impl.getColumnCount() - 1); + } else + impl.transferFocusBackward(); + } + } + } + } + + /** + * Navigate down throw Table rows + */ + protected void nextDownElement() { + int editingColumn = getActiveColumn(); + int editingRow = getActiveRow(); + int nextRow = editingRow + 1; + if (editingRow == -1) { + return; + } + if (editingColumn == -1) { + editingColumn = 0; + } + if (nextRow > impl.getRowCount() - 1) { + nextRow = 0; + } + moveToStart(nextRow, editingColumn); + } + + /** + * Navigate up throw Table rows + */ + protected void nextUpElement() { + int editingColumn = getActiveColumn(); + int editingRow = getActiveRow(); + int nextRow = editingRow - 1; + if (editingRow == -1) { + return; + } + if (editingColumn == -1) { + editingColumn = 0; + } + if (nextRow == -1) { + nextRow = impl.getRowCount() - 1; + } + moveToStart(nextRow, editingColumn); + } + + /** + * Navigate to prev active control or cell in table + */ + public void prevFocusElement() { + int selectedColumn = getActiveColumn(); + int selectedRow = getActiveRow(); + int prevColumn = selectedColumn - 1; + int prevRow = selectedRow; + if (selectedColumn == -1) { + selectedColumn = 0; + } + + if (selectedRow == -1) { + if (impl.getModel().getRowCount() > 0) { + moveToEnd(impl.getRowCount() - 1, impl.getColumnCount() - 1); + } else + moveFocusToPrevControl(); + return; + } + + if (selectedColumn == 0) { + prevColumn = impl.getColumnCount() - 1; + prevRow = selectedRow - 1; + } + + JComponent activeComponent = getActiveComponent(); + boolean wasMoved = false; + if (activeComponent != null) { + wasMoved = moveFocusPrevIntoComponent(activeComponent); + } + + if (!wasMoved) { + if (prevRow < 0) + impl.transferFocusBackward(); + else + moveToEnd(prevRow, prevColumn); + } + } + + /** + * Navigate to previous active control or cell in table + */ + public void nextFocusElement() { + int selectedColumn = getActiveColumn(); + int selectedRow = getActiveRow(); + int nextColumn = selectedColumn + 1; + int nextRow = selectedRow; + if (selectedColumn == -1) { + selectedColumn = 0; + } + + if (selectedRow == -1) { + if (impl.getModel().getRowCount() > 0) { + moveToStart(0, 0); + } else + moveFocusToNextControl(); + + return; + } + if (selectedColumn == impl.getColumnCount() - 1) { + nextColumn = 0; + nextRow = selectedRow + 1; + } + + JComponent activeComponent = getActiveComponent(); + boolean wasMoved = false; + if (activeComponent != null) { + wasMoved = moveFocusNextIntoComponent(activeComponent); + } + + if (!wasMoved) { + if (nextRow > impl.getRowCount() - 1) + impl.transferFocus(); + else + moveToStart(nextRow, nextColumn); + } + } + + /** + * Focus first cell in specified row + * + * @param selectedRow Focused row + */ + public void focusSelectedRow(int selectedRow) { + if (impl.getModel().getRowCount() > 0) { + focusTo(selectedRow, 0); + } else { + moveFocusToNextControl(); + } + } + + /** + * Scroll to first cell in specified row + * + * @param selectedRow row + */ + public void scrollToSelectedRow(int selectedRow) { + if (impl.getModel().getRowCount() > 0) { + scrollTo(selectedRow, 0); + } + } + + protected void moveTo(int row, int col) { + Component editorComp = impl.getEditorComponent(); + + if (editorComp != null) { + editorComp.dispatchEvent(new FocusEvent(editorComp, FocusEvent.FOCUS_LOST, false, impl)); + } + impl.scrollRectToVisible(impl.getCellRect(row, col, true)); + + if (row >= 0 && col >= 0) + impl.requestFocus(); + + impl.getSelectionModel().setSelectionInterval(row, row); + impl.getColumnModel().getSelectionModel().setSelectionInterval(col, col); + impl.editCellAt( + impl.getSelectedRow(), + impl.getSelectedColumn() + ); + } + + protected void focusTo(int row, int col) { + if (row >= 0) { + impl.requestFocus(); + + impl.getSelectionModel().setSelectionInterval(row, row); + impl.getColumnModel().getSelectionModel().setSelectionInterval(col, col); + + scrollTo(row, col); + } + } + + protected void scrollTo(int row, int col) { + if (row >= 0) { + Rectangle cellRect = impl.getCellRect(row, col, true); + impl.scrollRectToVisible(cellRect); + } + } + + protected void moveToStart(int row, int col) { + moveTo(row, col); + JComponent newEditorComp = (JComponent) impl.getEditorComponent(); + + if (newEditorComp != null) { + newEditorComp.requestFocusInWindow(); + KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); + Component component = defaultFocusTraversalPolicy.getFirstComponent(newEditorComp); + + if (component != null) + component.requestFocus(); + } + } + + protected void moveToEnd(int row, int col) { + moveTo(row, col); + JComponent newEditorComp = (JComponent) impl.getEditorComponent(); + + if (newEditorComp != null) { + newEditorComp.requestFocusInWindow(); + KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); + Component component = defaultFocusTraversalPolicy.getLastComponent(newEditorComp); + + if (component != null) + component.requestFocus(); + } + } + + protected JComponent getActiveComponent() { + return (JComponent) impl.getEditorComponent(); + } + + protected int getActiveColumn() { + int editingColumn = impl.getEditingColumn(); + int selectedColumn = impl.getSelectedColumn(); + if (editingColumn < 0) + return selectedColumn; + else + return editingColumn; + } + + protected int getActiveRow() { + int editingRow = impl.getEditingColumn() == -1 ? -1 : impl.getEditingRow(); + int selectedRow = impl.getSelectedRow(); + if (editingRow < 0) + return selectedRow; + else + return editingRow; + } + + protected boolean moveFocusNextIntoComponent(Container activeComponent) { + KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + Component focusOwner = focusManager.getFocusOwner(); + FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); + Component lastComponent = defaultFocusTraversalPolicy.getLastComponent(activeComponent); + if (focusOwner != null && + lastComponent != null && + lastComponent != focusOwner) { + if (focusOwner == impl) { + Component component = defaultFocusTraversalPolicy.getFirstComponent(activeComponent); + if (component != null) + component.requestFocus(); + else + moveFocusToNextControl(); + } else { + moveFocusToNextControl(); + } + + return true; + } + + return false; + } + + protected boolean moveFocusPrevIntoComponent(JComponent activeComponent) { + KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + Component focusOwner = focusManager.getFocusOwner(); + FocusTraversalPolicy defaultFocusTraversalPolicy = focusManager.getDefaultFocusTraversalPolicy(); + Component firstComponent = defaultFocusTraversalPolicy.getFirstComponent(activeComponent); + if (focusOwner != null && + firstComponent != null && + firstComponent != focusOwner) { + if (focusOwner == impl) { + Component component = defaultFocusTraversalPolicy.getLastComponent(activeComponent); + if (component != null) + component.requestFocus(); + else + moveFocusToPrevControl(); + } else + moveFocusToPrevControl(); + + return true; + } + + return false; + } + + protected void moveFocusToNextControl() { + FocusHelper.moveFocusToNextControl(); + } + + protected void moveFocusToPrevControl() { + FocusHelper.moveFocusToPrevControl(); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ToolTipButton.java b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ToolTipButton.java index f984d8c00f..88a61c4aaf 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ToolTipButton.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/sys/vcl/ToolTipButton.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import org.jdesktop.swingx.JXHyperlink; - -import javax.swing.*; - -/** - * Button is used together with field to display field's tooltip - * - * - */ -public class ToolTipButton extends JXHyperlink { - - public ToolTipButton() { - setText("[?]"); - setFocusable(false); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import org.jdesktop.swingx.JXHyperlink; + +import javax.swing.*; + +/** + * Button is used together with field to display field's tooltip + * + * + */ +public class ToolTipButton extends JXHyperlink { + + public ToolTipButton() { + setText("[?]"); + setFocusable(false); + } +} diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/ComponentDecorator.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/ComponentDecorator.java index f07694eb46..429896bbf4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/ComponentDecorator.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/ComponentDecorator.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme; - -import java.util.Set; - -public interface ComponentDecorator { - /* - * Accepts cuba component, if style is applied to it, - * or awt component, if style applied via Table.StyleProvider - */ - void decorate(Object component, Set state); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme; + +import java.util.Set; + +public interface ComponentDecorator { + /* + * Accepts cuba component, if style is applied to it, + * or awt component, if style applied via Table.StyleProvider + */ + void decorate(Object component, Set state); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopTheme.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopTheme.java index 64b78617ae..e6bc2dbfb1 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopTheme.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopTheme.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme; - -import com.haulmont.cuba.desktop.DesktopResources; - -import java.util.Set; - -public interface DesktopTheme { - - /** - * @return name of theme - */ - String getName(); - - /** - * Invoke this method before any UI components initialization. - * Theme sets up look and feel, assigns UI defaults overrides. - */ - void init(); - - /** - * Apply style to CUBA, swing or AWT component. - * - * @param component component - * @param styleName space-separated list of styles to apply - */ - void applyStyle(Object component, String styleName); - - /** - * Apply style to CUBA, swing or AWT component. - * This method is used by table style providers to reflect focus and selection states. - * - * @param component component - * @param styleName space-separated list of styles to apply - * @param state set of strings describing internal swing component state - */ - void applyStyle(Object component, String styleName, Set state); - - /** - * Return resources associated with theme. - * - * @return resources - */ - DesktopResources getResources(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme; + +import com.haulmont.cuba.desktop.DesktopResources; + +import java.util.Set; + +public interface DesktopTheme { + + /** + * @return name of theme + */ + String getName(); + + /** + * Invoke this method before any UI components initialization. + * Theme sets up look and feel, assigns UI defaults overrides. + */ + void init(); + + /** + * Apply style to CUBA, swing or AWT component. + * + * @param component component + * @param styleName space-separated list of styles to apply + */ + void applyStyle(Object component, String styleName); + + /** + * Apply style to CUBA, swing or AWT component. + * This method is used by table style providers to reflect focus and selection states. + * + * @param component component + * @param styleName space-separated list of styles to apply + * @param state set of strings describing internal swing component state + */ + void applyStyle(Object component, String styleName, Set state); + + /** + * Return resources associated with theme. + * + * @return resources + */ + DesktopResources getResources(); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopThemeLoader.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopThemeLoader.java index 4b3df44b16..523e8fcfdc 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopThemeLoader.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/DesktopThemeLoader.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme; - -public interface DesktopThemeLoader { - String NAME = "cuba_DesktopThemeLoader"; - - DesktopTheme loadTheme(String theme); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme; + +public interface DesktopThemeLoader { + String NAME = "cuba_DesktopThemeLoader"; + + DesktopTheme loadTheme(String theme); } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/CustomDecorator.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/CustomDecorator.java index 1eb38ed0d2..af5ecf9238 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/CustomDecorator.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/CustomDecorator.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Scripting; -import com.haulmont.cuba.desktop.theme.ComponentDecorator; - -import java.util.Set; - -public class CustomDecorator implements ComponentDecorator { - - private Class decoratorClass; - - public CustomDecorator(String className) { - this.decoratorClass = AppBeans.get(Scripting.class).loadClassNN(className); - } - - @Override - public void decorate(Object component, Set state) { - try { - ComponentDecorator delegate = (ComponentDecorator) decoratorClass.newInstance(); - delegate.decorate(component, state); - } - catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Scripting; +import com.haulmont.cuba.desktop.theme.ComponentDecorator; + +import java.util.Set; + +public class CustomDecorator implements ComponentDecorator { + + private Class decoratorClass; + + public CustomDecorator(String className) { + this.decoratorClass = AppBeans.get(Scripting.class).loadClassNN(className); + } + + @Override + public void decorate(Object component, Set state) { + try { + ComponentDecorator delegate = (ComponentDecorator) decoratorClass.newInstance(); + delegate.decorate(component, state); + } + catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopStyle.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopStyle.java index 1fb218fcc6..2301343eda 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopStyle.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopStyle.java @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.desktop.theme.ComponentDecorator; - -import java.util.List; - -public class DesktopStyle { - - private String name; - private List decorators; - private List supportedComponents; - - public DesktopStyle(String name, List decorators, List supportedComponents) { - this.name = name; - this.decorators = decorators; - this.supportedComponents = supportedComponents; - } - - /* - * If not specified supported components than supports all - */ - public boolean isSupported(Class componentClass) { - if (supportedComponents == null || supportedComponents.isEmpty()) { - return true; - } - - return supportedComponents.contains(componentClass); - } - - public String getName() { - return name; - } - - public List getDecorators() { - return decorators; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.desktop.theme.ComponentDecorator; + +import java.util.List; + +public class DesktopStyle { + + private String name; + private List decorators; + private List supportedComponents; + + public DesktopStyle(String name, List decorators, List supportedComponents) { + this.name = name; + this.decorators = decorators; + this.supportedComponents = supportedComponents; + } + + /* + * If not specified supported components than supports all + */ + public boolean isSupported(Class componentClass) { + if (supportedComponents == null || supportedComponents.isEmpty()) { + return true; + } + + return supportedComponents.contains(componentClass); + } + + public String getName() { + return name; + } + + public List getDecorators() { + return decorators; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeImpl.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeImpl.java index e1eabae984..c784a6a44a 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeImpl.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeImpl.java @@ -1,204 +1,204 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.desktop.DesktopResources; -import com.haulmont.cuba.desktop.theme.ComponentDecorator; -import com.haulmont.cuba.desktop.theme.DesktopTheme; -import net.miginfocom.layout.PlatformDefaults; -import net.miginfocom.layout.UnitValue; -import org.apache.commons.lang.text.StrTokenizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.swing.*; -import java.util.*; - -public class DesktopThemeImpl implements DesktopTheme { - - private String name; - - private String lookAndFeel; - - private Map uiDefaults; - - private Map> styles; - - private DesktopResources resources; - - private Logger log = LoggerFactory.getLogger(DesktopThemeImpl.class); - - /** - * we can control margin & spacing sizes with help of {@link net.miginfocom.layout.PlatformDefaults} class. - */ - private Integer marginSize; - - private Integer spacingSize; - - public DesktopThemeImpl() { - this.uiDefaults = new HashMap<>(); - this.styles = new HashMap<>(); - } - - public void setName(String name) { - this.name = name; - } - - @Override - public DesktopResources getResources() { - return resources; - } - - public void setResources(DesktopResources resources) { - this.resources = resources; - } - - public Map getUiDefaults() { - return uiDefaults; - } - - public Map> getStyles() { - return styles; - } - - public String getLookAndFeel() { - return lookAndFeel; - } - - public void setLookAndFeel(String lookAndFeel) { - this.lookAndFeel = lookAndFeel; - } - - @Override - public String getName() { - return name; - } - - @Override - public void init() { - JDialog.setDefaultLookAndFeelDecorated(true); - JFrame.setDefaultLookAndFeelDecorated(true); - - try { - UIManager.setLookAndFeel(lookAndFeel); - initUIDefaults(); - initButtonsKeyBinding(); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException - | UnsupportedLookAndFeelException e) { - throw new RuntimeException(e); - } - - if (marginSize != null) { - UnitValue marginValue = new UnitValue(marginSize); - PlatformDefaults.setPanelInsets(marginValue, marginValue, marginValue, marginValue); - } - - if (spacingSize != null) { - UnitValue spacingValue = new UnitValue(spacingSize); - PlatformDefaults.setGridCellGap(spacingValue, spacingValue); - } - } - - protected void initButtonsKeyBinding() { - InputMap im = (InputMap) UIManager.get("Button.focusInputMap"); - im.put(KeyStroke.getKeyStroke("ENTER"), "pressed"); - im.put(KeyStroke.getKeyStroke("released ENTER"), "released"); - } - - protected void initUIDefaults() { - for (String propertyName : uiDefaults.keySet()) { - UIManager.getLookAndFeelDefaults().put(propertyName, uiDefaults.get(propertyName)); - } - } - - @Override - public void applyStyle(Object component, String styleName) { - applyStyle(component, styleName, null); - } - - @Override - public void applyStyle(Object component, String styleNameString, Set state) { - // split string into individual style names - StrTokenizer tokenizer = new StrTokenizer(styleNameString); - String[] styleNames = tokenizer.getTokenArray(); - for (String styleName : styleNames) { - applyStyleName(component, state, styleName); - } - } - - private void applyStyleName(Object component, Set state, String styleName) { - DesktopStyle style = findStyle(component.getClass(), styleName); - if (style == null) { - if (log.isDebugEnabled()) { - log.debug("Can not find style " + styleName + " for component " + component); - } - return; - } - - for (ComponentDecorator decorator : style.getDecorators()) { - try { - decorator.decorate(component, state); - } catch (Exception e) { - log.error("Error applying decorator " + decorator + " to " + component, e); - } - } - } - - @Nullable - private DesktopStyle findStyle(Class componentClass, String styleName) { - List stylesByName = styles.get(styleName); - if (stylesByName == null) { - return null; - } - for (DesktopStyle desktopStyle : stylesByName) { - if (desktopStyle.isSupported(componentClass)) { - return desktopStyle; - } - } - return null; - } - - public void setStyles(Map> styles) { - this.styles = styles; - } - - /** - * Add style to theme. Adding any subsequent style with the same name will override existing styles. - * - * @param style style to add - */ - public void addStyle(DesktopStyle style) { - List list = styles.get(style.getName()); - if (list != null) { - list.add(0, style); - } else { - list = new ArrayList<>(); - list.add(style); - styles.put(style.getName(), list); - } - } - - public void setMarginSize(Integer marginSize) { - this.marginSize = marginSize; - } - - public void setSpacingSize(Integer spacingSize) { - this.spacingSize = spacingSize; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.desktop.DesktopResources; +import com.haulmont.cuba.desktop.theme.ComponentDecorator; +import com.haulmont.cuba.desktop.theme.DesktopTheme; +import net.miginfocom.layout.PlatformDefaults; +import net.miginfocom.layout.UnitValue; +import org.apache.commons.lang.text.StrTokenizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.util.*; + +public class DesktopThemeImpl implements DesktopTheme { + + private String name; + + private String lookAndFeel; + + private Map uiDefaults; + + private Map> styles; + + private DesktopResources resources; + + private Logger log = LoggerFactory.getLogger(DesktopThemeImpl.class); + + /** + * we can control margin & spacing sizes with help of {@link net.miginfocom.layout.PlatformDefaults} class. + */ + private Integer marginSize; + + private Integer spacingSize; + + public DesktopThemeImpl() { + this.uiDefaults = new HashMap<>(); + this.styles = new HashMap<>(); + } + + public void setName(String name) { + this.name = name; + } + + @Override + public DesktopResources getResources() { + return resources; + } + + public void setResources(DesktopResources resources) { + this.resources = resources; + } + + public Map getUiDefaults() { + return uiDefaults; + } + + public Map> getStyles() { + return styles; + } + + public String getLookAndFeel() { + return lookAndFeel; + } + + public void setLookAndFeel(String lookAndFeel) { + this.lookAndFeel = lookAndFeel; + } + + @Override + public String getName() { + return name; + } + + @Override + public void init() { + JDialog.setDefaultLookAndFeelDecorated(true); + JFrame.setDefaultLookAndFeelDecorated(true); + + try { + UIManager.setLookAndFeel(lookAndFeel); + initUIDefaults(); + initButtonsKeyBinding(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e) { + throw new RuntimeException(e); + } + + if (marginSize != null) { + UnitValue marginValue = new UnitValue(marginSize); + PlatformDefaults.setPanelInsets(marginValue, marginValue, marginValue, marginValue); + } + + if (spacingSize != null) { + UnitValue spacingValue = new UnitValue(spacingSize); + PlatformDefaults.setGridCellGap(spacingValue, spacingValue); + } + } + + protected void initButtonsKeyBinding() { + InputMap im = (InputMap) UIManager.get("Button.focusInputMap"); + im.put(KeyStroke.getKeyStroke("ENTER"), "pressed"); + im.put(KeyStroke.getKeyStroke("released ENTER"), "released"); + } + + protected void initUIDefaults() { + for (String propertyName : uiDefaults.keySet()) { + UIManager.getLookAndFeelDefaults().put(propertyName, uiDefaults.get(propertyName)); + } + } + + @Override + public void applyStyle(Object component, String styleName) { + applyStyle(component, styleName, null); + } + + @Override + public void applyStyle(Object component, String styleNameString, Set state) { + // split string into individual style names + StrTokenizer tokenizer = new StrTokenizer(styleNameString); + String[] styleNames = tokenizer.getTokenArray(); + for (String styleName : styleNames) { + applyStyleName(component, state, styleName); + } + } + + private void applyStyleName(Object component, Set state, String styleName) { + DesktopStyle style = findStyle(component.getClass(), styleName); + if (style == null) { + if (log.isDebugEnabled()) { + log.debug("Can not find style " + styleName + " for component " + component); + } + return; + } + + for (ComponentDecorator decorator : style.getDecorators()) { + try { + decorator.decorate(component, state); + } catch (Exception e) { + log.error("Error applying decorator " + decorator + " to " + component, e); + } + } + } + + @Nullable + private DesktopStyle findStyle(Class componentClass, String styleName) { + List stylesByName = styles.get(styleName); + if (stylesByName == null) { + return null; + } + for (DesktopStyle desktopStyle : stylesByName) { + if (desktopStyle.isSupported(componentClass)) { + return desktopStyle; + } + } + return null; + } + + public void setStyles(Map> styles) { + this.styles = styles; + } + + /** + * Add style to theme. Adding any subsequent style with the same name will override existing styles. + * + * @param style style to add + */ + public void addStyle(DesktopStyle style) { + List list = styles.get(style.getName()); + if (list != null) { + list.add(0, style); + } else { + list = new ArrayList<>(); + list.add(style); + styles.put(style.getName(), list); + } + } + + public void setMarginSize(Integer marginSize) { + this.marginSize = marginSize; + } + + public void setSpacingSize(Integer spacingSize) { + this.spacingSize = spacingSize; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeLoaderImpl.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeLoaderImpl.java index b086c7c59e..c50298e90c 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeLoaderImpl.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/DesktopThemeLoaderImpl.java @@ -1,521 +1,521 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.core.global.Resources; -import com.haulmont.cuba.desktop.DesktopConfig; -import com.haulmont.cuba.desktop.DesktopResources; -import com.haulmont.cuba.desktop.theme.ComponentDecorator; -import com.haulmont.cuba.desktop.theme.DesktopTheme; -import com.haulmont.cuba.desktop.theme.DesktopThemeLoader; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.springframework.core.io.Resource; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; -import javax.swing.*; -import javax.swing.border.Border; -import java.awt.*; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Component(DesktopThemeLoader.NAME) -public class DesktopThemeLoaderImpl implements DesktopThemeLoader { - - private static final String BORDER_TAG = "border"; - - @Inject - private DesktopConfig config; - - @Inject - private Resources resources; - - private final Logger log = LoggerFactory.getLogger(DesktopThemeLoaderImpl.class); - - // like '255 128 0' - private static final Pattern DECIMAL_COLOR_PATTERN = Pattern.compile("^(\\d+)\\s+(\\d+)\\s+(\\d+)$"); - - @Override - public DesktopTheme loadTheme(String themeName) { - String themeLocations = config.getResourceLocations(); - StrTokenizer tokenizer = new StrTokenizer(themeLocations); - String[] locationList = tokenizer.getTokenArray(); - - List resourceLocationList = new ArrayList<>(); - DesktopThemeImpl theme = createTheme(themeName, locationList); - theme.setName(themeName); - for (String location : locationList) { - resourceLocationList.add(getResourcesDir(themeName, location)); - - String xmlLocation = getConfigFileName(themeName, location); - Resource resource = resources.getResource(xmlLocation); - if (resource.exists()) { - try { - loadThemeFromXml(theme, resource); - } catch (IOException e) { - log.error("Error", e); - } - } else { - log.warn("Resource " + location + " not found, ignore it"); - } - } - - DesktopResources desktopResources = new DesktopResources(resourceLocationList, resources); - theme.setResources(desktopResources); - - return theme; - } - - // read config files and search for element which should contain custom theme class - private DesktopThemeImpl createTheme(String themeName, String[] locationList) { - String themeClassName = null; - for (String location : locationList) { - String xmlLocation = getConfigFileName(themeName, location); - Resource resource = resources.getResource(xmlLocation); - if (resource.exists()) { - try { - Document doc = readXmlDocument(resource); - final Element rootElement = doc.getRootElement(); - - List classElements = rootElement.elements("class"); - if (!classElements.isEmpty()) { - themeClassName = classElements.get(0).getTextTrim(); - } - } catch (IOException e) { - log.error("Error", e); - } - } else { - log.warn("Resource " + location + " not found, ignore it"); - } - } - if (themeClassName != null) { - try { - Class themeClass = Class.forName(themeClassName); - return (DesktopThemeImpl) themeClass.newInstance(); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { - throw new RuntimeException(e); - } - } - return new DesktopThemeImpl(); - } - - private String getResourcesDir(String themeName, String location) { - return location + "/" + themeName; - } - - private String getConfigFileName(String themeName, String location) { - return location + "/" + themeName + "/" + themeName + ".xml"; - } - - private void loadThemeFromXml(DesktopThemeImpl theme, Resource resource) throws IOException { - log.info("Loading theme file " + resource.getURL()); - - Document doc = readXmlDocument(resource); - final Element rootElement = doc.getRootElement(); - - for (Element element : (List) rootElement.elements()) { - String elementName = element.getName(); - if ("lookAndFeel".equals(elementName)) { - String lookAndFeel = element.getTextTrim(); - if (StringUtils.isNotEmpty(lookAndFeel)) { - theme.setLookAndFeel(lookAndFeel); - } - } else if ("ui-defaults".equals(elementName)) { - loadUIDefaults(theme.getUiDefaults(), element); - } else if ("layout".equals(elementName)) { - loadLayoutSettings(theme, element); - } else if ("style".equals(elementName)) { - DesktopStyle style = loadStyle(element); - theme.addStyle(style); - } else if ("include".equals(elementName)) { - includeThemeFile(theme, element, resource); - } else if ("class".equals(elementName)) { - // ignore it - } else { - log.error("Unknown tag: " + elementName); - } - } - } - - private Document readXmlDocument(Resource resource) throws IOException { - Document doc; - InputStream stream = null; - try { - stream = resource.getInputStream(); - try { - SAXReader reader = new SAXReader(); - doc = reader.read(stream); - } catch (DocumentException e) { - throw new RuntimeException(e); - } - } finally { - IOUtils.closeQuietly(stream); - } - return doc; - } - - private void includeThemeFile(DesktopThemeImpl theme, Element element, Resource resource) throws IOException { - String fileName = element.attributeValue("file"); - if (StringUtils.isEmpty(fileName)) { - log.error("Missing 'file' attribute to include"); - return; - } - - Resource relativeResource = resource.createRelative(fileName); - if (relativeResource.exists()) { - log.info("Including theme file " + relativeResource.getURL()); - loadThemeFromXml(theme, relativeResource); - } else { - log.error("Resource " + fileName + " not found, ignore it"); - } - } - - private void loadLayoutSettings(DesktopThemeImpl theme, Element element) { - try { - String margin = element.attributeValue("margin-size"); - if (margin != null) { - theme.setMarginSize(Integer.valueOf(margin)); - } - - String spacing = element.attributeValue("spacing-size"); - if (spacing != null) { - theme.setSpacingSize(Integer.valueOf(spacing)); - } - } catch (NumberFormatException e) { - log.error("Invalid integer value at layout settings: " + e.getMessage()); - } - } - - private DesktopStyle loadStyle(Element element) { - final String componentsSubTag = "components"; - - String styleName = element.attributeValue("name"); - - List components = null; - if (element.attributeValue("component") != null) { - String className = element.attributeValue("component"); - try { - components = Collections.singletonList((Class) Class.forName(className)); - } catch (ClassNotFoundException e) { - log.error("Unknown component class: " + className); - } - } else { - Element componentsElement = element.element(componentsSubTag); - if (componentsElement != null) { - String componentsStr = componentsElement.getTextTrim(); - StrTokenizer tokenizer = new StrTokenizer(componentsStr); - components = new ArrayList<>(); - for (String className : tokenizer.getTokenArray()) { - try { - components.add(Class.forName(className)); - } catch (ClassNotFoundException e) { - log.error("Unknown component class: " + className); - } - } - } - } - - List decorators = new ArrayList<>(); - for (Element childElement : (List) element.elements()) { - if (!componentsSubTag.equals(childElement.getName())) { - ComponentDecorator decorator = loadDecorator(childElement); - if (decorator != null) { - decorators.add(decorator); - } - } - } - - return new DesktopStyle(styleName, decorators, components); - } - - private ComponentDecorator loadDecorator(Element element) { - String elementName = element.getName(); - String property = element.attributeValue("property"); - if (property == null) { - property = elementName; - } - - String state = element.attributeValue("state"); - - if ("custom".equals(elementName)) { - String className = element.attributeValue("class"); - return new CustomDecorator(className); - } else if ("background".equals(elementName)) { - Color value = loadColorValue(element.attributeValue("color")); - return new PropertyPathDecorator(property, value, state); - } else if ("foreground".equals(elementName)) { - Color value = loadColorValue(element.attributeValue("color")); - return new PropertyPathDecorator(property, value, state); - } else if ("font".equals(elementName)) { - return loadFontDecorator(element, property, state); - } else if (BORDER_TAG.equals(elementName)) { - Border border = loadBorder(element); - return new PropertyPathDecorator(property, border, state); - } else if ("icon".equals(elementName)) { - return loadIconDecorator(element); - } - - log.error("Unknown style tag: " + elementName); - return null; - } - - private ComponentDecorator loadIconDecorator(Element element) { - String iconName = element.attributeValue("name"); - if (StringUtils.isEmpty(iconName)) { - log.error("icon requires 'name' attribute"); - return null; - } - return new IconDecorator(iconName); - } - - private ComponentDecorator loadFontDecorator(Element element, String property, String state) { - try { - String family = element.attributeValue("family"); - Integer style = element.attributeValue("style") != null - ? convertFontStyle(element.attributeValue("style")) : null; - Integer size = element.attributeValue("size") != null - ? Integer.parseInt(element.attributeValue("size")) : null; - FontDecorator decorator = new FontDecorator(property, family, style, size); - decorator.setState(state); - return decorator; - } catch (NumberFormatException e) { - log.error("Error loading font for style", e); - return null; - } - } - - private Border loadBorder(Element element) { - String type = element.attributeValue("type"); - if ("empty".equals(type)) { - String value = element.attributeValue("margins"); - String[] values = value.split(" "); - if (values.length != 4) { - log.error("Border margins value should be like '0 0 0 0': " + value); - return null; - } - try { - int top = Integer.parseInt(values[0]); - int right = Integer.parseInt(values[1]); - int bottom = Integer.parseInt(values[2]); - int left = Integer.parseInt(values[3]); - return BorderFactory.createEmptyBorder(top, left, bottom, right); - } catch (NumberFormatException e) { - log.error("Border margins value should be like '0 0 0 0': " + value); - } - } else if ("line".equals(type)) { - String color = element.attributeValue("color"); - String width = element.attributeValue("width"); - Color borderColor = loadColorValue(color); - if (borderColor == null) { - log.error("Invalid line border color"); - return null; - } - if (width != null) { - return BorderFactory.createLineBorder(borderColor, Integer.parseInt(width)); - } else { - return BorderFactory.createLineBorder(borderColor); - } - } else if ("compound".equals(type)) { - if (element.elements().size() < 2) { - log.error("Compound border should have two child borders"); - return null; - } - final Element child1 = (Element) element.elements().get(0); - final Element child2 = (Element) element.elements().get(1); - if (!BORDER_TAG.equals(child1.getName()) || !BORDER_TAG.equals(child2.getName())) { - log.error("Compound border should have two child borders"); - return null; - } - Border outsideBorder = loadBorder(child1); - Border insideBorder = loadBorder(child2); - if (outsideBorder == null || insideBorder == null) { - return null; - } - return BorderFactory.createCompoundBorder(outsideBorder, insideBorder); - } else { - log.error("Unknown border type: " + type); - } - return null; - } - - private void loadUIDefaults(Map uiDefaults, Element rootElement) { - for (Element element : (List) rootElement.elements()) { - String propertyName = element.attributeValue("property"); - - Object value = loadUIValue(element); - if (value != null) { - uiDefaults.put(propertyName, value); - } - } - } - - private Object loadUIValue(Element element) { - String elementName = element.getName(); - if ("color".equals(elementName)) { - String value = element.attributeValue("value"); - if (value == null) { - log.error("Color requires value attribute specified"); - return null; - } - return loadColorValue(value); - } else if ("font".equals(elementName)) { - return loadFontForUIDefault(element); - } else if ("insets".equals(elementName)) { - return loadInsets(element); - } else if ("dimension".equals(elementName)) { - return loadDimension(element); - } else { - log.error("Uknown UI property value: " + elementName); - return null; - } - } - - private Dimension loadDimension(Element element) { - String value = element.attributeValue("value"); - if (value == null) { - log.error("Dimension value should specified"); - return null; - } - String[] values = value.split(" "); - if (values.length != 2) { - log.error("Dimension value should be like '0 0': " + value); - return null; - } - - try { - int width = Integer.parseInt(values[0]); - int height = Integer.parseInt(values[1]); - return new Dimension(width, height); - } catch (NumberFormatException e) { - log.error("Dimension value should be like '0 0': " + value); - return null; - } - - } - - private Insets loadInsets(Element element) { - String value = element.attributeValue("value"); - if (value == null) { - log.error("Insets value should specified"); - return null; - } - String[] values = value.split(" "); - if (values.length != 4) { - log.error("Insets value should be like '0 0 0 0': " + value); - return null; - } - - try { - int top = Integer.parseInt(values[0]); - int right = Integer.parseInt(values[1]); - int bottom = Integer.parseInt(values[2]); - int left = Integer.parseInt(values[3]); - return new Insets(top, left, bottom, right); - } catch (NumberFormatException e) { - log.error("Insets value should be like '0 0 0 0': " + value); - return null; - } - } - - private Font loadFontForUIDefault(Element element) { - String family = element.attributeValue("family"); - if (family == null) { - log.error("Font family required for ui-defaults"); - return null; - } - - String styleStr = element.attributeValue("style"); - Integer styleInt = convertFontStyle(styleStr); - if (styleInt == null) { - log.error("Unknown style: " + styleStr); - return null; - } - - String size = element.attributeValue("size"); - if (size == null) { - log.error("Font size required for ui-defauls"); - return null; - } - - int sizeInt; - try { - sizeInt = Integer.parseInt(size); - } catch (NumberFormatException e) { - log.error("Unparseable size: " + size); - return null; - } - - return new Font(family, styleInt, sizeInt); - } - - private Integer convertFontStyle(String styleStr) { - if ("bold".equals(styleStr)) { - return Font.BOLD; - } else if ("italic".equals(styleStr)) { - return Font.ITALIC; - } else if ("bold-italic".equals(styleStr)) { - return Font.BOLD | Font.ITALIC; - } else if (styleStr == null || "plain".equals(styleStr)) { - return Font.PLAIN; - } else { - log.error("Unknown font style: " + styleStr); - return null; - } - } - - private Color loadColorValue(String value) { - if (value == null) { - return null; - } - - if ("transparent".equalsIgnoreCase(value)) { - return new Color(255, 255, 255, 0); // completely transparent color - } - - if (value.length() == 7 && value.charAt(0) == '#') { // html - final int radix = 16; - int r = Integer.parseInt(value.substring(1, 3), radix); - int g = Integer.parseInt(value.substring(3, 5), radix); - int b = Integer.parseInt(value.substring(5, 7), radix); - return new Color(r, g, b); - } - final Matcher matcher = DECIMAL_COLOR_PATTERN.matcher(value); - if (matcher.matches()) { - int r = Integer.parseInt(matcher.group(1)); - int g = Integer.parseInt(matcher.group(2)); - int b = Integer.parseInt(matcher.group(3)); - return new Color(r, g, b); - } - log.error("Unparseable color value: " + value); - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.core.global.Resources; +import com.haulmont.cuba.desktop.DesktopConfig; +import com.haulmont.cuba.desktop.DesktopResources; +import com.haulmont.cuba.desktop.theme.ComponentDecorator; +import com.haulmont.cuba.desktop.theme.DesktopTheme; +import com.haulmont.cuba.desktop.theme.DesktopThemeLoader; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.springframework.core.io.Resource; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Component(DesktopThemeLoader.NAME) +public class DesktopThemeLoaderImpl implements DesktopThemeLoader { + + private static final String BORDER_TAG = "border"; + + @Inject + private DesktopConfig config; + + @Inject + private Resources resources; + + private final Logger log = LoggerFactory.getLogger(DesktopThemeLoaderImpl.class); + + // like '255 128 0' + private static final Pattern DECIMAL_COLOR_PATTERN = Pattern.compile("^(\\d+)\\s+(\\d+)\\s+(\\d+)$"); + + @Override + public DesktopTheme loadTheme(String themeName) { + String themeLocations = config.getResourceLocations(); + StrTokenizer tokenizer = new StrTokenizer(themeLocations); + String[] locationList = tokenizer.getTokenArray(); + + List resourceLocationList = new ArrayList<>(); + DesktopThemeImpl theme = createTheme(themeName, locationList); + theme.setName(themeName); + for (String location : locationList) { + resourceLocationList.add(getResourcesDir(themeName, location)); + + String xmlLocation = getConfigFileName(themeName, location); + Resource resource = resources.getResource(xmlLocation); + if (resource.exists()) { + try { + loadThemeFromXml(theme, resource); + } catch (IOException e) { + log.error("Error", e); + } + } else { + log.warn("Resource " + location + " not found, ignore it"); + } + } + + DesktopResources desktopResources = new DesktopResources(resourceLocationList, resources); + theme.setResources(desktopResources); + + return theme; + } + + // read config files and search for element which should contain custom theme class + private DesktopThemeImpl createTheme(String themeName, String[] locationList) { + String themeClassName = null; + for (String location : locationList) { + String xmlLocation = getConfigFileName(themeName, location); + Resource resource = resources.getResource(xmlLocation); + if (resource.exists()) { + try { + Document doc = readXmlDocument(resource); + final Element rootElement = doc.getRootElement(); + + List classElements = rootElement.elements("class"); + if (!classElements.isEmpty()) { + themeClassName = classElements.get(0).getTextTrim(); + } + } catch (IOException e) { + log.error("Error", e); + } + } else { + log.warn("Resource " + location + " not found, ignore it"); + } + } + if (themeClassName != null) { + try { + Class themeClass = Class.forName(themeClassName); + return (DesktopThemeImpl) themeClass.newInstance(); + } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { + throw new RuntimeException(e); + } + } + return new DesktopThemeImpl(); + } + + private String getResourcesDir(String themeName, String location) { + return location + "/" + themeName; + } + + private String getConfigFileName(String themeName, String location) { + return location + "/" + themeName + "/" + themeName + ".xml"; + } + + private void loadThemeFromXml(DesktopThemeImpl theme, Resource resource) throws IOException { + log.info("Loading theme file " + resource.getURL()); + + Document doc = readXmlDocument(resource); + final Element rootElement = doc.getRootElement(); + + for (Element element : (List) rootElement.elements()) { + String elementName = element.getName(); + if ("lookAndFeel".equals(elementName)) { + String lookAndFeel = element.getTextTrim(); + if (StringUtils.isNotEmpty(lookAndFeel)) { + theme.setLookAndFeel(lookAndFeel); + } + } else if ("ui-defaults".equals(elementName)) { + loadUIDefaults(theme.getUiDefaults(), element); + } else if ("layout".equals(elementName)) { + loadLayoutSettings(theme, element); + } else if ("style".equals(elementName)) { + DesktopStyle style = loadStyle(element); + theme.addStyle(style); + } else if ("include".equals(elementName)) { + includeThemeFile(theme, element, resource); + } else if ("class".equals(elementName)) { + // ignore it + } else { + log.error("Unknown tag: " + elementName); + } + } + } + + private Document readXmlDocument(Resource resource) throws IOException { + Document doc; + InputStream stream = null; + try { + stream = resource.getInputStream(); + try { + SAXReader reader = new SAXReader(); + doc = reader.read(stream); + } catch (DocumentException e) { + throw new RuntimeException(e); + } + } finally { + IOUtils.closeQuietly(stream); + } + return doc; + } + + private void includeThemeFile(DesktopThemeImpl theme, Element element, Resource resource) throws IOException { + String fileName = element.attributeValue("file"); + if (StringUtils.isEmpty(fileName)) { + log.error("Missing 'file' attribute to include"); + return; + } + + Resource relativeResource = resource.createRelative(fileName); + if (relativeResource.exists()) { + log.info("Including theme file " + relativeResource.getURL()); + loadThemeFromXml(theme, relativeResource); + } else { + log.error("Resource " + fileName + " not found, ignore it"); + } + } + + private void loadLayoutSettings(DesktopThemeImpl theme, Element element) { + try { + String margin = element.attributeValue("margin-size"); + if (margin != null) { + theme.setMarginSize(Integer.valueOf(margin)); + } + + String spacing = element.attributeValue("spacing-size"); + if (spacing != null) { + theme.setSpacingSize(Integer.valueOf(spacing)); + } + } catch (NumberFormatException e) { + log.error("Invalid integer value at layout settings: " + e.getMessage()); + } + } + + private DesktopStyle loadStyle(Element element) { + final String componentsSubTag = "components"; + + String styleName = element.attributeValue("name"); + + List components = null; + if (element.attributeValue("component") != null) { + String className = element.attributeValue("component"); + try { + components = Collections.singletonList((Class) Class.forName(className)); + } catch (ClassNotFoundException e) { + log.error("Unknown component class: " + className); + } + } else { + Element componentsElement = element.element(componentsSubTag); + if (componentsElement != null) { + String componentsStr = componentsElement.getTextTrim(); + StrTokenizer tokenizer = new StrTokenizer(componentsStr); + components = new ArrayList<>(); + for (String className : tokenizer.getTokenArray()) { + try { + components.add(Class.forName(className)); + } catch (ClassNotFoundException e) { + log.error("Unknown component class: " + className); + } + } + } + } + + List decorators = new ArrayList<>(); + for (Element childElement : (List) element.elements()) { + if (!componentsSubTag.equals(childElement.getName())) { + ComponentDecorator decorator = loadDecorator(childElement); + if (decorator != null) { + decorators.add(decorator); + } + } + } + + return new DesktopStyle(styleName, decorators, components); + } + + private ComponentDecorator loadDecorator(Element element) { + String elementName = element.getName(); + String property = element.attributeValue("property"); + if (property == null) { + property = elementName; + } + + String state = element.attributeValue("state"); + + if ("custom".equals(elementName)) { + String className = element.attributeValue("class"); + return new CustomDecorator(className); + } else if ("background".equals(elementName)) { + Color value = loadColorValue(element.attributeValue("color")); + return new PropertyPathDecorator(property, value, state); + } else if ("foreground".equals(elementName)) { + Color value = loadColorValue(element.attributeValue("color")); + return new PropertyPathDecorator(property, value, state); + } else if ("font".equals(elementName)) { + return loadFontDecorator(element, property, state); + } else if (BORDER_TAG.equals(elementName)) { + Border border = loadBorder(element); + return new PropertyPathDecorator(property, border, state); + } else if ("icon".equals(elementName)) { + return loadIconDecorator(element); + } + + log.error("Unknown style tag: " + elementName); + return null; + } + + private ComponentDecorator loadIconDecorator(Element element) { + String iconName = element.attributeValue("name"); + if (StringUtils.isEmpty(iconName)) { + log.error("icon requires 'name' attribute"); + return null; + } + return new IconDecorator(iconName); + } + + private ComponentDecorator loadFontDecorator(Element element, String property, String state) { + try { + String family = element.attributeValue("family"); + Integer style = element.attributeValue("style") != null + ? convertFontStyle(element.attributeValue("style")) : null; + Integer size = element.attributeValue("size") != null + ? Integer.parseInt(element.attributeValue("size")) : null; + FontDecorator decorator = new FontDecorator(property, family, style, size); + decorator.setState(state); + return decorator; + } catch (NumberFormatException e) { + log.error("Error loading font for style", e); + return null; + } + } + + private Border loadBorder(Element element) { + String type = element.attributeValue("type"); + if ("empty".equals(type)) { + String value = element.attributeValue("margins"); + String[] values = value.split(" "); + if (values.length != 4) { + log.error("Border margins value should be like '0 0 0 0': " + value); + return null; + } + try { + int top = Integer.parseInt(values[0]); + int right = Integer.parseInt(values[1]); + int bottom = Integer.parseInt(values[2]); + int left = Integer.parseInt(values[3]); + return BorderFactory.createEmptyBorder(top, left, bottom, right); + } catch (NumberFormatException e) { + log.error("Border margins value should be like '0 0 0 0': " + value); + } + } else if ("line".equals(type)) { + String color = element.attributeValue("color"); + String width = element.attributeValue("width"); + Color borderColor = loadColorValue(color); + if (borderColor == null) { + log.error("Invalid line border color"); + return null; + } + if (width != null) { + return BorderFactory.createLineBorder(borderColor, Integer.parseInt(width)); + } else { + return BorderFactory.createLineBorder(borderColor); + } + } else if ("compound".equals(type)) { + if (element.elements().size() < 2) { + log.error("Compound border should have two child borders"); + return null; + } + final Element child1 = (Element) element.elements().get(0); + final Element child2 = (Element) element.elements().get(1); + if (!BORDER_TAG.equals(child1.getName()) || !BORDER_TAG.equals(child2.getName())) { + log.error("Compound border should have two child borders"); + return null; + } + Border outsideBorder = loadBorder(child1); + Border insideBorder = loadBorder(child2); + if (outsideBorder == null || insideBorder == null) { + return null; + } + return BorderFactory.createCompoundBorder(outsideBorder, insideBorder); + } else { + log.error("Unknown border type: " + type); + } + return null; + } + + private void loadUIDefaults(Map uiDefaults, Element rootElement) { + for (Element element : (List) rootElement.elements()) { + String propertyName = element.attributeValue("property"); + + Object value = loadUIValue(element); + if (value != null) { + uiDefaults.put(propertyName, value); + } + } + } + + private Object loadUIValue(Element element) { + String elementName = element.getName(); + if ("color".equals(elementName)) { + String value = element.attributeValue("value"); + if (value == null) { + log.error("Color requires value attribute specified"); + return null; + } + return loadColorValue(value); + } else if ("font".equals(elementName)) { + return loadFontForUIDefault(element); + } else if ("insets".equals(elementName)) { + return loadInsets(element); + } else if ("dimension".equals(elementName)) { + return loadDimension(element); + } else { + log.error("Uknown UI property value: " + elementName); + return null; + } + } + + private Dimension loadDimension(Element element) { + String value = element.attributeValue("value"); + if (value == null) { + log.error("Dimension value should specified"); + return null; + } + String[] values = value.split(" "); + if (values.length != 2) { + log.error("Dimension value should be like '0 0': " + value); + return null; + } + + try { + int width = Integer.parseInt(values[0]); + int height = Integer.parseInt(values[1]); + return new Dimension(width, height); + } catch (NumberFormatException e) { + log.error("Dimension value should be like '0 0': " + value); + return null; + } + + } + + private Insets loadInsets(Element element) { + String value = element.attributeValue("value"); + if (value == null) { + log.error("Insets value should specified"); + return null; + } + String[] values = value.split(" "); + if (values.length != 4) { + log.error("Insets value should be like '0 0 0 0': " + value); + return null; + } + + try { + int top = Integer.parseInt(values[0]); + int right = Integer.parseInt(values[1]); + int bottom = Integer.parseInt(values[2]); + int left = Integer.parseInt(values[3]); + return new Insets(top, left, bottom, right); + } catch (NumberFormatException e) { + log.error("Insets value should be like '0 0 0 0': " + value); + return null; + } + } + + private Font loadFontForUIDefault(Element element) { + String family = element.attributeValue("family"); + if (family == null) { + log.error("Font family required for ui-defaults"); + return null; + } + + String styleStr = element.attributeValue("style"); + Integer styleInt = convertFontStyle(styleStr); + if (styleInt == null) { + log.error("Unknown style: " + styleStr); + return null; + } + + String size = element.attributeValue("size"); + if (size == null) { + log.error("Font size required for ui-defauls"); + return null; + } + + int sizeInt; + try { + sizeInt = Integer.parseInt(size); + } catch (NumberFormatException e) { + log.error("Unparseable size: " + size); + return null; + } + + return new Font(family, styleInt, sizeInt); + } + + private Integer convertFontStyle(String styleStr) { + if ("bold".equals(styleStr)) { + return Font.BOLD; + } else if ("italic".equals(styleStr)) { + return Font.ITALIC; + } else if ("bold-italic".equals(styleStr)) { + return Font.BOLD | Font.ITALIC; + } else if (styleStr == null || "plain".equals(styleStr)) { + return Font.PLAIN; + } else { + log.error("Unknown font style: " + styleStr); + return null; + } + } + + private Color loadColorValue(String value) { + if (value == null) { + return null; + } + + if ("transparent".equalsIgnoreCase(value)) { + return new Color(255, 255, 255, 0); // completely transparent color + } + + if (value.length() == 7 && value.charAt(0) == '#') { // html + final int radix = 16; + int r = Integer.parseInt(value.substring(1, 3), radix); + int g = Integer.parseInt(value.substring(3, 5), radix); + int b = Integer.parseInt(value.substring(5, 7), radix); + return new Color(r, g, b); + } + final Matcher matcher = DECIMAL_COLOR_PATTERN.matcher(value); + if (matcher.matches()) { + int r = Integer.parseInt(matcher.group(1)); + int g = Integer.parseInt(matcher.group(2)); + int b = Integer.parseInt(matcher.group(3)); + return new Color(r, g, b); + } + log.error("Unparseable color value: " + value); + return null; + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/FontDecorator.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/FontDecorator.java index 30e6d7a7b8..a14061e671 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/FontDecorator.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/FontDecorator.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import java.awt.*; - -public class FontDecorator extends PropertyPathDecorator { - - private String family; - private Integer style; - private Integer size; - - public FontDecorator(String propertyPath, String family, Integer style, Integer size) { - super(propertyPath); - this.family = family; - this.style = style; - this.size = size; - } - - @Override - protected void apply(Object object, String property) { - java.awt.Component component = (java.awt.Component) object; - Font oldFont = component.getFont(); - - String newFamily = oldFont.getFamily(); - int newStyle = oldFont.getStyle(); - int newSize = oldFont.getSize(); - if (family != null) { - newFamily = family; - } - - if (style != null) { - newStyle = style; - } - - if (size != null) { - newSize = size; - } - - Font newFont = new Font(newFamily, newStyle, newSize); - setProperty(object, property, newFont); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import java.awt.*; + +public class FontDecorator extends PropertyPathDecorator { + + private String family; + private Integer style; + private Integer size; + + public FontDecorator(String propertyPath, String family, Integer style, Integer size) { + super(propertyPath); + this.family = family; + this.style = style; + this.size = size; + } + + @Override + protected void apply(Object object, String property) { + java.awt.Component component = (java.awt.Component) object; + Font oldFont = component.getFont(); + + String newFamily = oldFont.getFamily(); + int newStyle = oldFont.getStyle(); + int newSize = oldFont.getSize(); + if (family != null) { + newFamily = family; + } + + if (style != null) { + newStyle = style; + } + + if (size != null) { + newSize = size; + } + + Font newFont = new Font(newFamily, newStyle, newSize); + setProperty(object, property, newFont); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/IconDecorator.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/IconDecorator.java index 099b843e1a..4bbf446fa3 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/IconDecorator.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/IconDecorator.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.desktop.App; -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.theme.ComponentDecorator; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Label; - -import javax.swing.*; -import java.util.Set; - -/** - * Assigns icon to swing or cuba label. - * Can be used also for table cells. - * - */ -public class IconDecorator implements ComponentDecorator { - private String iconName; - - public IconDecorator(String iconName) { - this.iconName = iconName; - } - - @Override - public void decorate(Object component, Set state) { - JLabel label; - if (component instanceof JLabel) { - label = (JLabel) component; - } else if (component instanceof Label) { - label = (JLabel) DesktopComponentsHelper.unwrap((Component) component); - } else { - throw new RuntimeException("Component is not suitable: " + component); - } - - Icon icon = App.getInstance().getResources().getIcon(iconName); - label.setIcon(icon); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.desktop.App; +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.theme.ComponentDecorator; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Label; + +import javax.swing.*; +import java.util.Set; + +/** + * Assigns icon to swing or cuba label. + * Can be used also for table cells. + * + */ +public class IconDecorator implements ComponentDecorator { + private String iconName; + + public IconDecorator(String iconName) { + this.iconName = iconName; + } + + @Override + public void decorate(Object component, Set state) { + JLabel label; + if (component instanceof JLabel) { + label = (JLabel) component; + } else if (component instanceof Label) { + label = (JLabel) DesktopComponentsHelper.unwrap((Component) component); + } else { + throw new RuntimeException("Component is not suitable: " + component); + } + + Icon icon = App.getInstance().getResources().getIcon(iconName); + label.setIcon(icon); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/NimbusTheme.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/NimbusTheme.java index 46492640c1..b2d91276e4 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/NimbusTheme.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/NimbusTheme.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.desktop.plaf.nimbus.MandatoryComboBoxTextFieldPainter; - -import javax.swing.*; -import javax.swing.plaf.InsetsUIResource; - -/** - * Performs initialization needed to highlight empty mandatory ("missing value") fields. - * - */ -public class NimbusTheme extends DesktopThemeImpl { - - @Override - public void init() { - super.init(); - - UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); - lafDefaults.put("Nimbus.keepAlternateRowColor", true); // deny SwingX to remove alternate row color - lafDefaults.put("ComboBox:\"ComboBox.textField\".contentMargins", new InsetsUIResource(0, 6, 0, 6)); - lafDefaults.put("ComboBox:\"ComboBox.textField\"[Enabled].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundEnabledPainter()); - lafDefaults.put("ComboBox:\"ComboBox.textField\"[Disabled].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundDisabledPainter()); - lafDefaults.put("ComboBox:\"ComboBox.textField\"[Selected].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundSelectedPainter()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.desktop.plaf.nimbus.MandatoryComboBoxTextFieldPainter; + +import javax.swing.*; +import javax.swing.plaf.InsetsUIResource; + +/** + * Performs initialization needed to highlight empty mandatory ("missing value") fields. + * + */ +public class NimbusTheme extends DesktopThemeImpl { + + @Override + public void init() { + super.init(); + + UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults(); + lafDefaults.put("Nimbus.keepAlternateRowColor", true); // deny SwingX to remove alternate row color + lafDefaults.put("ComboBox:\"ComboBox.textField\".contentMargins", new InsetsUIResource(0, 6, 0, 6)); + lafDefaults.put("ComboBox:\"ComboBox.textField\"[Enabled].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundEnabledPainter()); + lafDefaults.put("ComboBox:\"ComboBox.textField\"[Disabled].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundDisabledPainter()); + lafDefaults.put("ComboBox:\"ComboBox.textField\"[Selected].backgroundPainter", MandatoryComboBoxTextFieldPainter.backgroundSelectedPainter()); + } } \ No newline at end of file diff --git a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/PropertyPathDecorator.java b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/PropertyPathDecorator.java index 63ee000319..310edc08df 100644 --- a/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/PropertyPathDecorator.java +++ b/modules/desktop/src/com/haulmont/cuba/desktop/theme/impl/PropertyPathDecorator.java @@ -1,110 +1,110 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.theme.impl; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import com.haulmont.cuba.desktop.theme.ComponentDecorator; -import com.haulmont.cuba.gui.components.Component; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Set; - -public class PropertyPathDecorator implements ComponentDecorator { - - protected String[] properties; - protected Object value; - protected String state; - - public PropertyPathDecorator(String propertyPath) { - this(propertyPath, null, null); - } - - public PropertyPathDecorator(String propertyPath, Object value) { - this(propertyPath, value, null); - } - - public PropertyPathDecorator(String propertyPath, Object value, String state) { - this.properties = propertyPath.split("\\."); - if (properties.length < 1) { - throw new IllegalArgumentException("Invalid property path: " + propertyPath); - } - this.value = value; - this.state = state; - } - - public void setState(String state) { - this.state = state; - } - - @Override - public void decorate(Object component, Set state) { - if (this.state != null && (state == null || !state.contains(this.state))) { - return; - } - - Object object = component; - - if (component instanceof Component && properties.length == 1) { - object = DesktopComponentsHelper.getComposition((Component) component); - } - - for (int i = 0; i < properties.length - 1; i++) { - object = getProperty(object, properties[i]); - } - apply(object, properties[properties.length - 1]); - } - - public Object getProperty(Object object, String property) { - String methodName = "get" + Character.toUpperCase(property.charAt(0)) + property.substring(1); - Class componentClass = object.getClass(); - try { - Method method = componentClass.getMethod(methodName); - return method.invoke(object); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected void apply(Object object, String property) { - setProperty(object, property, value); - } - - protected void setProperty(Object object, String property, Object value) { - String methodName = "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1); - Class componentClass = object.getClass(); - Method[] methods = componentClass.getMethods(); - Method method = null; - for (Method m: methods) { - if (m.getName().equals(methodName)) { - method = m; - break; - } - } - if (method == null) { - throw new RuntimeException("Can't find matching method for property " + property + " at object " + object); - } - - try { - method.invoke(object, value); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.theme.impl; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import com.haulmont.cuba.desktop.theme.ComponentDecorator; +import com.haulmont.cuba.gui.components.Component; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +public class PropertyPathDecorator implements ComponentDecorator { + + protected String[] properties; + protected Object value; + protected String state; + + public PropertyPathDecorator(String propertyPath) { + this(propertyPath, null, null); + } + + public PropertyPathDecorator(String propertyPath, Object value) { + this(propertyPath, value, null); + } + + public PropertyPathDecorator(String propertyPath, Object value, String state) { + this.properties = propertyPath.split("\\."); + if (properties.length < 1) { + throw new IllegalArgumentException("Invalid property path: " + propertyPath); + } + this.value = value; + this.state = state; + } + + public void setState(String state) { + this.state = state; + } + + @Override + public void decorate(Object component, Set state) { + if (this.state != null && (state == null || !state.contains(this.state))) { + return; + } + + Object object = component; + + if (component instanceof Component && properties.length == 1) { + object = DesktopComponentsHelper.getComposition((Component) component); + } + + for (int i = 0; i < properties.length - 1; i++) { + object = getProperty(object, properties[i]); + } + apply(object, properties[properties.length - 1]); + } + + public Object getProperty(Object object, String property) { + String methodName = "get" + Character.toUpperCase(property.charAt(0)) + property.substring(1); + Class componentClass = object.getClass(); + try { + Method method = componentClass.getMethod(methodName); + return method.invoke(object); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected void apply(Object object, String property) { + setProperty(object, property, value); + } + + protected void setProperty(Object object, String property, Object value) { + String methodName = "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1); + Class componentClass = object.getClass(); + Method[] methods = componentClass.getMethods(); + Method method = null; + for (Method m: methods) { + if (m.getName().equals(methodName)) { + method = m; + break; + } + } + if (method == null) { + throw new RuntimeException("Can't find matching method for property " + property + " at object " + object); + } + + try { + method.invoke(object, value); + } catch (InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/modules/desktop/src/cuba-desktop-app.properties b/modules/desktop/src/cuba-desktop-app.properties index 4acaba6d6f..c5515f0f77 100644 --- a/modules/desktop/src/cuba-desktop-app.properties +++ b/modules/desktop/src/cuba-desktop-app.properties @@ -1,51 +1,51 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -############################################################################### -# Names and Directories # -############################################################################### - -# Middleware connection -cuba.connectionUrlList=http://localhost:8080/cuba-core - -# System directories -cuba.confDir=${cuba.desktop.home}/conf -cuba.logDir=${cuba.desktop.home}/logs -cuba.tempDir=${cuba.desktop.home}/temp -cuba.dataDir=${cuba.desktop.home}/work - -############################################################################### -# Configuration # -############################################################################### - -cuba.springContextConfig=cuba-desktop-spring.xml -cuba.viewsConfig=cuba-views.xml -cuba.themeConfig=nimbus-theme.properties - -cuba.windowConfig=cuba-desktop-screens.xml -cuba.menuConfig=cuba-desktop-menu.xml -cuba.permissionConfig=cuba-desktop-permissions.xml -cuba.persistenceConfig = base-persistence.xml cuba-persistence.xml -cuba.mainMessagePack=com.haulmont.cuba.desktop -cuba.metadataConfig = cuba-metadata.xml cuba-gui-metadata.xml - -cuba.groovyClassPath= -cuba.groovyEvaluatorImport=com.haulmont.cuba.core.global.PersistenceHelper - -cuba.creditsConfig=cuba-credits.xml - -cuba.passwordEncryptionModule=cuba_Sha1EncryptionModule +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +############################################################################### +# Names and Directories # +############################################################################### + +# Middleware connection +cuba.connectionUrlList=http://localhost:8080/cuba-core + +# System directories +cuba.confDir=${cuba.desktop.home}/conf +cuba.logDir=${cuba.desktop.home}/logs +cuba.tempDir=${cuba.desktop.home}/temp +cuba.dataDir=${cuba.desktop.home}/work + +############################################################################### +# Configuration # +############################################################################### + +cuba.springContextConfig=cuba-desktop-spring.xml +cuba.viewsConfig=cuba-views.xml +cuba.themeConfig=nimbus-theme.properties + +cuba.windowConfig=cuba-desktop-screens.xml +cuba.menuConfig=cuba-desktop-menu.xml +cuba.permissionConfig=cuba-desktop-permissions.xml +cuba.persistenceConfig = base-persistence.xml cuba-persistence.xml +cuba.mainMessagePack=com.haulmont.cuba.desktop +cuba.metadataConfig = cuba-metadata.xml cuba-gui-metadata.xml + +cuba.groovyClassPath= +cuba.groovyEvaluatorImport=com.haulmont.cuba.core.global.PersistenceHelper + +cuba.creditsConfig=cuba-credits.xml + +cuba.passwordEncryptionModule=cuba_Sha1EncryptionModule diff --git a/modules/desktop/src/cuba-desktop-menu.xml b/modules/desktop/src/cuba-desktop-menu.xml index e8818ced40..828407d54c 100644 --- a/modules/desktop/src/cuba-desktop-menu.xml +++ b/modules/desktop/src/cuba-desktop-menu.xml @@ -1,43 +1,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/desktop/src/cuba-desktop-permissions.xml b/modules/desktop/src/cuba-desktop-permissions.xml index e2c7cf6575..a66f889abc 100644 --- a/modules/desktop/src/cuba-desktop-permissions.xml +++ b/modules/desktop/src/cuba-desktop-permissions.xml @@ -1,22 +1,22 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/modules/desktop/src/cuba-desktop-screens.xml b/modules/desktop/src/cuba-desktop-screens.xml index 7cb93d919a..8300bfe6b8 100644 --- a/modules/desktop/src/cuba-desktop-screens.xml +++ b/modules/desktop/src/cuba-desktop-screens.xml @@ -1,26 +1,26 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/modules/desktop/src/cuba-desktop-spring.xml b/modules/desktop/src/cuba-desktop-spring.xml index 1590483b70..37c4845145 100644 --- a/modules/desktop/src/cuba-desktop-spring.xml +++ b/modules/desktop/src/cuba-desktop-spring.xml @@ -1,122 +1,122 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.haulmont.cuba.desktop.exception.NoUserSessionHandler - com.haulmont.cuba.desktop.exception.EntitySerializationExceptionHandler - com.haulmont.cuba.desktop.exception.ConnectExceptionHandler - com.haulmont.cuba.desktop.exception.IllegalComponentStateExceptionHandler - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.haulmont.cuba.desktop.exception.NoUserSessionHandler + com.haulmont.cuba.desktop.exception.EntitySerializationExceptionHandler + com.haulmont.cuba.desktop.exception.ConnectExceptionHandler + com.haulmont.cuba.desktop.exception.IllegalComponentStateExceptionHandler + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/desktop/src/cuba-logback.xml b/modules/desktop/src/cuba-logback.xml index ed83cc452b..d189ab0680 100644 --- a/modules/desktop/src/cuba-logback.xml +++ b/modules/desktop/src/cuba-logback.xml @@ -1,154 +1,154 @@ - - - - - - - - - ${logDir}/app.log - false - - - DEBUG - - - - - app.%d{yyyy-MM-dd}.log - - 30 - true - - - - %d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n - - - - - - INFO - - - - %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n - - - - - ${logDir}/user-actions.log - false - - - ${logDir}/user-actions.%d{yyyy-MM-dd}.log - 30 - true - - - - %d{HH:mm:ss.SSS} %-5level [%thread] - %msg%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + ${logDir}/app.log + false + + + DEBUG + + + + + app.%d{yyyy-MM-dd}.log + + 30 + true + + + + %d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n + + + + + + INFO + + + + %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n + + + + + ${logDir}/user-actions.log + false + + + ${logDir}/user-actions.%d{yyyy-MM-dd}.log + 30 + true + + + + %d{HH:mm:ss.SSS} %-5level [%thread] - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/desktop/test/com/haulmont/cuba/desktop/LayoutTest.java b/modules/desktop/test/com/haulmont/cuba/desktop/LayoutTest.java index e05a325860..8b49516add 100644 --- a/modules/desktop/test/com/haulmont/cuba/desktop/LayoutTest.java +++ b/modules/desktop/test/com/haulmont/cuba/desktop/LayoutTest.java @@ -1,95 +1,95 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop; - -import net.miginfocom.layout.AC; -import net.miginfocom.swing.MigLayout; - -import java.awt.BorderLayout; -import javax.swing.*; -import javax.swing.table.DefaultTableModel; - -public class LayoutTest { - - private JFrame frame; - private JPanel contentPane; - - public static void main(String[] args) { - LayoutTest layoutTest = new LayoutTest(); - - layoutTest.testTableAndButtons(); - - layoutTest.start(); - } - - public LayoutTest() { - frame = new JFrame("Layout Test"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setBounds(300, 300, 800, 600); - - contentPane = new JPanel(new BorderLayout()); - frame.setContentPane(contentPane); - - } - - private void start() { - frame.setVisible(true); - } - - private void testTable() { - MigLayout layout = new MigLayout("debug"); - JPanel panel = new JPanel(layout); - contentPane.add(panel, BorderLayout.CENTER); - - layout.setLayoutConstraints("fill, flowy, insets 10 0 0 0, debug"); - - JTable table = new JTable(); - table.setModel(new DefaultTableModel(new String[] {"col1", "col2"}, 3)); - panel.add(table); - - layout.setComponentConstraints(table, "grow"); - } - - private void testTableAndButtons() { - MigLayout mainLayout = new MigLayout(); - JPanel mainPanel = new JPanel(mainLayout); - contentPane.add(mainPanel, BorderLayout.CENTER); - - mainLayout.setLayoutConstraints("flowy, fillx, insets panel, debug"); - - MigLayout buttonsLayout = new MigLayout("flowx, filly, insets panel, debug"); - JPanel buttonsPanel = new JPanel(buttonsLayout); - buttonsPanel.add(new JButton("button1")); - buttonsPanel.add(new JButton("button2")); - - mainPanel.add(buttonsPanel); - - MigLayout tableLayout = new MigLayout("flowy, fill, debug"); - JPanel tablePanel = new JPanel(tableLayout); - JTable table = new JTable(); - table.setModel(new DefaultTableModel(new String[] {"col1", "col2"}, 3)); - tablePanel.add(table, "grow"); - - mainPanel.add(tablePanel); - mainLayout.setComponentConstraints(tablePanel, "grow"); - mainLayout.setLayoutConstraints("flowy, fill, insets panel, debug"); // change fillx to fill -// mainLayout.setRowConstraints("[min!][fill]"); - AC ac = new AC().size("min!", 0).fill(1); - mainLayout.setRowConstraints(ac); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop; + +import net.miginfocom.layout.AC; +import net.miginfocom.swing.MigLayout; + +import java.awt.BorderLayout; +import javax.swing.*; +import javax.swing.table.DefaultTableModel; + +public class LayoutTest { + + private JFrame frame; + private JPanel contentPane; + + public static void main(String[] args) { + LayoutTest layoutTest = new LayoutTest(); + + layoutTest.testTableAndButtons(); + + layoutTest.start(); + } + + public LayoutTest() { + frame = new JFrame("Layout Test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setBounds(300, 300, 800, 600); + + contentPane = new JPanel(new BorderLayout()); + frame.setContentPane(contentPane); + + } + + private void start() { + frame.setVisible(true); + } + + private void testTable() { + MigLayout layout = new MigLayout("debug"); + JPanel panel = new JPanel(layout); + contentPane.add(panel, BorderLayout.CENTER); + + layout.setLayoutConstraints("fill, flowy, insets 10 0 0 0, debug"); + + JTable table = new JTable(); + table.setModel(new DefaultTableModel(new String[] {"col1", "col2"}, 3)); + panel.add(table); + + layout.setComponentConstraints(table, "grow"); + } + + private void testTableAndButtons() { + MigLayout mainLayout = new MigLayout(); + JPanel mainPanel = new JPanel(mainLayout); + contentPane.add(mainPanel, BorderLayout.CENTER); + + mainLayout.setLayoutConstraints("flowy, fillx, insets panel, debug"); + + MigLayout buttonsLayout = new MigLayout("flowx, filly, insets panel, debug"); + JPanel buttonsPanel = new JPanel(buttonsLayout); + buttonsPanel.add(new JButton("button1")); + buttonsPanel.add(new JButton("button2")); + + mainPanel.add(buttonsPanel); + + MigLayout tableLayout = new MigLayout("flowy, fill, debug"); + JPanel tablePanel = new JPanel(tableLayout); + JTable table = new JTable(); + table.setModel(new DefaultTableModel(new String[] {"col1", "col2"}, 3)); + tablePanel.add(table, "grow"); + + mainPanel.add(tablePanel); + mainLayout.setComponentConstraints(tablePanel, "grow"); + mainLayout.setLayoutConstraints("flowy, fill, insets panel, debug"); // change fillx to fill +// mainLayout.setRowConstraints("[min!][fill]"); + AC ac = new AC().size("min!", 0).fill(1); + mainLayout.setRowConstraints(ac); + } } \ No newline at end of file diff --git a/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/LookupPicker.java b/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/LookupPicker.java index e53dde4926..63241f54e2 100644 --- a/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/LookupPicker.java +++ b/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/LookupPicker.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import javax.swing.*; - -public class LookupPicker extends Picker { - - @Override - protected void initEditor() { - JComboBox comboBox = new JComboBox(); - comboBox.setPrototypeDisplayValue("AAAAAAAAAAAA"); - - editor = comboBox; - } - - public JComboBox getComboBox() { - return (JComboBox) editor; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import javax.swing.*; + +public class LookupPicker extends Picker { + + @Override + protected void initEditor() { + JComboBox comboBox = new JComboBox(); + comboBox.setPrototypeDisplayValue("AAAAAAAAAAAA"); + + editor = comboBox; + } + + public JComboBox getComboBox() { + return (JComboBox) editor; + } } \ No newline at end of file diff --git a/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/VclTestApp.java b/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/VclTestApp.java index 789c010b00..8d8bc507a6 100644 --- a/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/VclTestApp.java +++ b/modules/desktop/test/com/haulmont/cuba/desktop/sys/vcl/VclTestApp.java @@ -1,359 +1,359 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.sys.vcl; - -import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; -import net.miginfocom.layout.AC; -import net.miginfocom.layout.CC; -import net.miginfocom.layout.LC; -import net.miginfocom.swing.MigLayout; - -import javax.swing.*; -import javax.swing.table.AbstractTableModel; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.util.Date; -import java.util.Map; -import java.util.Set; - -public class VclTestApp extends JFrame { - - public static void main(String[] args) { - //printUIDefaults(); - - SwingUtilities.invokeLater( - new Runnable() { - @Override - public void run() { - VclTestApp app = new VclTestApp(); - app.initLookAndFeel(); - app.showUI(); - app.setVisible(true); - } - } - ); - } - - private static void printUIDefaults() { - Set defaults = UIManager.getLookAndFeelDefaults().entrySet(); - for (Object aDefault : defaults) { - Map.Entry entry = (Map.Entry) aDefault; - System.out.print(entry.getKey() + " = "); - System.out.println(entry.getValue()); - } - - Font font = UIManager.getLookAndFeelDefaults().getFont("Panel.font"); - System.out.println(font); - } - - public VclTestApp() throws HeadlessException { - setLayout(new BorderLayout()); - setTitle("VCL Test"); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - setBounds(500, 300, 600, 300); - } - - private void initLookAndFeel() { - try { - JDialog.setDefaultLookAndFeelDecorated(true); - JFrame.setDefaultLookAndFeelDecorated(true); - - boolean found = false; - for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - if ("Nimbus".equals(info.getName())) { - UIManager.setLookAndFeel(info.getClassName()); - found = true; - break; - } - } - if (!found) - UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } catch (Exception e) { - e.printStackTrace(System.out); - System.exit(-1); - } - } - - private void showUI() { - JTabbedPane tabbedPane = new JTabbedPane(); - add(tabbedPane, BorderLayout.CENTER); - - tabbedPane.add("Table", createTableTab()); - tabbedPane.add("Align", createAlignTab()); - tabbedPane.add("TextArea", createTextAreaTab()); - tabbedPane.add("Popup", createPopupTab()); - tabbedPane.add("Picker", createPickersTab()); -// tabbedPane.add("Autocomplete", createAutocompleteTab()); - } - - public static class MyPanel extends JPanel implements Scrollable { - - @Override - public Dimension getPreferredScrollableViewportSize() { - return getPreferredSize(); - } - - @Override - public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { - return 10; - } - - @Override - public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { - return visibleRect.width; - } - - @Override - public boolean getScrollableTracksViewportWidth() { -// final Container viewport = getParent(); -// System.out.println("viewport.width=" + viewport.getWidth() + ", minimumSize.width=" + getMinimumSize().width); -// return viewport.getWidth() > getMinimumSize().width; - return false; - } - - @Override - public boolean getScrollableTracksViewportHeight() { - return false; - } - } - - private Component createTableTab() { - final JPanel box = new JPanel(); - box.setFocusable(false); - MigLayout boxLayout = new MigLayout("fill"); - box.setLayout(boxLayout); - - final JScrollPane outerScrollPane = new JScrollPane(); - outerScrollPane.setViewportView(box); - - outerScrollPane.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - final Dimension minimumSize = box.getMinimumSize(); - final int width = Math.max(minimumSize.width, outerScrollPane.getViewport().getWidth()); - box.setPreferredSize(new Dimension(width, minimumSize.height)); - } - }); - - JPanel tablePanel = new JPanel(); - MigLayout tablePanellayout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); - tablePanel.setLayout(tablePanellayout); - - JPanel topPanel = new JPanel(new FlowLayout()); - topPanel.setVisible(true); - tablePanel.add(topPanel/*, "growx"*/); - - topPanel.add(new JButton("Button1")); - topPanel.add(new JButton("Button2")); - topPanel.add(new JButton("Button3")); - topPanel.add(new JButton("Button4")); - topPanel.add(new JButton("Button5")); - - JXTableExt table = new JXTableExt(); - - JScrollPane tableScrollPane = new JScrollPane(table); -// table.setFillsViewportHeight(true); - - tablePanel.add(tableScrollPane, "grow"); - - table.setShowGrid(true); - table.setGridColor(Color.lightGray); - - table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - table.setColumnControlVisible(true); - - table.setModel(new AbstractTableModel() { - @Override - public int getRowCount() { - return 20; - } - - @Override - public int getColumnCount() { - return 20; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - return rowIndex + "-" + columnIndex; - } - }); - - CC cc = new CC(); -// cc.growX(0); -// cc.width("300!"); - cc.width("100%"); -// cc.growY(0.0f); - cc.height("200!"); -// cc.height("100%"); - - box.add(tablePanel); - - boxLayout.setComponentConstraints(tablePanel, cc); - -// cc = new CC(); -// cc.growX(0); -// cc.width("300!"); -// cc.width("100%"); -// cc.height("200!"); -// tablePanellayout.setComponentConstraints(tableScrollPane, cc); - - return outerScrollPane; - } - - private Component createAlignTab() { - JPanel box = new JPanel(); - box.setFocusable(false); - MigLayout boxLayout = new MigLayout("debug 1000, fill"); - box.setLayout(boxLayout); - - JPanel panel = new JPanel(); - MigLayout layout = new MigLayout("debug 1000, fill"); - panel.setLayout(layout); - - JLabel label = new JLabel("Label"); - CC cc = new CC(); - cc.alignX("right").alignY("50%"); - - panel.add(label); - - layout.setComponentConstraints(label, cc); - - LC lc = new LC(); - lc.hideMode(2); // The size of an invisible component will be set to 0, 0 and the gaps will also be set to 0 around it. - lc.debug(1000); - - AC rowConstr = new AC(); - AC colConstr = new AC(); - - lc.fillX(); - lc.flowY(); - lc.gridGapY("0"); - - layout.setLayoutConstraints(lc); - layout.setRowConstraints(rowConstr); - layout.setColumnConstraints(colConstr); - - box.add(panel, "height 100px, width 100px"); - layout.setComponentConstraints(label, cc); - return box; - } - - private Component createTextAreaTab() { - JPanel panel = new JPanel(); - panel.setLayout(new MigLayout("flowy, fill", "[]", "[min!][fill]")); -// panel.setLayout(new BorderLayout()); - - JTextArea textArea = new JTextArea(); - textArea.setRows(3); - textArea.setLineWrap(true); - textArea.setWrapStyleWord(true); - - int height = (int) textArea.getPreferredSize().getHeight(); - textArea.setMinimumSize(new Dimension(150, height)); - - JScrollPane scrollPane = new JScrollPane(textArea); - scrollPane.setMinimumSize(new Dimension(0, height)); - scrollPane.setPreferredSize(new Dimension(150, height)); - - panel.add(scrollPane); - panel.add(new JButton("button"), "grow"); - - return panel; - } - - private JPanel createPickersTab() { - JPanel panel = new JPanel(); - panel.setLayout(new MigLayout()); - - panel.add(new JLabel("Picker")); - - Picker picker = new Picker(); - panel.add(picker, "wrap"); - - panel.add(new JLabel("Picker")); - - Picker picker1 = new Picker(); - picker1.addButton(new JButton("..."), 0); - panel.add(picker1, "wrap"); - - panel.add(new JLabel("LookupPicker")); - - Picker picker2 = new LookupPicker(); - picker2.addButton(new JButton("..."), 0); - panel.add(picker2, "wrap"); - - return panel; - } - - private JPanel createPopupTab() { - JPanel panel = new JPanel(); - panel.setLayout(new MigLayout()); - - JButton start = new JButton("Pick Me for Popup"); - start.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - showPopup(); - } - } - ); - panel.add(start); - - return panel; - } - - private void showPopup() { - JPanel panel = new JPanel(new MigLayout("flowy")); - panel.setBorder(BorderFactory.createLineBorder(Color.yellow)); - panel.setBackground(Color.yellow); - String text = "A Message " + new Date(); - - JLabel label = new JLabel("" + text + "
" + text + ""); - panel.add(label); - - Dimension labelSize = DesktopComponentsHelper.measureHtmlText(text); - - int x = getX() + getWidth() - (50 + labelSize.width); - int y = getY() + getHeight() - (50 + labelSize.height); - - PopupFactory factory = PopupFactory.getSharedInstance(); - final Popup popup = factory.getPopup(this, panel, x, y); - System.out.println("Show popup " + popup); - popup.show(); - final Point location = MouseInfo.getPointerInfo().getLocation(); - final Timer timer = new Timer(3000, null); - timer.addActionListener( - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (!MouseInfo.getPointerInfo().getLocation().equals(location)) { - System.out.println("Hide popup " + popup); - popup.hide(); - timer.stop(); - } - } - } - ); - timer.start(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.sys.vcl; + +import com.haulmont.cuba.desktop.gui.components.DesktopComponentsHelper; +import net.miginfocom.layout.AC; +import net.miginfocom.layout.CC; +import net.miginfocom.layout.LC; +import net.miginfocom.swing.MigLayout; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +public class VclTestApp extends JFrame { + + public static void main(String[] args) { + //printUIDefaults(); + + SwingUtilities.invokeLater( + new Runnable() { + @Override + public void run() { + VclTestApp app = new VclTestApp(); + app.initLookAndFeel(); + app.showUI(); + app.setVisible(true); + } + } + ); + } + + private static void printUIDefaults() { + Set defaults = UIManager.getLookAndFeelDefaults().entrySet(); + for (Object aDefault : defaults) { + Map.Entry entry = (Map.Entry) aDefault; + System.out.print(entry.getKey() + " = "); + System.out.println(entry.getValue()); + } + + Font font = UIManager.getLookAndFeelDefaults().getFont("Panel.font"); + System.out.println(font); + } + + public VclTestApp() throws HeadlessException { + setLayout(new BorderLayout()); + setTitle("VCL Test"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(500, 300, 600, 300); + } + + private void initLookAndFeel() { + try { + JDialog.setDefaultLookAndFeelDecorated(true); + JFrame.setDefaultLookAndFeelDecorated(true); + + boolean found = false; + for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + UIManager.setLookAndFeel(info.getClassName()); + found = true; + break; + } + } + if (!found) + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } catch (Exception e) { + e.printStackTrace(System.out); + System.exit(-1); + } + } + + private void showUI() { + JTabbedPane tabbedPane = new JTabbedPane(); + add(tabbedPane, BorderLayout.CENTER); + + tabbedPane.add("Table", createTableTab()); + tabbedPane.add("Align", createAlignTab()); + tabbedPane.add("TextArea", createTextAreaTab()); + tabbedPane.add("Popup", createPopupTab()); + tabbedPane.add("Picker", createPickersTab()); +// tabbedPane.add("Autocomplete", createAutocompleteTab()); + } + + public static class MyPanel extends JPanel implements Scrollable { + + @Override + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + @Override + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 10; + } + + @Override + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return visibleRect.width; + } + + @Override + public boolean getScrollableTracksViewportWidth() { +// final Container viewport = getParent(); +// System.out.println("viewport.width=" + viewport.getWidth() + ", minimumSize.width=" + getMinimumSize().width); +// return viewport.getWidth() > getMinimumSize().width; + return false; + } + + @Override + public boolean getScrollableTracksViewportHeight() { + return false; + } + } + + private Component createTableTab() { + final JPanel box = new JPanel(); + box.setFocusable(false); + MigLayout boxLayout = new MigLayout("fill"); + box.setLayout(boxLayout); + + final JScrollPane outerScrollPane = new JScrollPane(); + outerScrollPane.setViewportView(box); + + outerScrollPane.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + final Dimension minimumSize = box.getMinimumSize(); + final int width = Math.max(minimumSize.width, outerScrollPane.getViewport().getWidth()); + box.setPreferredSize(new Dimension(width, minimumSize.height)); + } + }); + + JPanel tablePanel = new JPanel(); + MigLayout tablePanellayout = new MigLayout("flowy, fill, insets 0", "", "[min!][fill]"); + tablePanel.setLayout(tablePanellayout); + + JPanel topPanel = new JPanel(new FlowLayout()); + topPanel.setVisible(true); + tablePanel.add(topPanel/*, "growx"*/); + + topPanel.add(new JButton("Button1")); + topPanel.add(new JButton("Button2")); + topPanel.add(new JButton("Button3")); + topPanel.add(new JButton("Button4")); + topPanel.add(new JButton("Button5")); + + JXTableExt table = new JXTableExt(); + + JScrollPane tableScrollPane = new JScrollPane(table); +// table.setFillsViewportHeight(true); + + tablePanel.add(tableScrollPane, "grow"); + + table.setShowGrid(true); + table.setGridColor(Color.lightGray); + + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + table.setColumnControlVisible(true); + + table.setModel(new AbstractTableModel() { + @Override + public int getRowCount() { + return 20; + } + + @Override + public int getColumnCount() { + return 20; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return rowIndex + "-" + columnIndex; + } + }); + + CC cc = new CC(); +// cc.growX(0); +// cc.width("300!"); + cc.width("100%"); +// cc.growY(0.0f); + cc.height("200!"); +// cc.height("100%"); + + box.add(tablePanel); + + boxLayout.setComponentConstraints(tablePanel, cc); + +// cc = new CC(); +// cc.growX(0); +// cc.width("300!"); +// cc.width("100%"); +// cc.height("200!"); +// tablePanellayout.setComponentConstraints(tableScrollPane, cc); + + return outerScrollPane; + } + + private Component createAlignTab() { + JPanel box = new JPanel(); + box.setFocusable(false); + MigLayout boxLayout = new MigLayout("debug 1000, fill"); + box.setLayout(boxLayout); + + JPanel panel = new JPanel(); + MigLayout layout = new MigLayout("debug 1000, fill"); + panel.setLayout(layout); + + JLabel label = new JLabel("Label"); + CC cc = new CC(); + cc.alignX("right").alignY("50%"); + + panel.add(label); + + layout.setComponentConstraints(label, cc); + + LC lc = new LC(); + lc.hideMode(2); // The size of an invisible component will be set to 0, 0 and the gaps will also be set to 0 around it. + lc.debug(1000); + + AC rowConstr = new AC(); + AC colConstr = new AC(); + + lc.fillX(); + lc.flowY(); + lc.gridGapY("0"); + + layout.setLayoutConstraints(lc); + layout.setRowConstraints(rowConstr); + layout.setColumnConstraints(colConstr); + + box.add(panel, "height 100px, width 100px"); + layout.setComponentConstraints(label, cc); + return box; + } + + private Component createTextAreaTab() { + JPanel panel = new JPanel(); + panel.setLayout(new MigLayout("flowy, fill", "[]", "[min!][fill]")); +// panel.setLayout(new BorderLayout()); + + JTextArea textArea = new JTextArea(); + textArea.setRows(3); + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + + int height = (int) textArea.getPreferredSize().getHeight(); + textArea.setMinimumSize(new Dimension(150, height)); + + JScrollPane scrollPane = new JScrollPane(textArea); + scrollPane.setMinimumSize(new Dimension(0, height)); + scrollPane.setPreferredSize(new Dimension(150, height)); + + panel.add(scrollPane); + panel.add(new JButton("button"), "grow"); + + return panel; + } + + private JPanel createPickersTab() { + JPanel panel = new JPanel(); + panel.setLayout(new MigLayout()); + + panel.add(new JLabel("Picker")); + + Picker picker = new Picker(); + panel.add(picker, "wrap"); + + panel.add(new JLabel("Picker")); + + Picker picker1 = new Picker(); + picker1.addButton(new JButton("..."), 0); + panel.add(picker1, "wrap"); + + panel.add(new JLabel("LookupPicker")); + + Picker picker2 = new LookupPicker(); + picker2.addButton(new JButton("..."), 0); + panel.add(picker2, "wrap"); + + return panel; + } + + private JPanel createPopupTab() { + JPanel panel = new JPanel(); + panel.setLayout(new MigLayout()); + + JButton start = new JButton("Pick Me for Popup"); + start.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showPopup(); + } + } + ); + panel.add(start); + + return panel; + } + + private void showPopup() { + JPanel panel = new JPanel(new MigLayout("flowy")); + panel.setBorder(BorderFactory.createLineBorder(Color.yellow)); + panel.setBackground(Color.yellow); + String text = "A Message " + new Date(); + + JLabel label = new JLabel("" + text + "
" + text + ""); + panel.add(label); + + Dimension labelSize = DesktopComponentsHelper.measureHtmlText(text); + + int x = getX() + getWidth() - (50 + labelSize.width); + int y = getY() + getHeight() - (50 + labelSize.height); + + PopupFactory factory = PopupFactory.getSharedInstance(); + final Popup popup = factory.getPopup(this, panel, x, y); + System.out.println("Show popup " + popup); + popup.show(); + final Point location = MouseInfo.getPointerInfo().getLocation(); + final Timer timer = new Timer(3000, null); + timer.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (!MouseInfo.getPointerInfo().getLocation().equals(location)) { + System.out.println("Hide popup " + popup); + popup.hide(); + timer.stop(); + } + } + } + ); + timer.start(); + } } \ No newline at end of file diff --git a/modules/desktop/test/com/haulmont/cuba/desktop/test/ui/DesktopPickerFieldTest.java b/modules/desktop/test/com/haulmont/cuba/desktop/test/ui/DesktopPickerFieldTest.java index 50a57d12b4..85bb694774 100644 --- a/modules/desktop/test/com/haulmont/cuba/desktop/test/ui/DesktopPickerFieldTest.java +++ b/modules/desktop/test/com/haulmont/cuba/desktop/test/ui/DesktopPickerFieldTest.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.desktop.test.ui; - -import com.google.common.collect.ImmutableMap; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.desktop.gui.DesktopComponentsFactory; -import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; -import com.haulmont.cuba.gui.components.PickerFieldTest; -import mockit.Mocked; -import mockit.NonStrictExpectations; - -import java.util.Locale; - -public class DesktopPickerFieldTest extends PickerFieldTest { - @Mocked({"checkSwingUIAccess"}) - protected DesktopBackgroundWorker desktopBackgroundWorker; - - public DesktopPickerFieldTest() { - factory = new DesktopComponentsFactory(); - } - - @Override - protected void initExpectations() { - super.initExpectations(); - - - new NonStrictExpectations() { - { - globalConfig.getAvailableLocales(); result = ImmutableMap.of("en", Locale.ENGLISH); - AppContext.getProperty("cuba.mainMessagePack"); result = "com.haulmont.cuba.desktop"; - } - }; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.desktop.test.ui; + +import com.google.common.collect.ImmutableMap; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.desktop.gui.DesktopComponentsFactory; +import com.haulmont.cuba.desktop.gui.executors.impl.DesktopBackgroundWorker; +import com.haulmont.cuba.gui.components.PickerFieldTest; +import mockit.Mocked; +import mockit.NonStrictExpectations; + +import java.util.Locale; + +public class DesktopPickerFieldTest extends PickerFieldTest { + @Mocked({"checkSwingUIAccess"}) + protected DesktopBackgroundWorker desktopBackgroundWorker; + + public DesktopPickerFieldTest() { + factory = new DesktopComponentsFactory(); + } + + @Override + protected void initExpectations() { + super.initExpectations(); + + + new NonStrictExpectations() { + { + globalConfig.getAvailableLocales(); result = ImmutableMap.of("en", Locale.ENGLISH); + AppContext.getProperty("cuba.mainMessagePack"); result = "com.haulmont.cuba.desktop"; + } + }; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/datastruct/Node.java b/modules/global/src/com/haulmont/bali/datastruct/Node.java index 1eb6649a8e..2564189ec8 100644 --- a/modules/global/src/com/haulmont/bali/datastruct/Node.java +++ b/modules/global/src/com/haulmont/bali/datastruct/Node.java @@ -1,155 +1,155 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.datastruct; - -import java.io.Serializable; -import java.util.List; -import java.util.ArrayList; - -public class Node implements Serializable { - - private static final long serialVersionUID = -7441713052548471005L; - - public T data; - public Node parent; - public List> children; - - public Node() { - super(); - } - - /** - * Convenience constructor to create a {@code Node} with an instance of T. - * - * @param data an instance of T. - */ - public Node(T data) { - this(); - setData(data); - } - - /** - * Return the children of {@code Node}. The {@code Tree} is represented by a single - * root {@code Node} whose children are represented by a {@code List>}. Each of - * these {@code Node} elements in the List can have children. The getChildren() - * method will return the children of a {@code Node}. - * - * @return the children of {@code Node} - */ - public List> getChildren() { - if (this.children == null) { - this.children = new ArrayList<>(); - } - return this.children; - } - - public Node getParent() { - return parent; - } - - /** - * Sets the children of a {@code Node} object. See docs for getChildren() for - * more information. - * - * @param children the {@code List>} to set. - */ - public void setChildren(List> children) { - for (Node child : children) { - child.parent = this; - } - this.children = children; - } - - /** - * Returns the number of immediate children of this {@code Node}. - * - * @return the number of immediate children. - */ - public int getNumberOfChildren() { - if (children == null) { - return 0; - } - return children.size(); - } - - /** - * Adds a child to the list of children for this {@code Node}. The addition of - * the first child will create a new {@code List>}. - * - * @param child a {@code Node} object to set. - */ - public void addChild(Node child) { - if (children == null) { - children = new ArrayList<>(); - } - child.parent = this; - children.add(child); - } - - /** - * Inserts a {@code Node} at the specified position in the child list. Will - * throw an ArrayIndexOutOfBoundsException if the index does not exist. - * - * @param index the position to insert at. - * @param child the {@code Node} object to insert. - * @throws IndexOutOfBoundsException if thrown. - */ - public void insertChildAt(int index, Node child) throws IndexOutOfBoundsException { - if (index == getNumberOfChildren()) { - // this is really an append - addChild(child); - } else { - children.get(index); //just to throw the exception, and stop here - children.add(index, child); - child.parent = this; - } - } - - /** - * Remove the {@code Node} element at index index of the {@code List>}. - * - * @param index the index of the element to delete. - * @throws IndexOutOfBoundsException if thrown. - */ - public void removeChildAt(int index) throws IndexOutOfBoundsException { - children.remove(index); - } - - public T getData() { - return this.data; - } - - public void setData(T data) { - this.data = data; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{").append(getData().toString()).append(",["); - int i = 0; - for (Node e : getChildren()) { - if (i > 0) { - sb.append(","); - } - sb.append(e.getData().toString()); - i++; - } - sb.append("]").append("}"); - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.datastruct; + +import java.io.Serializable; +import java.util.List; +import java.util.ArrayList; + +public class Node implements Serializable { + + private static final long serialVersionUID = -7441713052548471005L; + + public T data; + public Node parent; + public List> children; + + public Node() { + super(); + } + + /** + * Convenience constructor to create a {@code Node} with an instance of T. + * + * @param data an instance of T. + */ + public Node(T data) { + this(); + setData(data); + } + + /** + * Return the children of {@code Node}. The {@code Tree} is represented by a single + * root {@code Node} whose children are represented by a {@code List>}. Each of + * these {@code Node} elements in the List can have children. The getChildren() + * method will return the children of a {@code Node}. + * + * @return the children of {@code Node} + */ + public List> getChildren() { + if (this.children == null) { + this.children = new ArrayList<>(); + } + return this.children; + } + + public Node getParent() { + return parent; + } + + /** + * Sets the children of a {@code Node} object. See docs for getChildren() for + * more information. + * + * @param children the {@code List>} to set. + */ + public void setChildren(List> children) { + for (Node child : children) { + child.parent = this; + } + this.children = children; + } + + /** + * Returns the number of immediate children of this {@code Node}. + * + * @return the number of immediate children. + */ + public int getNumberOfChildren() { + if (children == null) { + return 0; + } + return children.size(); + } + + /** + * Adds a child to the list of children for this {@code Node}. The addition of + * the first child will create a new {@code List>}. + * + * @param child a {@code Node} object to set. + */ + public void addChild(Node child) { + if (children == null) { + children = new ArrayList<>(); + } + child.parent = this; + children.add(child); + } + + /** + * Inserts a {@code Node} at the specified position in the child list. Will + * throw an ArrayIndexOutOfBoundsException if the index does not exist. + * + * @param index the position to insert at. + * @param child the {@code Node} object to insert. + * @throws IndexOutOfBoundsException if thrown. + */ + public void insertChildAt(int index, Node child) throws IndexOutOfBoundsException { + if (index == getNumberOfChildren()) { + // this is really an append + addChild(child); + } else { + children.get(index); //just to throw the exception, and stop here + children.add(index, child); + child.parent = this; + } + } + + /** + * Remove the {@code Node} element at index index of the {@code List>}. + * + * @param index the index of the element to delete. + * @throws IndexOutOfBoundsException if thrown. + */ + public void removeChildAt(int index) throws IndexOutOfBoundsException { + children.remove(index); + } + + public T getData() { + return this.data; + } + + public void setData(T data) { + this.data = data; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{").append(getData().toString()).append(",["); + int i = 0; + for (Node e : getChildren()) { + if (i > 0) { + sb.append(","); + } + sb.append(e.getData().toString()); + i++; + } + sb.append("]").append("}"); + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/datastruct/Pair.java b/modules/global/src/com/haulmont/bali/datastruct/Pair.java index 8c8aa0d29e..c1b574c0ea 100644 --- a/modules/global/src/com/haulmont/bali/datastruct/Pair.java +++ b/modules/global/src/com/haulmont/bali/datastruct/Pair.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.datastruct; - -import java.io.Serializable; - -public class Pair implements Serializable { - - private static final long serialVersionUID = -9055932650752898581L; - - private F first; - private S second; - - public Pair(F first, S second) { - this.first = first; - this.second = second; - } - - public F getFirst() { - return first; - } - - public S getSecond() { - return second; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Pair pair = (Pair) o; - - if (first != null ? !first.equals(pair.first) : pair.first != null) return false; - if (second != null ? !second.equals(pair.second) : pair.second != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = first != null ? first.hashCode() : 0; - result = 31 * result + (second != null ? second.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return (first == null ? "null" : first.toString()) + ", " + (second == null ? "null" : second.toString()); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.datastruct; + +import java.io.Serializable; + +public class Pair implements Serializable { + + private static final long serialVersionUID = -9055932650752898581L; + + private F first; + private S second; + + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + public F getFirst() { + return first; + } + + public S getSecond() { + return second; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Pair pair = (Pair) o; + + if (first != null ? !first.equals(pair.first) : pair.first != null) return false; + if (second != null ? !second.equals(pair.second) : pair.second != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = first != null ? first.hashCode() : 0; + result = 31 * result + (second != null ? second.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return (first == null ? "null" : first.toString()) + ", " + (second == null ? "null" : second.toString()); + } +} diff --git a/modules/global/src/com/haulmont/bali/datastruct/Tree.java b/modules/global/src/com/haulmont/bali/datastruct/Tree.java index de73c57ea2..eb6c1ce7b2 100644 --- a/modules/global/src/com/haulmont/bali/datastruct/Tree.java +++ b/modules/global/src/com/haulmont/bali/datastruct/Tree.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.datastruct; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * @param type of tree node data - */ -public class Tree implements Serializable { - private static final long serialVersionUID = 701368293843044209L; - - private List> rootNodes; - - public Tree() { - } - - public Tree(final Node root) { - this.rootNodes = new ArrayList<>(Collections.singletonList(root)); - } - - public Tree(List> rootNodes) { - this.rootNodes = new ArrayList<>(rootNodes); - } - - /** - * Return the first root Node of the tree. - * - * @return the root element. - */ - public Node getRootNode() { - return rootNodes.isEmpty() ? null : rootNodes.get(0); - } - - /** - * Return the root nodes of the tree. - * - * @return the root elements. - */ - public List> getRootNodes() { - if (rootNodes == null) { - rootNodes = new ArrayList<>(); - } - - return this.rootNodes; - } - - /** - * Set the root Element for the tree. - * - * @param rootNodes the root element to set. - */ - public void setRootNodes(List> rootNodes) { - this.rootNodes = rootNodes; - } - - /** - * Returns the {@code Tree} as a List of {@code Node} objects. The elements of the - * List are generated from a pre-order traversal of the tree. - * - * @return a {@code List>}. - */ - public List> toList() { - List> list = new ArrayList<>(); - if (rootNodes != null) { - for (Node rootNode : rootNodes) { - walk(rootNode, list); - } - } - return list; - } - - /** - * Returns a String representation of the Tree. The elements are generated - * from a pre-order traversal of the Tree. - * - * @return the String representation of the Tree. - */ - public String toString() { - return toList().toString(); - } - - /** - * Walks the Tree in pre-order style. This is a recursive method, and is - * called from the toList() method with the root element as the first - * argument. It appends to the second argument, which is passed by reference as it recurses down the tree. - * - * @param element the starting element. - * @param list the output of the walk. - */ - private void walk(Node element, List> list) { - list.add(element); - for (Node data : element.getChildren()) { - walk(data, list); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.datastruct; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @param type of tree node data + */ +public class Tree implements Serializable { + private static final long serialVersionUID = 701368293843044209L; + + private List> rootNodes; + + public Tree() { + } + + public Tree(final Node root) { + this.rootNodes = new ArrayList<>(Collections.singletonList(root)); + } + + public Tree(List> rootNodes) { + this.rootNodes = new ArrayList<>(rootNodes); + } + + /** + * Return the first root Node of the tree. + * + * @return the root element. + */ + public Node getRootNode() { + return rootNodes.isEmpty() ? null : rootNodes.get(0); + } + + /** + * Return the root nodes of the tree. + * + * @return the root elements. + */ + public List> getRootNodes() { + if (rootNodes == null) { + rootNodes = new ArrayList<>(); + } + + return this.rootNodes; + } + + /** + * Set the root Element for the tree. + * + * @param rootNodes the root element to set. + */ + public void setRootNodes(List> rootNodes) { + this.rootNodes = rootNodes; + } + + /** + * Returns the {@code Tree} as a List of {@code Node} objects. The elements of the + * List are generated from a pre-order traversal of the tree. + * + * @return a {@code List>}. + */ + public List> toList() { + List> list = new ArrayList<>(); + if (rootNodes != null) { + for (Node rootNode : rootNodes) { + walk(rootNode, list); + } + } + return list; + } + + /** + * Returns a String representation of the Tree. The elements are generated + * from a pre-order traversal of the Tree. + * + * @return the String representation of the Tree. + */ + public String toString() { + return toList().toString(); + } + + /** + * Walks the Tree in pre-order style. This is a recursive method, and is + * called from the toList() method with the root element as the first + * argument. It appends to the second argument, which is passed by reference as it recurses down the tree. + * + * @param element the starting element. + * @param list the output of the walk. + */ + private void walk(Node element, List> list) { + list.add(element); + for (Node data : element.getChildren()) { + walk(data, list); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/ArrayHandler.java b/modules/global/src/com/haulmont/bali/db/ArrayHandler.java index e46e6db698..fb484721f5 100644 --- a/modules/global/src/com/haulmont/bali/db/ArrayHandler.java +++ b/modules/global/src/com/haulmont/bali/db/ArrayHandler.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import javax.annotation.concurrent.ThreadSafe; -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * ResultSetHandler implementation that converts a - * ResultSet into an Object[]. This class is - * thread safe. - * - */ -@ThreadSafe -public class ArrayHandler implements ResultSetHandler { - - /** - * Singleton processor instance that handlers share to save memory. Notice - * the default scoping to allow only classes in this package to use this - * instance. - */ - static final RowProcessor ROW_PROCESSOR = new BasicRowProcessor(); - - /** - * The RowProcessor implementation to use when converting rows - * into arrays. - */ - private RowProcessor convert = ROW_PROCESSOR; - - /** - * Creates a new instance of ArrayHandler using a - * BasicRowProcessor for conversion. - */ - public ArrayHandler() { - super(); - } - - /** - * Creates a new instance of ArrayHandler. - * - * @param convert The RowProcessor implementation - * to use when converting rows into arrays. - */ - public ArrayHandler(RowProcessor convert) { - super(); - this.convert = convert; - } - - /** - * Places the column values from the first row in an Object[]. - * - * @return An Object[] or null if there are no rows in the - * ResultSet. - * - * @throws SQLException if a database access error occurs - */ - @Override - public Object[] handle(ResultSet rs) throws SQLException { - return rs.next() ? this.convert.toArray(rs) : null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import javax.annotation.concurrent.ThreadSafe; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * ResultSetHandler implementation that converts a + * ResultSet into an Object[]. This class is + * thread safe. + * + */ +@ThreadSafe +public class ArrayHandler implements ResultSetHandler { + + /** + * Singleton processor instance that handlers share to save memory. Notice + * the default scoping to allow only classes in this package to use this + * instance. + */ + static final RowProcessor ROW_PROCESSOR = new BasicRowProcessor(); + + /** + * The RowProcessor implementation to use when converting rows + * into arrays. + */ + private RowProcessor convert = ROW_PROCESSOR; + + /** + * Creates a new instance of ArrayHandler using a + * BasicRowProcessor for conversion. + */ + public ArrayHandler() { + super(); + } + + /** + * Creates a new instance of ArrayHandler. + * + * @param convert The RowProcessor implementation + * to use when converting rows into arrays. + */ + public ArrayHandler(RowProcessor convert) { + super(); + this.convert = convert; + } + + /** + * Places the column values from the first row in an Object[]. + * + * @return An Object[] or null if there are no rows in the + * ResultSet. + * + * @throws SQLException if a database access error occurs + */ + @Override + public Object[] handle(ResultSet rs) throws SQLException { + return rs.next() ? this.convert.toArray(rs) : null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/BasicRowProcessor.java b/modules/global/src/com/haulmont/bali/db/BasicRowProcessor.java index 79a4400eb8..d4cdecf1f1 100644 --- a/modules/global/src/com/haulmont/bali/db/BasicRowProcessor.java +++ b/modules/global/src/com/haulmont/bali/db/BasicRowProcessor.java @@ -1,193 +1,193 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * Basic implementation of the RowProcessor interface. - * - *

- * This class is thread-safe. - *

- * - * @see RowProcessor - */ -public class BasicRowProcessor implements RowProcessor { - - /** - * The default BeanProcessor instance to use if not supplied in the - * constructor. - */ - private static final BeanProcessor defaultConvert = new BeanProcessor(); - - /** - * The Singleton instance of this class. - */ - private static final BasicRowProcessor instance = new BasicRowProcessor(); - - /** - * Returns the Singleton instance of this class. - * - * @return The single instance of this class. - * @deprecated Create instances with the constructors instead. This will - * be removed after DbUtils 1.1. - */ - public static BasicRowProcessor instance() { - return instance; - } - - /** - * Use this to process beans. - */ - private BeanProcessor convert = null; - - /** - * BasicRowProcessor constructor. Bean processing defaults to a - * BeanProcessor instance. - */ - public BasicRowProcessor() { - this(defaultConvert); - } - - /** - * BasicRowProcessor constructor. - * @param convert The BeanProcessor to use when converting columns to - * bean properties. - * @since DbUtils 1.1 - */ - public BasicRowProcessor(BeanProcessor convert) { - super(); - this.convert = convert; - } - - /** - * Convert a ResultSet row into an Object[]. - * This implementation copies column values into the array in the same - * order they're returned from the ResultSet. Array elements - * will be set to null if the column was SQL NULL. - * - */ - @Override - public Object[] toArray(ResultSet rs) throws SQLException { - ResultSetMetaData meta = rs.getMetaData(); - int cols = meta.getColumnCount(); - Object[] result = new Object[cols]; - - for (int i = 0; i < cols; i++) { - result[i] = rs.getObject(i + 1); - } - - return result; - } - - /** - * Convert a ResultSet row into a JavaBean. This - * implementation delegates to a BeanProcessor instance. - */ - @Override - public Object toBean(ResultSet rs, Class type) throws SQLException { - return this.convert.toBean(rs, type); - } - - /** - * Convert a ResultSet into a List of JavaBeans. - * This implementation delegates to a BeanProcessor instance. - */ - @Override - public List toBeanList(ResultSet rs, Class type) throws SQLException { - return this.convert.toBeanList(rs, type); - } - - /** - * Convert a ResultSet row into a Map. This - * implementation returns a Map with case insensitive column - * names as keys. Calls to map.get("COL") and - * map.get("col") return the same value. - */ - @Override - public Map toMap(ResultSet rs) throws SQLException { - Map result = new CaseInsensitiveHashMap(); - ResultSetMetaData rsmd = rs.getMetaData(); - int cols = rsmd.getColumnCount(); - - for (int i = 1; i <= cols; i++) { - result.put(rsmd.getColumnName(i), rs.getObject(i)); - } - - return result; - } - - /** - * A Map that converts all keys to lowercase Strings for case insensitive - * lookups. This is needed for the toMap() implementation because - * databases don't consistently handle the casing of column names. - */ - private static class CaseInsensitiveHashMap extends HashMap { - - /** - * @see java.util.Map#containsKey(java.lang.Object) - */ - @Override - public boolean containsKey(Object key) { - return super.containsKey(key.toString().toLowerCase()); - } - - /** - * @see java.util.Map#get(java.lang.Object) - */ - @Override - public Object get(Object key) { - return super.get(key.toString().toLowerCase()); - } - - /** - * @see java.util.Map#put(java.lang.Object, java.lang.Object) - */ - @Override - public Object put(Object key, Object value) { - return super.put(key.toString().toLowerCase(), value); - } - - /** - * @see java.util.Map#putAll(java.util.Map) - */ - @Override - public void putAll(Map m) { - Iterator iter = m.keySet().iterator(); - while (iter.hasNext()) { - Object key = iter.next(); - Object value = m.get(key); - this.put(key, value); - } - } - - /** - * @see java.util.Map#remove(java.lang.Object) - */ - @Override - public Object remove(Object key) { - return super.remove(key.toString().toLowerCase()); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Basic implementation of the RowProcessor interface. + * + *

+ * This class is thread-safe. + *

+ * + * @see RowProcessor + */ +public class BasicRowProcessor implements RowProcessor { + + /** + * The default BeanProcessor instance to use if not supplied in the + * constructor. + */ + private static final BeanProcessor defaultConvert = new BeanProcessor(); + + /** + * The Singleton instance of this class. + */ + private static final BasicRowProcessor instance = new BasicRowProcessor(); + + /** + * Returns the Singleton instance of this class. + * + * @return The single instance of this class. + * @deprecated Create instances with the constructors instead. This will + * be removed after DbUtils 1.1. + */ + public static BasicRowProcessor instance() { + return instance; + } + + /** + * Use this to process beans. + */ + private BeanProcessor convert = null; + + /** + * BasicRowProcessor constructor. Bean processing defaults to a + * BeanProcessor instance. + */ + public BasicRowProcessor() { + this(defaultConvert); + } + + /** + * BasicRowProcessor constructor. + * @param convert The BeanProcessor to use when converting columns to + * bean properties. + * @since DbUtils 1.1 + */ + public BasicRowProcessor(BeanProcessor convert) { + super(); + this.convert = convert; + } + + /** + * Convert a ResultSet row into an Object[]. + * This implementation copies column values into the array in the same + * order they're returned from the ResultSet. Array elements + * will be set to null if the column was SQL NULL. + * + */ + @Override + public Object[] toArray(ResultSet rs) throws SQLException { + ResultSetMetaData meta = rs.getMetaData(); + int cols = meta.getColumnCount(); + Object[] result = new Object[cols]; + + for (int i = 0; i < cols; i++) { + result[i] = rs.getObject(i + 1); + } + + return result; + } + + /** + * Convert a ResultSet row into a JavaBean. This + * implementation delegates to a BeanProcessor instance. + */ + @Override + public Object toBean(ResultSet rs, Class type) throws SQLException { + return this.convert.toBean(rs, type); + } + + /** + * Convert a ResultSet into a List of JavaBeans. + * This implementation delegates to a BeanProcessor instance. + */ + @Override + public List toBeanList(ResultSet rs, Class type) throws SQLException { + return this.convert.toBeanList(rs, type); + } + + /** + * Convert a ResultSet row into a Map. This + * implementation returns a Map with case insensitive column + * names as keys. Calls to map.get("COL") and + * map.get("col") return the same value. + */ + @Override + public Map toMap(ResultSet rs) throws SQLException { + Map result = new CaseInsensitiveHashMap(); + ResultSetMetaData rsmd = rs.getMetaData(); + int cols = rsmd.getColumnCount(); + + for (int i = 1; i <= cols; i++) { + result.put(rsmd.getColumnName(i), rs.getObject(i)); + } + + return result; + } + + /** + * A Map that converts all keys to lowercase Strings for case insensitive + * lookups. This is needed for the toMap() implementation because + * databases don't consistently handle the casing of column names. + */ + private static class CaseInsensitiveHashMap extends HashMap { + + /** + * @see java.util.Map#containsKey(java.lang.Object) + */ + @Override + public boolean containsKey(Object key) { + return super.containsKey(key.toString().toLowerCase()); + } + + /** + * @see java.util.Map#get(java.lang.Object) + */ + @Override + public Object get(Object key) { + return super.get(key.toString().toLowerCase()); + } + + /** + * @see java.util.Map#put(java.lang.Object, java.lang.Object) + */ + @Override + public Object put(Object key, Object value) { + return super.put(key.toString().toLowerCase(), value); + } + + /** + * @see java.util.Map#putAll(java.util.Map) + */ + @Override + public void putAll(Map m) { + Iterator iter = m.keySet().iterator(); + while (iter.hasNext()) { + Object key = iter.next(); + Object value = m.get(key); + this.put(key, value); + } + } + + /** + * @see java.util.Map#remove(java.lang.Object) + */ + @Override + public Object remove(Object key) { + return super.remove(key.toString().toLowerCase()); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/BeanProcessor.java b/modules/global/src/com/haulmont/bali/db/BeanProcessor.java index 7694b34400..f55de34afe 100644 --- a/modules/global/src/com/haulmont/bali/db/BeanProcessor.java +++ b/modules/global/src/com/haulmont/bali/db/BeanProcessor.java @@ -1,461 +1,461 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import javax.annotation.concurrent.ThreadSafe; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.*; - -/** - *

- * {@code BeanProcessor} matches column names to bean property names - * and converts {@code ResultSet} columns into objects for those bean - * properties. Subclasses should override the methods in the processing chain - * to customize behavior. - *

- * - *

- * This class is thread-safe. - *

- * - * @see BasicRowProcessor - * - * @since DbUtils 1.1 - */ -@ThreadSafe -public class BeanProcessor { - - /** - * Special array value used by {@code mapColumnsToProperties} that - * indicates there is no bean property that matches a column from a - * {@code ResultSet}. - */ - protected static final int PROPERTY_NOT_FOUND = -1; - - /** - * Set a bean's primitive properties to these defaults when SQL NULL - * is returned. These are the same as the defaults that ResultSet get* - * methods return in the event of a NULL column. - */ - private static final Map primitiveDefaults = new HashMap<>(); - - static { - primitiveDefaults.put(Integer.TYPE, new Integer(0)); - primitiveDefaults.put(Short.TYPE, new Short((short) 0)); - primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0)); - primitiveDefaults.put(Float.TYPE, new Float(0)); - primitiveDefaults.put(Double.TYPE, new Double(0)); - primitiveDefaults.put(Long.TYPE, new Long(0)); - primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE); - primitiveDefaults.put(Character.TYPE, new Character('\u0000')); - } - - /** - * Constructor for BeanProcessor. - */ - public BeanProcessor() { - super(); - } - - /** - * Convert a {@code ResultSet} row into a JavaBean. This - * implementation uses reflection and {@code BeanInfo} classes to - * match column names to bean property names. Properties are matched to - * columns based on several factors: - *
- *
    - *
  1. - * The class has a writable property with the same name as a column. - * The name comparison is case insensitive. - *
  2. - * - *
  3. - * The column type can be converted to the property's set method - * parameter type with a ResultSet.get* method. If the conversion fails - * (ie. the property was an int and the column was a Timestamp) an - * SQLException is thrown. - *
  4. - *
- * - *

- * Primitive bean properties are set to their defaults when SQL NULL is - * returned from the {@code ResultSet}. Numeric fields are set to 0 - * and booleans are set to false. Object bean properties are set to - * {@code null} when SQL NULL is returned. This is the same behavior - * as the {@code ResultSet} get* methods. - *

- * - * @param rs ResultSet that supplies the bean data - * @param type Class from which to create the bean instance - * @throws SQLException if a database access error occurs - * @return the newly created bean - */ - public Object toBean(ResultSet rs, Class type) throws SQLException { - - PropertyDescriptor[] props = this.propertyDescriptors(type); - - ResultSetMetaData rsmd = rs.getMetaData(); - int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); - - return this.createBean(rs, type, props, columnToProperty); - } - - /** - * Convert a {@code ResultSet} into a {@code List} of JavaBeans. - * This implementation uses reflection and {@code BeanInfo} classes to - * match column names to bean property names. Properties are matched to - * columns based on several factors: - *
- *
    - *
  1. - * The class has a writable property with the same name as a column. - * The name comparison is case insensitive. - *
  2. - * - *
  3. - * The column type can be converted to the property's set method - * parameter type with a ResultSet.get* method. If the conversion fails - * (ie. the property was an int and the column was a Timestamp) an - * SQLException is thrown. - *
  4. - *
- * - *

- * Primitive bean properties are set to their defaults when SQL NULL is - * returned from the {@code ResultSet}. Numeric fields are set to 0 - * and booleans are set to false. Object bean properties are set to - * {@code null} when SQL NULL is returned. This is the same behavior - * as the {@code ResultSet} get* methods. - *

- * - * @param rs ResultSet that supplies the bean data - * @param type Class from which to create the bean instance - * @throws SQLException if a database access error occurs - * @return the newly created List of beans - */ - public List toBeanList(ResultSet rs, Class type) throws SQLException { - List results = new ArrayList(); - - if (!rs.next()) { - return results; - } - - PropertyDescriptor[] props = this.propertyDescriptors(type); - ResultSetMetaData rsmd = rs.getMetaData(); - int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); - - do { - results.add(this.createBean(rs, type, props, columnToProperty)); - } while (rs.next()); - - return results; - } - - /** - * Creates a new object and initializes its fields from the ResultSet. - * - * @param rs The result set. - * @param type The bean type (the return type of the object). - * @param props The property descriptors. - * @param columnToProperty The column indices in the result set. - * @return An initialized object. - * @throws SQLException if a database error occurs. - */ - private Object createBean(ResultSet rs, Class type, - PropertyDescriptor[] props, int[] columnToProperty) - throws SQLException { - - Object bean = this.newInstance(type); - - for (int i = 1; i < columnToProperty.length; i++) { - - if (columnToProperty[i] == PROPERTY_NOT_FOUND) { - continue; - } - - PropertyDescriptor prop = props[columnToProperty[i]]; - Class propType = prop.getPropertyType(); - - Object value = this.processColumn(rs, i, propType); - - if (propType != null && value == null && propType.isPrimitive()) { - value = primitiveDefaults.get(propType); - } - - this.callSetter(bean, prop, value); - } - - return bean; - } - - /** - * Calls the setter method on the target object for the given property. - * If no setter method exists for the property, this method does nothing. - * @param target The object to set the property on. - * @param prop The property to set. - * @param value The value to pass into the setter. - * @throws SQLException if an error occurs setting the property. - */ - private void callSetter(Object target, PropertyDescriptor prop, Object value) - throws SQLException { - - Method setter = prop.getWriteMethod(); - - if (setter == null) { - return; - } - - Class[] params = setter.getParameterTypes(); - try { - // convert types for some popular ones - if (value != null) { - if (value instanceof java.util.Date) { - if (params[0].getName().equals("java.sql.Date")) { - value = new java.sql.Date(((java.util.Date) value).getTime()); - } else - if (params[0].getName().equals("java.sql.Time")) { - value = new java.sql.Time(((java.util.Date) value).getTime()); - } else - if (params[0].getName().equals("java.sql.Timestamp")) { - value = new java.sql.Timestamp(((java.util.Date) value).getTime()); - } - } - } - - // Don't call setter if the value object isn't the right type - if (this.isCompatibleType(value, params[0])) { - setter.invoke(target, new Object[]{value}); - } else { - throw new SQLException( - "Cannot set " + prop.getName() + ": incompatible types."); - } - } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { - throw new SQLException( - "Cannot set " + prop.getName() + ": " + e.getMessage()); - } - } - - /** - * ResultSet.getObject() returns an Integer object for an INT column. The - * setter method for the property might take an Integer or a primitive int. - * This method returns true if the value can be successfully passed into - * the setter method. Remember, Method.invoke() handles the unwrapping - * of Integer into an int. - * - * @param value The value to be passed into the setter method. - * @param type The setter's parameter type. - * @return boolean True if the value is compatible. - */ - private boolean isCompatibleType(Object value, Class type) { - // Do object check first, then primitives - if (value == null || type.isInstance(value)) { - return true; - - } else if ( - type.equals(Integer.TYPE) && Integer.class.isInstance(value)) { - return true; - - } else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) { - return true; - - } else if ( - type.equals(Double.TYPE) && Double.class.isInstance(value)) { - return true; - - } else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) { - return true; - - } else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) { - return true; - - } else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) { - return true; - - } else if ( - type.equals(Character.TYPE) && Character.class.isInstance(value)) { - return true; - - } else if ( - type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) { - return true; - - } else { - return false; - } - - } - - /** - * Factory method that returns a new instance of the given Class. This - * is called at the start of the bean creation process and may be - * overridden to provide custom behavior like returning a cached bean - * instance. - * - * @param c The Class to create an object from. - * @return A newly created object of the Class. - * @throws SQLException if creation failed. - */ - protected Object newInstance(Class c) throws SQLException { - try { - return c.newInstance(); - - } catch (InstantiationException e) { - throw new SQLException( - "Cannot create " + c.getName() + ": " + e.getMessage()); - - } catch (IllegalAccessException e) { - throw new SQLException( - "Cannot create " + c.getName() + ": " + e.getMessage()); - } - } - - /** - * Returns a PropertyDescriptor[] for the given Class. - * - * @param c The Class to retrieve PropertyDescriptors for. - * @return A PropertyDescriptor[] describing the Class. - * @throws SQLException if introspection failed. - */ - private PropertyDescriptor[] propertyDescriptors(Class c) - throws SQLException { - // Introspector caches BeanInfo classes for better performance - BeanInfo beanInfo; - try { - beanInfo = Introspector.getBeanInfo(c); - - } catch (IntrospectionException e) { - throw new SQLException( - "Bean introspection failed: " + e.getMessage()); - } - - return beanInfo.getPropertyDescriptors(); - } - - /** - * The positions in the returned array represent column numbers. The - * values stored at each position represent the index in the - * {@code PropertyDescriptor[]} for the bean property that matches - * the column name. If no bean property was found for a column, the - * position is set to {@code PROPERTY_NOT_FOUND}. - * - * @param rsmd The {@code ResultSetMetaData} containing column - * information. - * - * @param props The bean property descriptors. - * - * @throws SQLException if a database access error occurs - * - * @return An int[] with column index to property index mappings. The 0th - * element is meaningless because JDBC column indexing starts at 1. - */ - protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, - PropertyDescriptor[] props) throws SQLException { - - int cols = rsmd.getColumnCount(); - int[] columnToProperty = new int[cols + 1]; - Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND); - - for (int col = 1; col <= cols; col++) { - String columnName = rsmd.getColumnName(col); - for (int i = 0; i < props.length; i++) { - - if (columnName.equalsIgnoreCase(props[i].getName())) { - columnToProperty[col] = i; - break; - } - } - } - - return columnToProperty; - } - - /** - * Convert a {@code ResultSet} column into an object. Simple - * implementations could just call {@code rs.getObject(index)} while - * more complex implementations could perform type manipulation to match - * the column's type to the bean property type. - * - *

- * This implementation calls the appropriate {@code ResultSet} getter - * method for the given property type to perform the type conversion. If - * the property type doesn't match one of the supported - * {@code ResultSet} types, {@code getObject} is called. - *

- * - * @param rs The {@code ResultSet} currently being processed. It is - * positioned on a valid row before being passed into this method. - * - * @param index The current column index being processed. - * - * @param propType The bean property type that this column needs to be - * converted into. - * - * @throws SQLException if a database access error occurs - * - * @return The object from the {@code ResultSet} at the given column - * index after optional type processing or {@code null} if the column - * value was SQL NULL. - */ - protected Object processColumn(ResultSet rs, int index, Class propType) - throws SQLException { - - if (propType.equals(String.class)) { - return rs.getString(index); - - } else if ( - propType.equals(Integer.TYPE) || propType.equals(Integer.class)) { - return new Integer(rs.getInt(index)); - - } else if ( - propType.equals(Boolean.TYPE) || propType.equals(Boolean.class)) { - return new Boolean(rs.getBoolean(index)); - - } else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) { - return new Long(rs.getLong(index)); - - } else if ( - propType.equals(Double.TYPE) || propType.equals(Double.class)) { - return new Double(rs.getDouble(index)); - - } else if ( - propType.equals(Float.TYPE) || propType.equals(Float.class)) { - return new Float(rs.getFloat(index)); - - } else if ( - propType.equals(Short.TYPE) || propType.equals(Short.class)) { - return new Short(rs.getShort(index)); - - } else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) { - return new Byte(rs.getByte(index)); - - } else if (propType.equals(Timestamp.class)) { - return rs.getTimestamp(index); - - } else { - return rs.getObject(index); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import javax.annotation.concurrent.ThreadSafe; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.*; + +/** + *

+ * {@code BeanProcessor} matches column names to bean property names + * and converts {@code ResultSet} columns into objects for those bean + * properties. Subclasses should override the methods in the processing chain + * to customize behavior. + *

+ * + *

+ * This class is thread-safe. + *

+ * + * @see BasicRowProcessor + * + * @since DbUtils 1.1 + */ +@ThreadSafe +public class BeanProcessor { + + /** + * Special array value used by {@code mapColumnsToProperties} that + * indicates there is no bean property that matches a column from a + * {@code ResultSet}. + */ + protected static final int PROPERTY_NOT_FOUND = -1; + + /** + * Set a bean's primitive properties to these defaults when SQL NULL + * is returned. These are the same as the defaults that ResultSet get* + * methods return in the event of a NULL column. + */ + private static final Map primitiveDefaults = new HashMap<>(); + + static { + primitiveDefaults.put(Integer.TYPE, new Integer(0)); + primitiveDefaults.put(Short.TYPE, new Short((short) 0)); + primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0)); + primitiveDefaults.put(Float.TYPE, new Float(0)); + primitiveDefaults.put(Double.TYPE, new Double(0)); + primitiveDefaults.put(Long.TYPE, new Long(0)); + primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE); + primitiveDefaults.put(Character.TYPE, new Character('\u0000')); + } + + /** + * Constructor for BeanProcessor. + */ + public BeanProcessor() { + super(); + } + + /** + * Convert a {@code ResultSet} row into a JavaBean. This + * implementation uses reflection and {@code BeanInfo} classes to + * match column names to bean property names. Properties are matched to + * columns based on several factors: + *
+ *
    + *
  1. + * The class has a writable property with the same name as a column. + * The name comparison is case insensitive. + *
  2. + * + *
  3. + * The column type can be converted to the property's set method + * parameter type with a ResultSet.get* method. If the conversion fails + * (ie. the property was an int and the column was a Timestamp) an + * SQLException is thrown. + *
  4. + *
+ * + *

+ * Primitive bean properties are set to their defaults when SQL NULL is + * returned from the {@code ResultSet}. Numeric fields are set to 0 + * and booleans are set to false. Object bean properties are set to + * {@code null} when SQL NULL is returned. This is the same behavior + * as the {@code ResultSet} get* methods. + *

+ * + * @param rs ResultSet that supplies the bean data + * @param type Class from which to create the bean instance + * @throws SQLException if a database access error occurs + * @return the newly created bean + */ + public Object toBean(ResultSet rs, Class type) throws SQLException { + + PropertyDescriptor[] props = this.propertyDescriptors(type); + + ResultSetMetaData rsmd = rs.getMetaData(); + int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); + + return this.createBean(rs, type, props, columnToProperty); + } + + /** + * Convert a {@code ResultSet} into a {@code List} of JavaBeans. + * This implementation uses reflection and {@code BeanInfo} classes to + * match column names to bean property names. Properties are matched to + * columns based on several factors: + *
+ *
    + *
  1. + * The class has a writable property with the same name as a column. + * The name comparison is case insensitive. + *
  2. + * + *
  3. + * The column type can be converted to the property's set method + * parameter type with a ResultSet.get* method. If the conversion fails + * (ie. the property was an int and the column was a Timestamp) an + * SQLException is thrown. + *
  4. + *
+ * + *

+ * Primitive bean properties are set to their defaults when SQL NULL is + * returned from the {@code ResultSet}. Numeric fields are set to 0 + * and booleans are set to false. Object bean properties are set to + * {@code null} when SQL NULL is returned. This is the same behavior + * as the {@code ResultSet} get* methods. + *

+ * + * @param rs ResultSet that supplies the bean data + * @param type Class from which to create the bean instance + * @throws SQLException if a database access error occurs + * @return the newly created List of beans + */ + public List toBeanList(ResultSet rs, Class type) throws SQLException { + List results = new ArrayList(); + + if (!rs.next()) { + return results; + } + + PropertyDescriptor[] props = this.propertyDescriptors(type); + ResultSetMetaData rsmd = rs.getMetaData(); + int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); + + do { + results.add(this.createBean(rs, type, props, columnToProperty)); + } while (rs.next()); + + return results; + } + + /** + * Creates a new object and initializes its fields from the ResultSet. + * + * @param rs The result set. + * @param type The bean type (the return type of the object). + * @param props The property descriptors. + * @param columnToProperty The column indices in the result set. + * @return An initialized object. + * @throws SQLException if a database error occurs. + */ + private Object createBean(ResultSet rs, Class type, + PropertyDescriptor[] props, int[] columnToProperty) + throws SQLException { + + Object bean = this.newInstance(type); + + for (int i = 1; i < columnToProperty.length; i++) { + + if (columnToProperty[i] == PROPERTY_NOT_FOUND) { + continue; + } + + PropertyDescriptor prop = props[columnToProperty[i]]; + Class propType = prop.getPropertyType(); + + Object value = this.processColumn(rs, i, propType); + + if (propType != null && value == null && propType.isPrimitive()) { + value = primitiveDefaults.get(propType); + } + + this.callSetter(bean, prop, value); + } + + return bean; + } + + /** + * Calls the setter method on the target object for the given property. + * If no setter method exists for the property, this method does nothing. + * @param target The object to set the property on. + * @param prop The property to set. + * @param value The value to pass into the setter. + * @throws SQLException if an error occurs setting the property. + */ + private void callSetter(Object target, PropertyDescriptor prop, Object value) + throws SQLException { + + Method setter = prop.getWriteMethod(); + + if (setter == null) { + return; + } + + Class[] params = setter.getParameterTypes(); + try { + // convert types for some popular ones + if (value != null) { + if (value instanceof java.util.Date) { + if (params[0].getName().equals("java.sql.Date")) { + value = new java.sql.Date(((java.util.Date) value).getTime()); + } else + if (params[0].getName().equals("java.sql.Time")) { + value = new java.sql.Time(((java.util.Date) value).getTime()); + } else + if (params[0].getName().equals("java.sql.Timestamp")) { + value = new java.sql.Timestamp(((java.util.Date) value).getTime()); + } + } + } + + // Don't call setter if the value object isn't the right type + if (this.isCompatibleType(value, params[0])) { + setter.invoke(target, new Object[]{value}); + } else { + throw new SQLException( + "Cannot set " + prop.getName() + ": incompatible types."); + } + } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { + throw new SQLException( + "Cannot set " + prop.getName() + ": " + e.getMessage()); + } + } + + /** + * ResultSet.getObject() returns an Integer object for an INT column. The + * setter method for the property might take an Integer or a primitive int. + * This method returns true if the value can be successfully passed into + * the setter method. Remember, Method.invoke() handles the unwrapping + * of Integer into an int. + * + * @param value The value to be passed into the setter method. + * @param type The setter's parameter type. + * @return boolean True if the value is compatible. + */ + private boolean isCompatibleType(Object value, Class type) { + // Do object check first, then primitives + if (value == null || type.isInstance(value)) { + return true; + + } else if ( + type.equals(Integer.TYPE) && Integer.class.isInstance(value)) { + return true; + + } else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) { + return true; + + } else if ( + type.equals(Double.TYPE) && Double.class.isInstance(value)) { + return true; + + } else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) { + return true; + + } else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) { + return true; + + } else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) { + return true; + + } else if ( + type.equals(Character.TYPE) && Character.class.isInstance(value)) { + return true; + + } else if ( + type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) { + return true; + + } else { + return false; + } + + } + + /** + * Factory method that returns a new instance of the given Class. This + * is called at the start of the bean creation process and may be + * overridden to provide custom behavior like returning a cached bean + * instance. + * + * @param c The Class to create an object from. + * @return A newly created object of the Class. + * @throws SQLException if creation failed. + */ + protected Object newInstance(Class c) throws SQLException { + try { + return c.newInstance(); + + } catch (InstantiationException e) { + throw new SQLException( + "Cannot create " + c.getName() + ": " + e.getMessage()); + + } catch (IllegalAccessException e) { + throw new SQLException( + "Cannot create " + c.getName() + ": " + e.getMessage()); + } + } + + /** + * Returns a PropertyDescriptor[] for the given Class. + * + * @param c The Class to retrieve PropertyDescriptors for. + * @return A PropertyDescriptor[] describing the Class. + * @throws SQLException if introspection failed. + */ + private PropertyDescriptor[] propertyDescriptors(Class c) + throws SQLException { + // Introspector caches BeanInfo classes for better performance + BeanInfo beanInfo; + try { + beanInfo = Introspector.getBeanInfo(c); + + } catch (IntrospectionException e) { + throw new SQLException( + "Bean introspection failed: " + e.getMessage()); + } + + return beanInfo.getPropertyDescriptors(); + } + + /** + * The positions in the returned array represent column numbers. The + * values stored at each position represent the index in the + * {@code PropertyDescriptor[]} for the bean property that matches + * the column name. If no bean property was found for a column, the + * position is set to {@code PROPERTY_NOT_FOUND}. + * + * @param rsmd The {@code ResultSetMetaData} containing column + * information. + * + * @param props The bean property descriptors. + * + * @throws SQLException if a database access error occurs + * + * @return An int[] with column index to property index mappings. The 0th + * element is meaningless because JDBC column indexing starts at 1. + */ + protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, + PropertyDescriptor[] props) throws SQLException { + + int cols = rsmd.getColumnCount(); + int[] columnToProperty = new int[cols + 1]; + Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND); + + for (int col = 1; col <= cols; col++) { + String columnName = rsmd.getColumnName(col); + for (int i = 0; i < props.length; i++) { + + if (columnName.equalsIgnoreCase(props[i].getName())) { + columnToProperty[col] = i; + break; + } + } + } + + return columnToProperty; + } + + /** + * Convert a {@code ResultSet} column into an object. Simple + * implementations could just call {@code rs.getObject(index)} while + * more complex implementations could perform type manipulation to match + * the column's type to the bean property type. + * + *

+ * This implementation calls the appropriate {@code ResultSet} getter + * method for the given property type to perform the type conversion. If + * the property type doesn't match one of the supported + * {@code ResultSet} types, {@code getObject} is called. + *

+ * + * @param rs The {@code ResultSet} currently being processed. It is + * positioned on a valid row before being passed into this method. + * + * @param index The current column index being processed. + * + * @param propType The bean property type that this column needs to be + * converted into. + * + * @throws SQLException if a database access error occurs + * + * @return The object from the {@code ResultSet} at the given column + * index after optional type processing or {@code null} if the column + * value was SQL NULL. + */ + protected Object processColumn(ResultSet rs, int index, Class propType) + throws SQLException { + + if (propType.equals(String.class)) { + return rs.getString(index); + + } else if ( + propType.equals(Integer.TYPE) || propType.equals(Integer.class)) { + return new Integer(rs.getInt(index)); + + } else if ( + propType.equals(Boolean.TYPE) || propType.equals(Boolean.class)) { + return new Boolean(rs.getBoolean(index)); + + } else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) { + return new Long(rs.getLong(index)); + + } else if ( + propType.equals(Double.TYPE) || propType.equals(Double.class)) { + return new Double(rs.getDouble(index)); + + } else if ( + propType.equals(Float.TYPE) || propType.equals(Float.class)) { + return new Float(rs.getFloat(index)); + + } else if ( + propType.equals(Short.TYPE) || propType.equals(Short.class)) { + return new Short(rs.getShort(index)); + + } else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) { + return new Byte(rs.getByte(index)); + + } else if (propType.equals(Timestamp.class)) { + return rs.getTimestamp(index); + + } else { + return rs.getObject(index); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/DbUtils.java b/modules/global/src/com/haulmont/bali/db/DbUtils.java index 65a2a66904..efdc891b28 100644 --- a/modules/global/src/com/haulmont/bali/db/DbUtils.java +++ b/modules/global/src/com/haulmont/bali/db/DbUtils.java @@ -1,294 +1,294 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import javax.annotation.concurrent.ThreadSafe; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -/** - * A collection of JDBC helper methods. This class is thread safe. - * - */ -@ThreadSafe -public final class DbUtils { - - private DbUtils() { - } - - /** - * Close a Connection, avoid closing if null. - * - * @param conn Connection to close. - * @throws SQLException if a database access error occurs - */ - public static void close(Connection conn) throws SQLException { - if (conn != null) { - conn.close(); - } - } - - /** - * Close a ResultSet, avoid closing if null. - * - * @param rs ResultSet to close. - * @throws SQLException if a database access error occurs - */ - public static void close(ResultSet rs) throws SQLException { - if (rs != null) { - rs.close(); - } - } - - /** - * Close a Statement, avoid closing if null. - * - * @param stmt Statement to close. - * @throws SQLException if a database access error occurs - */ - public static void close(Statement stmt) throws SQLException { - if (stmt != null) { - stmt.close(); - } - } - - /** - * Close a Connection, avoid closing if null and hide - * any SQLExceptions that occur. - * - * @param conn Connection to close. - */ - public static void closeQuietly(Connection conn) { - try { - close(conn); - } catch (SQLException e) { - // quiet - } - } - - /** - * Close a Connection, Statement and - * ResultSet. Avoid closing if null and hide any - * SQLExceptions that occur. - * - * @param conn Connection to close. - * @param stmt Statement to close. - * @param rs ResultSet to close. - */ - public static void closeQuietly(Connection conn, Statement stmt, - ResultSet rs) { - - try { - closeQuietly(rs); - } finally { - try { - closeQuietly(stmt); - } finally { - closeQuietly(conn); - } - } - - } - - /** - * Close a ResultSet, avoid closing if null and hide any - * SQLExceptions that occur. - * - * @param rs ResultSet to close. - */ - public static void closeQuietly(ResultSet rs) { - try { - close(rs); - } catch (SQLException e) { - // quiet - } - } - - /** - * Close a Statement, avoid closing if null and hide - * any SQLExceptions that occur. - * - * @param stmt Statement to close. - */ - public static void closeQuietly(Statement stmt) { - try { - close(stmt); - } catch (SQLException e) { - // quiet - } - } - - /** - * Commits a Connection then closes it, avoid closing if null. - * - * @param conn Connection to close. - * @throws SQLException if a database access error occurs - */ - public static void commitAndClose(Connection conn) throws SQLException { - if (conn != null) { - try { - conn.commit(); - } finally { - conn.close(); - } - } - } - - /** - * Commits a Connection then closes it, avoid closing if null - * and hide any SQLExceptions that occur. - * - * @param conn Connection to close. - */ - public static void commitAndCloseQuietly(Connection conn) { - try { - commitAndClose(conn); - } catch (SQLException e) { - // quiet - } - } - - /** - * Loads and registers a database driver class. - * If this succeeds, it returns true, else it returns false. - * - * @param driverClassName of driver to load - * @return boolean true if the driver was found, otherwise false - */ - public static boolean loadDriver(String driverClassName) { - try { - Class.forName(driverClassName).newInstance(); - return true; - - } catch (ClassNotFoundException e) { - return false; - - } catch (IllegalAccessException e) { - // Constructor is private, OK for DriverManager contract - return true; - - } catch (InstantiationException e) { - return false; - - } catch (Throwable e) { - return false; - } - } - - /** - * Print the stack trace for a SQLException to STDERR. - * - * @param e SQLException to print stack trace of - */ - public static void printStackTrace(SQLException e) { - printStackTrace(e, new PrintWriter(new OutputStreamWriter(System.err, StandardCharsets.UTF_8))); - } - - /** - * Print the stack trace for a SQLException to a - * specified PrintWriter. - * - * @param e SQLException to print stack trace of - * @param pw PrintWriter to print to - */ - public static void printStackTrace(SQLException e, PrintWriter pw) { - - SQLException next = e; - while (next != null) { - next.printStackTrace(pw); - next = next.getNextException(); - if (next != null) { - pw.println("Next SQLException:"); - } - } - } - - /** - * Print warnings on a Connection to STDERR. - * - * @param conn Connection to print warnings from - */ - public static void printWarnings(Connection conn) { - printWarnings(conn, new PrintWriter(new OutputStreamWriter(System.err, StandardCharsets.UTF_8))); - } - - /** - * Print warnings on a Connection to a specified PrintWriter. - * - * @param conn Connection to print warnings from - * @param pw PrintWriter to print to - */ - public static void printWarnings(Connection conn, PrintWriter pw) { - if (conn != null) { - try { - printStackTrace(conn.getWarnings(), pw); - } catch (SQLException e) { - printStackTrace(e, pw); - } - } - } - - /** - * Rollback any changes made on the given connection. - * @param conn Connection to rollback. A null value is legal. - * @throws SQLException if a database access error occurs - */ - public static void rollback(Connection conn) throws SQLException { - if (conn != null) { - conn.rollback(); - } - } - - /** - * Performs a rollback on the Connection then closes it, - * avoid closing if null. - * - * @param conn Connection to rollback. A null value is legal. - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - public static void rollbackAndClose(Connection conn) throws SQLException { - if (conn != null) { - try { - conn.rollback(); - } finally { - conn.close(); - } - } - } - - /** - * Performs a rollback on the Connection then closes it, - * avoid closing if null and hide any SQLExceptions that occur. - * - * @param conn Connection to rollback. A null value is legal. - * @since DbUtils 1.1 - */ - public static void rollbackAndCloseQuietly(Connection conn) { - try { - rollbackAndClose(conn); - } catch (SQLException e) { - // quiet - } - } - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import javax.annotation.concurrent.ThreadSafe; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A collection of JDBC helper methods. This class is thread safe. + * + */ +@ThreadSafe +public final class DbUtils { + + private DbUtils() { + } + + /** + * Close a Connection, avoid closing if null. + * + * @param conn Connection to close. + * @throws SQLException if a database access error occurs + */ + public static void close(Connection conn) throws SQLException { + if (conn != null) { + conn.close(); + } + } + + /** + * Close a ResultSet, avoid closing if null. + * + * @param rs ResultSet to close. + * @throws SQLException if a database access error occurs + */ + public static void close(ResultSet rs) throws SQLException { + if (rs != null) { + rs.close(); + } + } + + /** + * Close a Statement, avoid closing if null. + * + * @param stmt Statement to close. + * @throws SQLException if a database access error occurs + */ + public static void close(Statement stmt) throws SQLException { + if (stmt != null) { + stmt.close(); + } + } + + /** + * Close a Connection, avoid closing if null and hide + * any SQLExceptions that occur. + * + * @param conn Connection to close. + */ + public static void closeQuietly(Connection conn) { + try { + close(conn); + } catch (SQLException e) { + // quiet + } + } + + /** + * Close a Connection, Statement and + * ResultSet. Avoid closing if null and hide any + * SQLExceptions that occur. + * + * @param conn Connection to close. + * @param stmt Statement to close. + * @param rs ResultSet to close. + */ + public static void closeQuietly(Connection conn, Statement stmt, + ResultSet rs) { + + try { + closeQuietly(rs); + } finally { + try { + closeQuietly(stmt); + } finally { + closeQuietly(conn); + } + } + + } + + /** + * Close a ResultSet, avoid closing if null and hide any + * SQLExceptions that occur. + * + * @param rs ResultSet to close. + */ + public static void closeQuietly(ResultSet rs) { + try { + close(rs); + } catch (SQLException e) { + // quiet + } + } + + /** + * Close a Statement, avoid closing if null and hide + * any SQLExceptions that occur. + * + * @param stmt Statement to close. + */ + public static void closeQuietly(Statement stmt) { + try { + close(stmt); + } catch (SQLException e) { + // quiet + } + } + + /** + * Commits a Connection then closes it, avoid closing if null. + * + * @param conn Connection to close. + * @throws SQLException if a database access error occurs + */ + public static void commitAndClose(Connection conn) throws SQLException { + if (conn != null) { + try { + conn.commit(); + } finally { + conn.close(); + } + } + } + + /** + * Commits a Connection then closes it, avoid closing if null + * and hide any SQLExceptions that occur. + * + * @param conn Connection to close. + */ + public static void commitAndCloseQuietly(Connection conn) { + try { + commitAndClose(conn); + } catch (SQLException e) { + // quiet + } + } + + /** + * Loads and registers a database driver class. + * If this succeeds, it returns true, else it returns false. + * + * @param driverClassName of driver to load + * @return boolean true if the driver was found, otherwise false + */ + public static boolean loadDriver(String driverClassName) { + try { + Class.forName(driverClassName).newInstance(); + return true; + + } catch (ClassNotFoundException e) { + return false; + + } catch (IllegalAccessException e) { + // Constructor is private, OK for DriverManager contract + return true; + + } catch (InstantiationException e) { + return false; + + } catch (Throwable e) { + return false; + } + } + + /** + * Print the stack trace for a SQLException to STDERR. + * + * @param e SQLException to print stack trace of + */ + public static void printStackTrace(SQLException e) { + printStackTrace(e, new PrintWriter(new OutputStreamWriter(System.err, StandardCharsets.UTF_8))); + } + + /** + * Print the stack trace for a SQLException to a + * specified PrintWriter. + * + * @param e SQLException to print stack trace of + * @param pw PrintWriter to print to + */ + public static void printStackTrace(SQLException e, PrintWriter pw) { + + SQLException next = e; + while (next != null) { + next.printStackTrace(pw); + next = next.getNextException(); + if (next != null) { + pw.println("Next SQLException:"); + } + } + } + + /** + * Print warnings on a Connection to STDERR. + * + * @param conn Connection to print warnings from + */ + public static void printWarnings(Connection conn) { + printWarnings(conn, new PrintWriter(new OutputStreamWriter(System.err, StandardCharsets.UTF_8))); + } + + /** + * Print warnings on a Connection to a specified PrintWriter. + * + * @param conn Connection to print warnings from + * @param pw PrintWriter to print to + */ + public static void printWarnings(Connection conn, PrintWriter pw) { + if (conn != null) { + try { + printStackTrace(conn.getWarnings(), pw); + } catch (SQLException e) { + printStackTrace(e, pw); + } + } + } + + /** + * Rollback any changes made on the given connection. + * @param conn Connection to rollback. A null value is legal. + * @throws SQLException if a database access error occurs + */ + public static void rollback(Connection conn) throws SQLException { + if (conn != null) { + conn.rollback(); + } + } + + /** + * Performs a rollback on the Connection then closes it, + * avoid closing if null. + * + * @param conn Connection to rollback. A null value is legal. + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + public static void rollbackAndClose(Connection conn) throws SQLException { + if (conn != null) { + try { + conn.rollback(); + } finally { + conn.close(); + } + } + } + + /** + * Performs a rollback on the Connection then closes it, + * avoid closing if null and hide any SQLExceptions that occur. + * + * @param conn Connection to rollback. A null value is legal. + * @since DbUtils 1.1 + */ + public static void rollbackAndCloseQuietly(Connection conn) { + try { + rollbackAndClose(conn); + } catch (SQLException e) { + // quiet + } + } + +} diff --git a/modules/global/src/com/haulmont/bali/db/ListArrayHandler.java b/modules/global/src/com/haulmont/bali/db/ListArrayHandler.java index 303aea5f5b..43d8e99897 100644 --- a/modules/global/src/com/haulmont/bali/db/ListArrayHandler.java +++ b/modules/global/src/com/haulmont/bali/db/ListArrayHandler.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -public class ListArrayHandler implements ResultSetHandler> { - - /** - * The RowProcessor implementation to use when converting rows - * into Maps. - */ - private RowProcessor convert; - - public ListArrayHandler() { - convert = ArrayHandler.ROW_PROCESSOR; - } - - public ListArrayHandler(RowProcessor convert) { - this.convert = convert; - } - - @Override - public List handle(ResultSet rs) throws SQLException { - List result = new ArrayList<>(); - while (rs.next()) { - result.add(convert.toArray(rs)); - } - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class ListArrayHandler implements ResultSetHandler> { + + /** + * The RowProcessor implementation to use when converting rows + * into Maps. + */ + private RowProcessor convert; + + public ListArrayHandler() { + convert = ArrayHandler.ROW_PROCESSOR; + } + + public ListArrayHandler(RowProcessor convert) { + this.convert = convert; + } + + @Override + public List handle(ResultSet rs) throws SQLException { + List result = new ArrayList<>(); + while (rs.next()) { + result.add(convert.toArray(rs)); + } + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/MapHandler.java b/modules/global/src/com/haulmont/bali/db/MapHandler.java index b23be839ee..06977fe39b 100644 --- a/modules/global/src/com/haulmont/bali/db/MapHandler.java +++ b/modules/global/src/com/haulmont/bali/db/MapHandler.java @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Map; - -/** - * ResultSetHandler implementation that converts the first - * ResultSet row into a Map. This class is thread - * safe. - * - */ -public class MapHandler implements ResultSetHandler> { - - /** - * The RowProcessor implementation to use when converting rows - * into Maps. - */ - private RowProcessor convert = ArrayHandler.ROW_PROCESSOR; - - /** - * Creates a new instance of MapHandler using a - * BasicRowProcessor for conversion. - */ - public MapHandler() { - super(); - } - - /** - * Creates a new instance of MapHandler. - * - * @param convert The RowProcessor implementation - * to use when converting rows into Maps. - */ - public MapHandler(RowProcessor convert) { - super(); - this.convert = convert; - } - - /** - * Converts the first row in the ResultSet into a - * Map. - * - * @return A Map with the values from the first row or - * null if there are no rows in the ResultSet. - * - * @throws SQLException if a database access error occurs - * - */ - @Override - public Map handle(ResultSet rs) throws SQLException { - return rs.next() ? this.convert.toMap(rs) : null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +/** + * ResultSetHandler implementation that converts the first + * ResultSet row into a Map. This class is thread + * safe. + * + */ +public class MapHandler implements ResultSetHandler> { + + /** + * The RowProcessor implementation to use when converting rows + * into Maps. + */ + private RowProcessor convert = ArrayHandler.ROW_PROCESSOR; + + /** + * Creates a new instance of MapHandler using a + * BasicRowProcessor for conversion. + */ + public MapHandler() { + super(); + } + + /** + * Creates a new instance of MapHandler. + * + * @param convert The RowProcessor implementation + * to use when converting rows into Maps. + */ + public MapHandler(RowProcessor convert) { + super(); + this.convert = convert; + } + + /** + * Converts the first row in the ResultSet into a + * Map. + * + * @return A Map with the values from the first row or + * null if there are no rows in the ResultSet. + * + * @throws SQLException if a database access error occurs + * + */ + @Override + public Map handle(ResultSet rs) throws SQLException { + return rs.next() ? this.convert.toMap(rs) : null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/MapListHandler.java b/modules/global/src/com/haulmont/bali/db/MapListHandler.java index 65a341ccd9..d5f45d851d 100644 --- a/modules/global/src/com/haulmont/bali/db/MapListHandler.java +++ b/modules/global/src/com/haulmont/bali/db/MapListHandler.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.util.List; -import java.util.Map; -import java.util.ArrayList; -import java.sql.ResultSet; -import java.sql.SQLException; - -public class MapListHandler implements ResultSetHandler>> { - /** - * The RowProcessor implementation to use when converting rows - * into Maps. - */ - private RowProcessor convert = ArrayHandler.ROW_PROCESSOR; - - public MapListHandler() { - } - - public MapListHandler(RowProcessor convert) { - this.convert = convert; - } - - @Override - public List> handle(ResultSet rs) throws SQLException { - List> result = new ArrayList<>(); - while (rs.next()) { - result.add(convert.toMap(rs)); - } - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class MapListHandler implements ResultSetHandler>> { + /** + * The RowProcessor implementation to use when converting rows + * into Maps. + */ + private RowProcessor convert = ArrayHandler.ROW_PROCESSOR; + + public MapListHandler() { + } + + public MapListHandler(RowProcessor convert) { + this.convert = convert; + } + + @Override + public List> handle(ResultSet rs) throws SQLException { + List> result = new ArrayList<>(); + while (rs.next()) { + result.add(convert.toMap(rs)); + } + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/QueryRunner.java b/modules/global/src/com/haulmont/bali/db/QueryRunner.java index 2e88b93c87..af494aa07f 100644 --- a/modules/global/src/com/haulmont/bali/db/QueryRunner.java +++ b/modules/global/src/com/haulmont/bali/db/QueryRunner.java @@ -1,695 +1,695 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Types; -import java.util.Arrays; - -import javax.sql.DataSource; - -/** - * Executes SQL queries with pluggable strategies for handling - * {@code ResultSet}s. This class is thread safe. - * - * @see ResultSetHandler - */ -public class QueryRunner { - - /** - * The DataSource to retrieve connections from. - */ - protected DataSource ds = null; - - /** - * Constructor for QueryRunner. - */ - public QueryRunner() { - super(); - } - - /** - * Constructor for QueryRunner. Methods that do not take a - * {@code Connection} parameter will retrieve connections from this - * {@code DataSource}. - * - * @param ds The {@code DataSource} to retrieve connections from. - */ - public QueryRunner(DataSource ds) { - setDataSource(ds); - } - - /** - * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. - * - * @param conn The Connection to use to run the query. The caller is - * responsible for closing this Connection. - * @param sql The SQL to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of batch replacement values. - * @return The number of rows updated per statement. - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - public int[] batch(Connection conn, String sql, Object[][] params) - throws SQLException { - - return batch(conn, sql, params, null); - } - - /** - * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. - * - * @param conn The Connection to use to run the query. The caller is - * responsible for closing this Connection. - * @param sql The SQL to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of batch replacement values. - * @param paramTypes Query replacement parameters types; {@code null} is a valid - * value to pass in. - * @return The number of rows updated per statement. - * @throws SQLException if a database access error occurs - */ - public int[] batch(Connection conn, String sql, Object[][] params, int[] paramTypes) - throws SQLException { - - PreparedStatement stmt = null; - int[] rows = null; - try { - stmt = this.prepareStatement(conn, sql); - - for (Object[] param : params) { - this.fillStatement(stmt, param, paramTypes); - stmt.addBatch(); - } - rows = stmt.executeBatch(); - - } catch (SQLException e) { - this.rethrow(e, sql, params); - } finally { - close(stmt); - } - - return rows; - } - - /** - * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. The - * {@code Connection} is retrieved from the {@code DataSource} - * set in the constructor. This {@code Connection} must be in - * auto-commit mode or the update will not be saved. - * - * @param sql The SQL to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of batch replacement values. - * @return The number of rows updated per statement. - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - public int[] batch(String sql, Object[][] params) throws SQLException { - return batch(sql, params, null); - } - - /** - * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. The - * {@code Connection} is retrieved from the {@code DataSource} - * set in the constructor. This {@code Connection} must be in - * auto-commit mode or the update will not be saved. - * - * @param sql The SQL to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of batch replacement values. - * @param paramTypes Query replacement parameters types; {@code null} is a valid - * value to pass in. - * @return The number of rows updated per statement. - * @throws SQLException if a database access error occurs - */ - public int[] batch(String sql, Object[][] params, int[] paramTypes) throws SQLException { - Connection conn = this.prepareConnection(); - - try { - return this.batch(conn, sql, params, paramTypes); - } finally { - close(conn); - } - } - - /** - * Fill the {@code PreparedStatement} replacement parameters with - * the given objects. - * @param stmt PreparedStatement to fill - * @param params Query replacement parameters; {@code null} is a valid - * value to pass in. - * @throws SQLException if a database access error occurs - */ - protected void fillStatement(PreparedStatement stmt, Object[] params) - throws SQLException { - - fillStatement(stmt, params, null); - } - - /** - * Fill the {@code PreparedStatement} replacement parameters with - * the given objects. - * @param stmt PreparedStatement to fill - * @param params Query replacement parameters; {@code null} is a valid - * value to pass in. - * @param paramTypes Query replacement parameters types; {@code null} is a valid - * value to pass in. - * @throws SQLException if a database access error occurs - */ - protected void fillStatement(PreparedStatement stmt, Object[] params, int[] paramTypes) - throws SQLException { - - if (params == null) { - return; - } - - if ((paramTypes != null) && (params.length != paramTypes.length)) { - throw new IllegalArgumentException("Sizes of params and paramTypes must be equal!"); - } - - for (int i = 0; i < params.length; i++) { - if (params[i] != null) { - if (paramTypes == null) - stmt.setObject(i + 1, params[i]); - else - stmt.setObject(i + 1, params[i], paramTypes[i]); - } else { - // VARCHAR works with many drivers regardless - // of the actual column type. Oddly, NULL and - // OTHER don't work with Oracle's drivers. - if (paramTypes == null) - stmt.setNull(i + 1, Types.VARCHAR); - else - stmt.setNull(i + 1, paramTypes[i]); - } - } - } - - /** - * Returns the {@code DataSource} this runner is using. - * {@code QueryRunner} methods always call this method to get the - * {@code DataSource} so subclasses can provide specialized - * behavior. - * - * @return DataSource the runner is using - */ - public DataSource getDataSource() { - return this.ds; - } - - /** - * Factory method that creates and initializes a - * {@code PreparedStatement} object for the given SQL. - * {@code QueryRunner} methods always call this method to prepare - * statements for them. Subclasses can override this method to provide - * special PreparedStatement configuration if needed. This implementation - * simply calls {@code conn.prepareStatement(sql)}. - * - * @param conn The {@code Connection} used to create the - * {@code PreparedStatement} - * @param sql The SQL statement to prepare. - * @return An initialized {@code PreparedStatement}. - * @throws SQLException if a database access error occurs - */ - protected PreparedStatement prepareStatement(Connection conn, String sql) - throws SQLException { - - return conn.prepareStatement(sql); - } - - /** - * Factory method that creates and initializes a - * {@code Connection} object. {@code QueryRunner} methods - * always call this method to retrieve connections from its DataSource. - * Subclasses can override this method to provide - * special {@code Connection} configuration if needed. This - * implementation simply calls {@code ds.getConnection()}. - * - * @return An initialized {@code Connection}. - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - protected Connection prepareConnection() throws SQLException { - if (this.getDataSource() == null) { - throw new SQLException("QueryRunner requires a DataSource to be " + - "invoked in this way, or a Connection should be passed in"); - } - return this.getDataSource().getConnection(); - } - - /** - * Execute an SQL SELECT query with a single replacement parameter. The - * caller is responsible for closing the connection. - * - * @param conn The connection to execute the query in. - * @param sql The query to execute. - * @param param The replacement parameter. - * @param rsh The handler that converts the results into an object. - * @return The object returned by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(Connection conn, String sql, Object param, - ResultSetHandler rsh) throws SQLException { - - return this.query(conn, sql, new Object[]{param}, rsh); - } - - /** - * Execute an SQL SELECT query with replacement parameters. The - * caller is responsible for closing the connection. - * - * @param conn The connection to execute the query in. - * @param sql The query to execute. - * @param params The replacement parameters. - * @param rsh The handler that converts the results into an object. - * @return The object returned by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(Connection conn, String sql, Object[] params, - ResultSetHandler rsh) throws SQLException { - - return query(conn, sql, params, null, rsh); - } - - /** - * Execute an SQL SELECT query with replacement parameters. The - * caller is responsible for closing the connection. - * - * @param conn The connection to execute the query in. - * @param sql The query to execute. - * @param params The replacement parameters. - * @param paramTypes The query replacement parameter types. - * @param rsh The handler that converts the results into an object. - * @return The object returned by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(Connection conn, String sql, Object[] params, int[] paramTypes, - ResultSetHandler rsh) throws SQLException { - - PreparedStatement stmt = null; - ResultSet rs = null; - T result = null; - - try { - stmt = this.prepareStatement(conn, sql); - this.fillStatement(stmt, params, paramTypes); - rs = this.wrap(stmt.executeQuery()); - result = rsh.handle(rs); - - } catch (SQLException e) { - this.rethrow(e, sql, params); - - } finally { - try { - close(rs); - } finally { - close(stmt); - } - } - - return result; - } - - /** - * Execute an SQL SELECT query without any replacement parameters. The - * caller is responsible for closing the connection. - * - * @param conn The connection to execute the query in. - * @param sql The query to execute. - * @param rsh The handler that converts the results into an object. - * @return The object returned by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(Connection conn, String sql, ResultSetHandler rsh) - throws SQLException { - - return this.query(conn, sql, (Object[]) null, rsh); - } - - /** - * Executes the given SELECT SQL with a single replacement parameter. - * The {@code Connection} is retrieved from the - * {@code DataSource} set in the constructor. - * - * @param sql The SQL statement to execute. - * @param param The replacement parameter. - * @param rsh The handler used to create the result object from - * the {@code ResultSet}. - * - * @return An object generated by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(String sql, Object param, ResultSetHandler rsh) - throws SQLException { - - return this.query(sql, new Object[] { param }, rsh); - } - - /** - * Executes the given SELECT SQL query and returns a result object. - * The {@code Connection} is retrieved from the - * {@code DataSource} set in the constructor. - * - * @param sql The SQL statement to execute. - * @param params Initialize the PreparedStatement's IN parameters with - * this array. - * - * @param rsh The handler used to create the result object from - * the {@code ResultSet}. - * - * @return An object generated by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(String sql, Object[] params, ResultSetHandler rsh) - throws SQLException { - - return this.query(sql, params, null, rsh); - } - - /** - * Executes the given SELECT SQL query and returns a result object. - * The {@code Connection} is retrieved from the - * {@code DataSource} set in the constructor. - * - * @param sql The SQL statement to execute. - * @param params Initialize the PreparedStatement's IN parameters with - * this array. - * @param paramTypes The query replacement parameter types. - * - * @param rsh The handler used to create the result object from - * the {@code ResultSet}. - * - * @return An object generated by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(String sql, Object[] params, int[] paramTypes, ResultSetHandler rsh) - throws SQLException { - - Connection conn = this.prepareConnection(); - - try { - return this.query(conn, sql, params, paramTypes, rsh); - } finally { - close(conn); - } - } - - /** - * Executes the given SELECT SQL without any replacement parameters. - * The {@code Connection} is retrieved from the - * {@code DataSource} set in the constructor. - * - * @param sql The SQL statement to execute. - * @param rsh The handler used to create the result object from - * the {@code ResultSet}. - * - * @return An object generated by the handler. - * @throws SQLException if a database access error occurs - */ - public T query(String sql, ResultSetHandler rsh) throws SQLException { - return this.query(sql, (Object[]) null, rsh); - } - - /** - * Throws a new exception with a more informative error message. - * - * @param cause The original exception that will be chained to the new - * exception when it's rethrown. - * - * @param sql The query that was executing when the exception happened. - * - * @param params The query replacement parameters; {@code null} is a - * valid value to pass in. - * - * @throws SQLException if a database access error occurs - */ - protected void rethrow(SQLException cause, String sql, Object[] params) - throws SQLException { - - StringBuilder msg = new StringBuilder(cause.getMessage()); - - msg.append(" Query: "); - msg.append(sql); - msg.append(" Parameters: "); - - if (params == null) { - msg.append("[]"); - } else { - msg.append(Arrays.asList(params)); - } - - SQLException e = new SQLException(msg.toString(), cause.getSQLState(), - cause.getErrorCode()); - e.setNextException(cause); - - throw e; - } - - /** - * Sets the {@code DataSource} this runner will use to get - * database connections from. This should be called after creating a - * runner with the default constructor if you intend to use the - * execute methods without passing in a {@code Connection}. - * - * @param dataSource The DataSource to use. - */ - public void setDataSource(DataSource dataSource) { - this.ds = dataSource; - } - - /** - * Execute an SQL INSERT, UPDATE, or DELETE query without replacement - * parameters. - * - * @param conn The connection to use to run the query. - * @param sql The SQL to execute. - * @return The number of rows updated. - * @throws SQLException if a database access error occurs - */ - public int update(Connection conn, String sql) throws SQLException { - return this.update(conn, sql, (Object[]) null); - } - - /** - * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement - * parameter. - * - * @param conn The connection to use to run the query. - * @param sql The SQL to execute. - * @param param The replacement parameter. - * @return The number of rows updated. - * @throws SQLException if a database access error occurs - */ - public int update(Connection conn, String sql, Object param) - throws SQLException { - - return this.update(conn, sql, new Object[] { param }); - } - - /** - * Execute an SQL INSERT, UPDATE, or DELETE query. - * - * @param conn The connection to use to run the query. - * @param sql The SQL to execute. - * @param params The query replacement parameters. - * @return The number of rows updated. - * @throws SQLException if a database access error occurs - */ - public int update(Connection conn, String sql, Object[] params) - throws SQLException { - - return update(conn, sql, params, null); - } - - /** - * Execute an SQL INSERT, UPDATE, or DELETE query. - * - * @param conn The connection to use to run the query. - * @param sql The SQL to execute. - * @param params The query replacement parameters. - * @param paramTypes The query replacement parameter types. - * @return The number of rows updated. - * @throws SQLException if a database access error occurs - */ - public int update(Connection conn, String sql, Object[] params, int[] paramTypes) - throws SQLException { - - if ((paramTypes != null) && params.length != paramTypes.length) { - throw new IllegalArgumentException("Sizes of params and paramTypes must be equal!"); - } - - PreparedStatement stmt = null; - int rows = 0; - - try { - stmt = this.prepareStatement(conn, sql); - this.fillStatement(stmt, params, paramTypes); - rows = stmt.executeUpdate(); - - } catch (SQLException e) { - this.rethrow(e, sql, params); - - } finally { - close(stmt); - } - - return rows; - } - - /** - * Executes the given INSERT, UPDATE, or DELETE SQL statement without - * any replacement parameters. The {@code Connection} is retrieved - * from the {@code DataSource} set in the constructor. This - * {@code Connection} must be in auto-commit mode or the update will - * not be saved. - * - * @param sql The SQL statement to execute. - * @throws SQLException if a database access error occurs - * @return The number of rows updated. - */ - public int update(String sql) throws SQLException { - return this.update(sql, (Object[]) null); - } - - /** - * Executes the given INSERT, UPDATE, or DELETE SQL statement with - * a single replacement parameter. The {@code Connection} is - * retrieved from the {@code DataSource} set in the constructor. - * This {@code Connection} must be in auto-commit mode or the - * update will not be saved. - * - * @param sql The SQL statement to execute. - * @param param The replacement parameter. - * @throws SQLException if a database access error occurs - * @return The number of rows updated. - */ - public int update(String sql, Object param) throws SQLException { - return this.update(sql, new Object[] { param }); - } - - /** - * Executes the given INSERT, UPDATE, or DELETE SQL statement. The - * {@code Connection} is retrieved from the {@code DataSource} - * set in the constructor. This {@code Connection} must be in - * auto-commit mode or the update will not be saved. - * - * @param sql The SQL statement to execute. - * @param params Initializes the PreparedStatement's IN (i.e. '?') - * parameters. - * @throws SQLException if a database access error occurs - * @return The number of rows updated. - */ - public int update(String sql, Object[] params) throws SQLException { - Connection conn = this.prepareConnection(); - - try { - return this.update(conn, sql, params); - } finally { - close(conn); - } - } - - /** - * Executes the given INSERT, UPDATE, or DELETE SQL statement. The - * {@code Connection} is retrieved from the {@code DataSource} - * set in the constructor. This {@code Connection} must be in - * auto-commit mode or the update will not be saved. - * - * @param sql The SQL statement to execute. - * @param params Initializes the PreparedStatement's IN (i.e. '?') - * parameters. - * @param paramTypes The query replacement parameter types. - * @throws SQLException if a database access error occurs - * @return The number of rows updated. - */ - public int update(String sql, Object[] params, int[] paramTypes) throws SQLException { - Connection conn = this.prepareConnection(); - - try { - return this.update(conn, sql, params, paramTypes); - } finally { - close(conn); - } - } - - /** - * Wrap the {@code ResultSet} in a decorator before processing it. - * This implementation returns the {@code ResultSet} it is given - * without any decoration. - * - *

- * Often, the implementation of this method can be done in an anonymous - * inner class like this: - *

- *
-     * QueryRunner run = new QueryRunner() {
-     *     protected ResultSet wrap(ResultSet rs) {
-     *         return StringTrimmedResultSet.wrap(rs);
-     *     }
-     * };
-     * 
- * - * @param rs The {@code ResultSet} to decorate; never - * {@code null}. - * @return The {@code ResultSet} wrapped in some decorator. - */ - protected ResultSet wrap(ResultSet rs) { - return rs; - } - - /** - * Close a {@code Connection}. This implementation avoids closing if - * null and does not suppress any exceptions. Subclasses - * can override to provide special handling like logging. - * @param conn Connection to close - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - protected void close(Connection conn) throws SQLException { - DbUtils.close(conn); - } - - /** - * Close a {@code Statement}. This implementation avoids closing if - * null and does not suppress any exceptions. Subclasses - * can override to provide special handling like logging. - * @param stmt Statement to close - * @throws SQLException if a database access error occurs - * @since DbUtils 1.1 - */ - protected void close(Statement stmt) throws SQLException { - DbUtils.close(stmt); - } - - /** - * Close a {@code ResultSet}. This implementation avoids closing if - * null and does not suppress any exceptions. Subclasses - * can override to provide special handling like logging. - * @throws SQLException if a database access error occurs - * @param rs ResultSet to close - * @since DbUtils 1.1 - */ - protected void close(ResultSet rs) throws SQLException { - DbUtils.close(rs); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.Arrays; + +import javax.sql.DataSource; + +/** + * Executes SQL queries with pluggable strategies for handling + * {@code ResultSet}s. This class is thread safe. + * + * @see ResultSetHandler + */ +public class QueryRunner { + + /** + * The DataSource to retrieve connections from. + */ + protected DataSource ds = null; + + /** + * Constructor for QueryRunner. + */ + public QueryRunner() { + super(); + } + + /** + * Constructor for QueryRunner. Methods that do not take a + * {@code Connection} parameter will retrieve connections from this + * {@code DataSource}. + * + * @param ds The {@code DataSource} to retrieve connections from. + */ + public QueryRunner(DataSource ds) { + setDataSource(ds); + } + + /** + * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. + * + * @param conn The Connection to use to run the query. The caller is + * responsible for closing this Connection. + * @param sql The SQL to execute. + * @param params An array of query replacement parameters. Each row in + * this array is one set of batch replacement values. + * @return The number of rows updated per statement. + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + public int[] batch(Connection conn, String sql, Object[][] params) + throws SQLException { + + return batch(conn, sql, params, null); + } + + /** + * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. + * + * @param conn The Connection to use to run the query. The caller is + * responsible for closing this Connection. + * @param sql The SQL to execute. + * @param params An array of query replacement parameters. Each row in + * this array is one set of batch replacement values. + * @param paramTypes Query replacement parameters types; {@code null} is a valid + * value to pass in. + * @return The number of rows updated per statement. + * @throws SQLException if a database access error occurs + */ + public int[] batch(Connection conn, String sql, Object[][] params, int[] paramTypes) + throws SQLException { + + PreparedStatement stmt = null; + int[] rows = null; + try { + stmt = this.prepareStatement(conn, sql); + + for (Object[] param : params) { + this.fillStatement(stmt, param, paramTypes); + stmt.addBatch(); + } + rows = stmt.executeBatch(); + + } catch (SQLException e) { + this.rethrow(e, sql, params); + } finally { + close(stmt); + } + + return rows; + } + + /** + * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. The + * {@code Connection} is retrieved from the {@code DataSource} + * set in the constructor. This {@code Connection} must be in + * auto-commit mode or the update will not be saved. + * + * @param sql The SQL to execute. + * @param params An array of query replacement parameters. Each row in + * this array is one set of batch replacement values. + * @return The number of rows updated per statement. + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + public int[] batch(String sql, Object[][] params) throws SQLException { + return batch(sql, params, null); + } + + /** + * Execute a batch of SQL INSERT, UPDATE, or DELETE queries. The + * {@code Connection} is retrieved from the {@code DataSource} + * set in the constructor. This {@code Connection} must be in + * auto-commit mode or the update will not be saved. + * + * @param sql The SQL to execute. + * @param params An array of query replacement parameters. Each row in + * this array is one set of batch replacement values. + * @param paramTypes Query replacement parameters types; {@code null} is a valid + * value to pass in. + * @return The number of rows updated per statement. + * @throws SQLException if a database access error occurs + */ + public int[] batch(String sql, Object[][] params, int[] paramTypes) throws SQLException { + Connection conn = this.prepareConnection(); + + try { + return this.batch(conn, sql, params, paramTypes); + } finally { + close(conn); + } + } + + /** + * Fill the {@code PreparedStatement} replacement parameters with + * the given objects. + * @param stmt PreparedStatement to fill + * @param params Query replacement parameters; {@code null} is a valid + * value to pass in. + * @throws SQLException if a database access error occurs + */ + protected void fillStatement(PreparedStatement stmt, Object[] params) + throws SQLException { + + fillStatement(stmt, params, null); + } + + /** + * Fill the {@code PreparedStatement} replacement parameters with + * the given objects. + * @param stmt PreparedStatement to fill + * @param params Query replacement parameters; {@code null} is a valid + * value to pass in. + * @param paramTypes Query replacement parameters types; {@code null} is a valid + * value to pass in. + * @throws SQLException if a database access error occurs + */ + protected void fillStatement(PreparedStatement stmt, Object[] params, int[] paramTypes) + throws SQLException { + + if (params == null) { + return; + } + + if ((paramTypes != null) && (params.length != paramTypes.length)) { + throw new IllegalArgumentException("Sizes of params and paramTypes must be equal!"); + } + + for (int i = 0; i < params.length; i++) { + if (params[i] != null) { + if (paramTypes == null) + stmt.setObject(i + 1, params[i]); + else + stmt.setObject(i + 1, params[i], paramTypes[i]); + } else { + // VARCHAR works with many drivers regardless + // of the actual column type. Oddly, NULL and + // OTHER don't work with Oracle's drivers. + if (paramTypes == null) + stmt.setNull(i + 1, Types.VARCHAR); + else + stmt.setNull(i + 1, paramTypes[i]); + } + } + } + + /** + * Returns the {@code DataSource} this runner is using. + * {@code QueryRunner} methods always call this method to get the + * {@code DataSource} so subclasses can provide specialized + * behavior. + * + * @return DataSource the runner is using + */ + public DataSource getDataSource() { + return this.ds; + } + + /** + * Factory method that creates and initializes a + * {@code PreparedStatement} object for the given SQL. + * {@code QueryRunner} methods always call this method to prepare + * statements for them. Subclasses can override this method to provide + * special PreparedStatement configuration if needed. This implementation + * simply calls {@code conn.prepareStatement(sql)}. + * + * @param conn The {@code Connection} used to create the + * {@code PreparedStatement} + * @param sql The SQL statement to prepare. + * @return An initialized {@code PreparedStatement}. + * @throws SQLException if a database access error occurs + */ + protected PreparedStatement prepareStatement(Connection conn, String sql) + throws SQLException { + + return conn.prepareStatement(sql); + } + + /** + * Factory method that creates and initializes a + * {@code Connection} object. {@code QueryRunner} methods + * always call this method to retrieve connections from its DataSource. + * Subclasses can override this method to provide + * special {@code Connection} configuration if needed. This + * implementation simply calls {@code ds.getConnection()}. + * + * @return An initialized {@code Connection}. + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + protected Connection prepareConnection() throws SQLException { + if (this.getDataSource() == null) { + throw new SQLException("QueryRunner requires a DataSource to be " + + "invoked in this way, or a Connection should be passed in"); + } + return this.getDataSource().getConnection(); + } + + /** + * Execute an SQL SELECT query with a single replacement parameter. The + * caller is responsible for closing the connection. + * + * @param conn The connection to execute the query in. + * @param sql The query to execute. + * @param param The replacement parameter. + * @param rsh The handler that converts the results into an object. + * @return The object returned by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(Connection conn, String sql, Object param, + ResultSetHandler rsh) throws SQLException { + + return this.query(conn, sql, new Object[]{param}, rsh); + } + + /** + * Execute an SQL SELECT query with replacement parameters. The + * caller is responsible for closing the connection. + * + * @param conn The connection to execute the query in. + * @param sql The query to execute. + * @param params The replacement parameters. + * @param rsh The handler that converts the results into an object. + * @return The object returned by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(Connection conn, String sql, Object[] params, + ResultSetHandler rsh) throws SQLException { + + return query(conn, sql, params, null, rsh); + } + + /** + * Execute an SQL SELECT query with replacement parameters. The + * caller is responsible for closing the connection. + * + * @param conn The connection to execute the query in. + * @param sql The query to execute. + * @param params The replacement parameters. + * @param paramTypes The query replacement parameter types. + * @param rsh The handler that converts the results into an object. + * @return The object returned by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(Connection conn, String sql, Object[] params, int[] paramTypes, + ResultSetHandler rsh) throws SQLException { + + PreparedStatement stmt = null; + ResultSet rs = null; + T result = null; + + try { + stmt = this.prepareStatement(conn, sql); + this.fillStatement(stmt, params, paramTypes); + rs = this.wrap(stmt.executeQuery()); + result = rsh.handle(rs); + + } catch (SQLException e) { + this.rethrow(e, sql, params); + + } finally { + try { + close(rs); + } finally { + close(stmt); + } + } + + return result; + } + + /** + * Execute an SQL SELECT query without any replacement parameters. The + * caller is responsible for closing the connection. + * + * @param conn The connection to execute the query in. + * @param sql The query to execute. + * @param rsh The handler that converts the results into an object. + * @return The object returned by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(Connection conn, String sql, ResultSetHandler rsh) + throws SQLException { + + return this.query(conn, sql, (Object[]) null, rsh); + } + + /** + * Executes the given SELECT SQL with a single replacement parameter. + * The {@code Connection} is retrieved from the + * {@code DataSource} set in the constructor. + * + * @param sql The SQL statement to execute. + * @param param The replacement parameter. + * @param rsh The handler used to create the result object from + * the {@code ResultSet}. + * + * @return An object generated by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(String sql, Object param, ResultSetHandler rsh) + throws SQLException { + + return this.query(sql, new Object[] { param }, rsh); + } + + /** + * Executes the given SELECT SQL query and returns a result object. + * The {@code Connection} is retrieved from the + * {@code DataSource} set in the constructor. + * + * @param sql The SQL statement to execute. + * @param params Initialize the PreparedStatement's IN parameters with + * this array. + * + * @param rsh The handler used to create the result object from + * the {@code ResultSet}. + * + * @return An object generated by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(String sql, Object[] params, ResultSetHandler rsh) + throws SQLException { + + return this.query(sql, params, null, rsh); + } + + /** + * Executes the given SELECT SQL query and returns a result object. + * The {@code Connection} is retrieved from the + * {@code DataSource} set in the constructor. + * + * @param sql The SQL statement to execute. + * @param params Initialize the PreparedStatement's IN parameters with + * this array. + * @param paramTypes The query replacement parameter types. + * + * @param rsh The handler used to create the result object from + * the {@code ResultSet}. + * + * @return An object generated by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(String sql, Object[] params, int[] paramTypes, ResultSetHandler rsh) + throws SQLException { + + Connection conn = this.prepareConnection(); + + try { + return this.query(conn, sql, params, paramTypes, rsh); + } finally { + close(conn); + } + } + + /** + * Executes the given SELECT SQL without any replacement parameters. + * The {@code Connection} is retrieved from the + * {@code DataSource} set in the constructor. + * + * @param sql The SQL statement to execute. + * @param rsh The handler used to create the result object from + * the {@code ResultSet}. + * + * @return An object generated by the handler. + * @throws SQLException if a database access error occurs + */ + public T query(String sql, ResultSetHandler rsh) throws SQLException { + return this.query(sql, (Object[]) null, rsh); + } + + /** + * Throws a new exception with a more informative error message. + * + * @param cause The original exception that will be chained to the new + * exception when it's rethrown. + * + * @param sql The query that was executing when the exception happened. + * + * @param params The query replacement parameters; {@code null} is a + * valid value to pass in. + * + * @throws SQLException if a database access error occurs + */ + protected void rethrow(SQLException cause, String sql, Object[] params) + throws SQLException { + + StringBuilder msg = new StringBuilder(cause.getMessage()); + + msg.append(" Query: "); + msg.append(sql); + msg.append(" Parameters: "); + + if (params == null) { + msg.append("[]"); + } else { + msg.append(Arrays.asList(params)); + } + + SQLException e = new SQLException(msg.toString(), cause.getSQLState(), + cause.getErrorCode()); + e.setNextException(cause); + + throw e; + } + + /** + * Sets the {@code DataSource} this runner will use to get + * database connections from. This should be called after creating a + * runner with the default constructor if you intend to use the + * execute methods without passing in a {@code Connection}. + * + * @param dataSource The DataSource to use. + */ + public void setDataSource(DataSource dataSource) { + this.ds = dataSource; + } + + /** + * Execute an SQL INSERT, UPDATE, or DELETE query without replacement + * parameters. + * + * @param conn The connection to use to run the query. + * @param sql The SQL to execute. + * @return The number of rows updated. + * @throws SQLException if a database access error occurs + */ + public int update(Connection conn, String sql) throws SQLException { + return this.update(conn, sql, (Object[]) null); + } + + /** + * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement + * parameter. + * + * @param conn The connection to use to run the query. + * @param sql The SQL to execute. + * @param param The replacement parameter. + * @return The number of rows updated. + * @throws SQLException if a database access error occurs + */ + public int update(Connection conn, String sql, Object param) + throws SQLException { + + return this.update(conn, sql, new Object[] { param }); + } + + /** + * Execute an SQL INSERT, UPDATE, or DELETE query. + * + * @param conn The connection to use to run the query. + * @param sql The SQL to execute. + * @param params The query replacement parameters. + * @return The number of rows updated. + * @throws SQLException if a database access error occurs + */ + public int update(Connection conn, String sql, Object[] params) + throws SQLException { + + return update(conn, sql, params, null); + } + + /** + * Execute an SQL INSERT, UPDATE, or DELETE query. + * + * @param conn The connection to use to run the query. + * @param sql The SQL to execute. + * @param params The query replacement parameters. + * @param paramTypes The query replacement parameter types. + * @return The number of rows updated. + * @throws SQLException if a database access error occurs + */ + public int update(Connection conn, String sql, Object[] params, int[] paramTypes) + throws SQLException { + + if ((paramTypes != null) && params.length != paramTypes.length) { + throw new IllegalArgumentException("Sizes of params and paramTypes must be equal!"); + } + + PreparedStatement stmt = null; + int rows = 0; + + try { + stmt = this.prepareStatement(conn, sql); + this.fillStatement(stmt, params, paramTypes); + rows = stmt.executeUpdate(); + + } catch (SQLException e) { + this.rethrow(e, sql, params); + + } finally { + close(stmt); + } + + return rows; + } + + /** + * Executes the given INSERT, UPDATE, or DELETE SQL statement without + * any replacement parameters. The {@code Connection} is retrieved + * from the {@code DataSource} set in the constructor. This + * {@code Connection} must be in auto-commit mode or the update will + * not be saved. + * + * @param sql The SQL statement to execute. + * @throws SQLException if a database access error occurs + * @return The number of rows updated. + */ + public int update(String sql) throws SQLException { + return this.update(sql, (Object[]) null); + } + + /** + * Executes the given INSERT, UPDATE, or DELETE SQL statement with + * a single replacement parameter. The {@code Connection} is + * retrieved from the {@code DataSource} set in the constructor. + * This {@code Connection} must be in auto-commit mode or the + * update will not be saved. + * + * @param sql The SQL statement to execute. + * @param param The replacement parameter. + * @throws SQLException if a database access error occurs + * @return The number of rows updated. + */ + public int update(String sql, Object param) throws SQLException { + return this.update(sql, new Object[] { param }); + } + + /** + * Executes the given INSERT, UPDATE, or DELETE SQL statement. The + * {@code Connection} is retrieved from the {@code DataSource} + * set in the constructor. This {@code Connection} must be in + * auto-commit mode or the update will not be saved. + * + * @param sql The SQL statement to execute. + * @param params Initializes the PreparedStatement's IN (i.e. '?') + * parameters. + * @throws SQLException if a database access error occurs + * @return The number of rows updated. + */ + public int update(String sql, Object[] params) throws SQLException { + Connection conn = this.prepareConnection(); + + try { + return this.update(conn, sql, params); + } finally { + close(conn); + } + } + + /** + * Executes the given INSERT, UPDATE, or DELETE SQL statement. The + * {@code Connection} is retrieved from the {@code DataSource} + * set in the constructor. This {@code Connection} must be in + * auto-commit mode or the update will not be saved. + * + * @param sql The SQL statement to execute. + * @param params Initializes the PreparedStatement's IN (i.e. '?') + * parameters. + * @param paramTypes The query replacement parameter types. + * @throws SQLException if a database access error occurs + * @return The number of rows updated. + */ + public int update(String sql, Object[] params, int[] paramTypes) throws SQLException { + Connection conn = this.prepareConnection(); + + try { + return this.update(conn, sql, params, paramTypes); + } finally { + close(conn); + } + } + + /** + * Wrap the {@code ResultSet} in a decorator before processing it. + * This implementation returns the {@code ResultSet} it is given + * without any decoration. + * + *

+ * Often, the implementation of this method can be done in an anonymous + * inner class like this: + *

+ *
+     * QueryRunner run = new QueryRunner() {
+     *     protected ResultSet wrap(ResultSet rs) {
+     *         return StringTrimmedResultSet.wrap(rs);
+     *     }
+     * };
+     * 
+ * + * @param rs The {@code ResultSet} to decorate; never + * {@code null}. + * @return The {@code ResultSet} wrapped in some decorator. + */ + protected ResultSet wrap(ResultSet rs) { + return rs; + } + + /** + * Close a {@code Connection}. This implementation avoids closing if + * null and does not suppress any exceptions. Subclasses + * can override to provide special handling like logging. + * @param conn Connection to close + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + protected void close(Connection conn) throws SQLException { + DbUtils.close(conn); + } + + /** + * Close a {@code Statement}. This implementation avoids closing if + * null and does not suppress any exceptions. Subclasses + * can override to provide special handling like logging. + * @param stmt Statement to close + * @throws SQLException if a database access error occurs + * @since DbUtils 1.1 + */ + protected void close(Statement stmt) throws SQLException { + DbUtils.close(stmt); + } + + /** + * Close a {@code ResultSet}. This implementation avoids closing if + * null and does not suppress any exceptions. Subclasses + * can override to provide special handling like logging. + * @throws SQLException if a database access error occurs + * @param rs ResultSet to close + * @since DbUtils 1.1 + */ + protected void close(ResultSet rs) throws SQLException { + DbUtils.close(rs); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/ResultSetHandler.java b/modules/global/src/com/haulmont/bali/db/ResultSetHandler.java index bfbe759cde..b887364604 100644 --- a/modules/global/src/com/haulmont/bali/db/ResultSetHandler.java +++ b/modules/global/src/com/haulmont/bali/db/ResultSetHandler.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * Implementations of this interface convert ResultSets into other objects. - * - */ -public interface ResultSetHandler { - - /** - * Turn the ResultSet into an Object. - * - * @param rs The ResultSet to handle. It has not been touched - * before being passed to this method. - * - * @return An Object initialized with ResultSet data. It is - * legal for implementations to return null if the - * ResultSet contained 0 rows. - * - * @throws SQLException if a database access error occurs - */ - T handle(ResultSet rs) throws SQLException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Implementations of this interface convert ResultSets into other objects. + * + */ +public interface ResultSetHandler { + + /** + * Turn the ResultSet into an Object. + * + * @param rs The ResultSet to handle. It has not been touched + * before being passed to this method. + * + * @return An Object initialized with ResultSet data. It is + * legal for implementations to return null if the + * ResultSet contained 0 rows. + * + * @throws SQLException if a database access error occurs + */ + T handle(ResultSet rs) throws SQLException; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/db/RowProcessor.java b/modules/global/src/com/haulmont/bali/db/RowProcessor.java index 8e3f576973..62063bced5 100644 --- a/modules/global/src/com/haulmont/bali/db/RowProcessor.java +++ b/modules/global/src/com/haulmont/bali/db/RowProcessor.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.db; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; - -/** - * RowProcessor implementations convert - * ResultSet rows into various other objects. Implementations - * can extend BasicRowProcessor to protect themselves - * from changes to this interface. - * - * @see BasicRowProcessor - * - */ -public interface RowProcessor { - - /** - * Create an Object[] from the column values in one - * ResultSet row. The ResultSet should be - * positioned on a valid row before passing it to this method. - * Implementations of this method must not alter the row position of - * the ResultSet. - * - * @param rs ResultSet that supplies the array data - * @throws SQLException if a database access error occurs - * @return the newly created array - */ - Object[] toArray(ResultSet rs) throws SQLException; - - /** - * Create a JavaBean from the column values in one ResultSet - * row. The ResultSet should be positioned on a valid row before - * passing it to this method. Implementations of this method must not - * alter the row position of the ResultSet. - * - * @param rs ResultSet that supplies the bean data - * @param type Class from which to create the bean instance - * @throws SQLException if a database access error occurs - * @return the newly created bean - */ - Object toBean(ResultSet rs, Class type) throws SQLException; - - /** - * Create a List of JavaBeans from the column values in all - * ResultSet rows. ResultSet.next() should - * not be called before passing it to this method. - * - * @param rs ResultSet that supplies the bean data - * @param type Class from which to create the bean instance - * @throws SQLException if a database access error occurs - * @return A List of beans with the given type in the order - * they were returned by the ResultSet. - */ - List toBeanList(ResultSet rs, Class type) throws SQLException; - - /** - * Create a Map from the column values in one - * ResultSet row. The ResultSet should be - * positioned on a valid row before - * passing it to this method. Implementations of this method must not - * alter the row position of the ResultSet. - * - * @param rs ResultSet that supplies the map data - * @throws SQLException if a database access error occurs - * @return the newly created Map - */ - Map toMap(ResultSet rs) throws SQLException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.db; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * RowProcessor implementations convert + * ResultSet rows into various other objects. Implementations + * can extend BasicRowProcessor to protect themselves + * from changes to this interface. + * + * @see BasicRowProcessor + * + */ +public interface RowProcessor { + + /** + * Create an Object[] from the column values in one + * ResultSet row. The ResultSet should be + * positioned on a valid row before passing it to this method. + * Implementations of this method must not alter the row position of + * the ResultSet. + * + * @param rs ResultSet that supplies the array data + * @throws SQLException if a database access error occurs + * @return the newly created array + */ + Object[] toArray(ResultSet rs) throws SQLException; + + /** + * Create a JavaBean from the column values in one ResultSet + * row. The ResultSet should be positioned on a valid row before + * passing it to this method. Implementations of this method must not + * alter the row position of the ResultSet. + * + * @param rs ResultSet that supplies the bean data + * @param type Class from which to create the bean instance + * @throws SQLException if a database access error occurs + * @return the newly created bean + */ + Object toBean(ResultSet rs, Class type) throws SQLException; + + /** + * Create a List of JavaBeans from the column values in all + * ResultSet rows. ResultSet.next() should + * not be called before passing it to this method. + * + * @param rs ResultSet that supplies the bean data + * @param type Class from which to create the bean instance + * @throws SQLException if a database access error occurs + * @return A List of beans with the given type in the order + * they were returned by the ResultSet. + */ + List toBeanList(ResultSet rs, Class type) throws SQLException; + + /** + * Create a Map from the column values in one + * ResultSet row. The ResultSet should be + * positioned on a valid row before + * passing it to this method. Implementations of this method must not + * alter the row position of the ResultSet. + * + * @param rs ResultSet that supplies the map data + * @throws SQLException if a database access error occurs + * @return the newly created Map + */ + Map toMap(ResultSet rs) throws SQLException; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/util/Dom4j.java b/modules/global/src/com/haulmont/bali/util/Dom4j.java index d41863eb09..b611642c47 100644 --- a/modules/global/src/com/haulmont/bali/util/Dom4j.java +++ b/modules/global/src/com/haulmont/bali/util/Dom4j.java @@ -1,215 +1,215 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.util; - -import org.apache.commons.compress.utils.IOUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import java.io.*; -import java.util.List; -import java.util.Map; - -/** - * Helper class for XML parsing. - * Caches SAXParser instance if application property cuba.saxParserThreadLocalCache is not set or set to true. - */ -public final class Dom4j { - - private static final ThreadLocal saxParserHolder = new ThreadLocal<>(); - - private Dom4j() { - } - - public static Document readDocument(String xmlString) { - return readDocument(new StringReader(xmlString)); - } - - public static Document readDocument(Reader reader) { - SAXReader xmlReader = getSaxReader(); - try { - return xmlReader.read(reader); - } catch (DocumentException e) { - throw new RuntimeException("Unable to read XML from reader", e); - } - } - - private static SAXReader getSaxReader() { - String useThreadLocalCache = System.getProperty("cuba.saxParserThreadLocalCache"); - if (useThreadLocalCache == null || Boolean.parseBoolean(useThreadLocalCache)) { - try { - return new SAXReader(getParser().getXMLReader()); - } catch (SAXException e) { - throw new RuntimeException("Unable to create SAX reader", e); - } - } else { - return new SAXReader(); - } - } - - public static SAXParser getParser() { - SAXParser parser = saxParserHolder.get(); - if (parser == null) { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setValidating(false); - factory.setNamespaceAware(false); - try { - parser = factory.newSAXParser(); - } catch (ParserConfigurationException | SAXException e) { - throw new RuntimeException("Unable to create SAX parser", e); - } - saxParserHolder.set(parser); - } - return parser; - } - - public static Document readDocument(InputStream stream) { - SAXReader xmlReader = getSaxReader(); - try { - return xmlReader.read(stream); - } catch (DocumentException e) { - throw new RuntimeException("Unable to read XML from stream", e); - } - } - - public static Document readDocument(File file) { - FileInputStream inputStream = null; - try { - inputStream = new FileInputStream(file); - return Dom4j.readDocument(inputStream); - } catch (FileNotFoundException e) { - throw new RuntimeException("Unable to read XML from file", e); - } finally { - IOUtils.closeQuietly(inputStream); - } - } - - public static String writeDocument(Document doc, boolean prettyPrint) { - StringWriter writer = new StringWriter(); - writeDocument(doc, prettyPrint, writer); - return writer.toString(); - } - - public static void writeDocument(Document doc, boolean prettyPrint, Writer writer) { - XMLWriter xmlWriter; - try { - if (prettyPrint) { - OutputFormat format = OutputFormat.createPrettyPrint(); - xmlWriter = new XMLWriter(writer, format); - } else { - xmlWriter = new XMLWriter(writer); - } - xmlWriter.write(doc); - } catch (IOException e) { - throw new RuntimeException("Unable to write XML", e); - } - } - - public static void writeDocument(Document doc, boolean prettyPrint, OutputStream stream) { - XMLWriter xmlWriter; - try { - if (prettyPrint) { - OutputFormat format = OutputFormat.createPrettyPrint(); - xmlWriter = new XMLWriter(stream, format); - } else { - xmlWriter = new XMLWriter(stream); - } - xmlWriter.write(doc); - } catch (IOException e) { - throw new RuntimeException("Unable to write XML", e); - } - } - - @SuppressWarnings("unchecked") - public static List elements(Element element) { - return element.elements(); - } - - @SuppressWarnings("unchecked") - public static List elements(Element element, String name) { - return element.elements(name); - } - - @SuppressWarnings("unchecked") - public static List attributes(Element element) { - return element.attributes(); - } - - public static void storeMap(Element parentElement, Map map) { - if (map == null) { - return; - } - - Element mapElem = parentElement.addElement("map"); - for (Map.Entry entry : map.entrySet()) { - Element entryElem = mapElem.addElement("entry"); - entryElem.addAttribute("key", entry.getKey()); - Element valueElem = entryElem.addElement("value"); - if (entry.getValue() != null) { - String value = StringEscapeUtils.escapeXml(entry.getValue()); - valueElem.setText(value); - } - } - } - - public static void loadMap(Element mapElement, Map map) { - Preconditions.checkNotNullArgument(map, "map is null"); - - for (Element entryElem : elements(mapElement, "entry")) { - String key = entryElem.attributeValue("key"); - if (key == null) { - throw new IllegalStateException("No 'key' attribute"); - } - - String value = null; - Element valueElem = entryElem.element("value"); - if (valueElem != null) { - value = StringEscapeUtils.unescapeXml(valueElem.getText()); - } - - map.put(key, value); - } - } - - public static void walkAttributesRecursive(Element element, ElementAttributeVisitor visitor) { - walkAttributes(element, visitor); - - for (Element childElement : elements(element)) { - walkAttributesRecursive(childElement, visitor); - } - } - - public static void walkAttributes(Element element, ElementAttributeVisitor visitor) { - for (Attribute attribute : attributes(element)) { - visitor.onVisit(element, attribute); - } - } - - public interface ElementAttributeVisitor { - void onVisit(Element element, Attribute attribute); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.util; + +import org.apache.commons.compress.utils.IOUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.*; +import java.util.List; +import java.util.Map; + +/** + * Helper class for XML parsing. + * Caches SAXParser instance if application property cuba.saxParserThreadLocalCache is not set or set to true. + */ +public final class Dom4j { + + private static final ThreadLocal saxParserHolder = new ThreadLocal<>(); + + private Dom4j() { + } + + public static Document readDocument(String xmlString) { + return readDocument(new StringReader(xmlString)); + } + + public static Document readDocument(Reader reader) { + SAXReader xmlReader = getSaxReader(); + try { + return xmlReader.read(reader); + } catch (DocumentException e) { + throw new RuntimeException("Unable to read XML from reader", e); + } + } + + private static SAXReader getSaxReader() { + String useThreadLocalCache = System.getProperty("cuba.saxParserThreadLocalCache"); + if (useThreadLocalCache == null || Boolean.parseBoolean(useThreadLocalCache)) { + try { + return new SAXReader(getParser().getXMLReader()); + } catch (SAXException e) { + throw new RuntimeException("Unable to create SAX reader", e); + } + } else { + return new SAXReader(); + } + } + + public static SAXParser getParser() { + SAXParser parser = saxParserHolder.get(); + if (parser == null) { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(false); + try { + parser = factory.newSAXParser(); + } catch (ParserConfigurationException | SAXException e) { + throw new RuntimeException("Unable to create SAX parser", e); + } + saxParserHolder.set(parser); + } + return parser; + } + + public static Document readDocument(InputStream stream) { + SAXReader xmlReader = getSaxReader(); + try { + return xmlReader.read(stream); + } catch (DocumentException e) { + throw new RuntimeException("Unable to read XML from stream", e); + } + } + + public static Document readDocument(File file) { + FileInputStream inputStream = null; + try { + inputStream = new FileInputStream(file); + return Dom4j.readDocument(inputStream); + } catch (FileNotFoundException e) { + throw new RuntimeException("Unable to read XML from file", e); + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + public static String writeDocument(Document doc, boolean prettyPrint) { + StringWriter writer = new StringWriter(); + writeDocument(doc, prettyPrint, writer); + return writer.toString(); + } + + public static void writeDocument(Document doc, boolean prettyPrint, Writer writer) { + XMLWriter xmlWriter; + try { + if (prettyPrint) { + OutputFormat format = OutputFormat.createPrettyPrint(); + xmlWriter = new XMLWriter(writer, format); + } else { + xmlWriter = new XMLWriter(writer); + } + xmlWriter.write(doc); + } catch (IOException e) { + throw new RuntimeException("Unable to write XML", e); + } + } + + public static void writeDocument(Document doc, boolean prettyPrint, OutputStream stream) { + XMLWriter xmlWriter; + try { + if (prettyPrint) { + OutputFormat format = OutputFormat.createPrettyPrint(); + xmlWriter = new XMLWriter(stream, format); + } else { + xmlWriter = new XMLWriter(stream); + } + xmlWriter.write(doc); + } catch (IOException e) { + throw new RuntimeException("Unable to write XML", e); + } + } + + @SuppressWarnings("unchecked") + public static List elements(Element element) { + return element.elements(); + } + + @SuppressWarnings("unchecked") + public static List elements(Element element, String name) { + return element.elements(name); + } + + @SuppressWarnings("unchecked") + public static List attributes(Element element) { + return element.attributes(); + } + + public static void storeMap(Element parentElement, Map map) { + if (map == null) { + return; + } + + Element mapElem = parentElement.addElement("map"); + for (Map.Entry entry : map.entrySet()) { + Element entryElem = mapElem.addElement("entry"); + entryElem.addAttribute("key", entry.getKey()); + Element valueElem = entryElem.addElement("value"); + if (entry.getValue() != null) { + String value = StringEscapeUtils.escapeXml(entry.getValue()); + valueElem.setText(value); + } + } + } + + public static void loadMap(Element mapElement, Map map) { + Preconditions.checkNotNullArgument(map, "map is null"); + + for (Element entryElem : elements(mapElement, "entry")) { + String key = entryElem.attributeValue("key"); + if (key == null) { + throw new IllegalStateException("No 'key' attribute"); + } + + String value = null; + Element valueElem = entryElem.element("value"); + if (valueElem != null) { + value = StringEscapeUtils.unescapeXml(valueElem.getText()); + } + + map.put(key, value); + } + } + + public static void walkAttributesRecursive(Element element, ElementAttributeVisitor visitor) { + walkAttributes(element, visitor); + + for (Element childElement : elements(element)) { + walkAttributesRecursive(childElement, visitor); + } + } + + public static void walkAttributes(Element element, ElementAttributeVisitor visitor) { + for (Attribute attribute : attributes(element)) { + visitor.onVisit(element, attribute); + } + } + + public interface ElementAttributeVisitor { + void onVisit(Element element, Attribute attribute); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/util/ReflectionHelper.java b/modules/global/src/com/haulmont/bali/util/ReflectionHelper.java index 0af8a1d070..5d4b431f5b 100644 --- a/modules/global/src/com/haulmont/bali/util/ReflectionHelper.java +++ b/modules/global/src/com/haulmont/bali/util/ReflectionHelper.java @@ -1,180 +1,180 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.util; - -import org.apache.commons.lang.reflect.ConstructorUtils; -import org.dom4j.Element; - -import javax.annotation.Nullable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Constructor; -import java.util.*; - -/** - * Utility class to simplify work with Java reflection. - * - */ -public final class ReflectionHelper { - - private ReflectionHelper() { - } - - /** - * Load class by name. - * @param name class FQN or primitive type name - * @return class instance - * @throws ClassNotFoundException if not found - */ - public static Class loadClass(String name) throws ClassNotFoundException { - switch (name) { - case "int": - return int.class; - case "short": - return short.class; - case "char": - return char.class; - case "byte": - return byte.class; - case "long": - return long.class; - case "float": - return float.class; - case "double": - return double.class; - case "boolean": - return boolean.class; - } - return Thread.currentThread().getContextClassLoader().loadClass(name); - } - - /** - * Load class by name, wrapping a {@link ClassNotFoundException} into unchecked exception. - * @param name class FQN - * @return class instance - */ - public static Class getClass(String name) { - try { - return (Class) loadClass(name); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - /** - * Instantiates an object by appropriate constructor. - * @param cls class - * @param params constructor arguments - * @return created object instance - * @throws NoSuchMethodException if the class has no constructor matching the given arguments - */ - @SuppressWarnings("unchecked") - public static T newInstance(Class cls, Object... params) throws NoSuchMethodException { - Class[] paramTypes = getParamTypes(params); - - Constructor constructor = ConstructorUtils.getMatchingAccessibleConstructor(cls, paramTypes); - if (constructor == null) - throw new NoSuchMethodException("Cannot find a matching constructor for " + cls.getName() + " and given parameters"); - try { - return constructor.newInstance(params); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - /** - * Searches for a method by its name and arguments. - * @param c class - * @param name method name - * @param params method arguments - * @return method reference or null if a suitable method not found - */ - @Nullable - public static Method findMethod(Class c, String name, Object...params) { - Class[] paramTypes = getParamTypes(params); - - Method method = null; - try { - method = c.getDeclaredMethod(name, paramTypes); - } catch (NoSuchMethodException e) { - try { - method = c.getMethod(name, paramTypes); - } catch (NoSuchMethodException e1) { - // - } - } - if (method != null) - method.setAccessible(true); - - return method; - } - - /** - * Invokes a method by reflection. - * @param obj object instance - * @param name method name - * @param params method arguments - * @return method result - * @throws NoSuchMethodException if a suitable method not found - */ - public static T invokeMethod(Object obj, String name, Object...params) throws NoSuchMethodException - { - Class[] paramTypes = getParamTypes(params); - - final Class aClass = obj.getClass(); - Method method; - try { - method = aClass.getDeclaredMethod(name, paramTypes); - } catch (NoSuchMethodException e) { - method = aClass.getMethod(name, paramTypes); - } - method.setAccessible(true); - try { - //noinspection unchecked - return (T) method.invoke(obj, params); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - /** - * Constructs an array of argument types from an array of actual values. Values can not contain nulls. - * @param params arguments - * @return the array of argument types - */ - public static Class[] getParamTypes(Object... params) { - List paramClasses = new ArrayList<>(); - for (Object param : params) { - if (param == null) - throw new IllegalStateException("Null parameter"); - - final Class aClass = param.getClass(); - if (List.class.isAssignableFrom(aClass)) { - paramClasses.add(List.class); - } else if (Set.class.isAssignableFrom(aClass)) { - paramClasses.add(Set.class); - } else if (Map.class.isAssignableFrom(aClass)) { - paramClasses.add(Map.class); - } else if (Element.class.isAssignableFrom(aClass)) { - paramClasses.add(Element.class); - } else { - paramClasses.add(aClass); - } - } - return paramClasses.toArray(new Class[paramClasses.size()]); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.util; + +import org.apache.commons.lang.reflect.ConstructorUtils; +import org.dom4j.Element; + +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.util.*; + +/** + * Utility class to simplify work with Java reflection. + * + */ +public final class ReflectionHelper { + + private ReflectionHelper() { + } + + /** + * Load class by name. + * @param name class FQN or primitive type name + * @return class instance + * @throws ClassNotFoundException if not found + */ + public static Class loadClass(String name) throws ClassNotFoundException { + switch (name) { + case "int": + return int.class; + case "short": + return short.class; + case "char": + return char.class; + case "byte": + return byte.class; + case "long": + return long.class; + case "float": + return float.class; + case "double": + return double.class; + case "boolean": + return boolean.class; + } + return Thread.currentThread().getContextClassLoader().loadClass(name); + } + + /** + * Load class by name, wrapping a {@link ClassNotFoundException} into unchecked exception. + * @param name class FQN + * @return class instance + */ + public static Class getClass(String name) { + try { + return (Class) loadClass(name); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Instantiates an object by appropriate constructor. + * @param cls class + * @param params constructor arguments + * @return created object instance + * @throws NoSuchMethodException if the class has no constructor matching the given arguments + */ + @SuppressWarnings("unchecked") + public static T newInstance(Class cls, Object... params) throws NoSuchMethodException { + Class[] paramTypes = getParamTypes(params); + + Constructor constructor = ConstructorUtils.getMatchingAccessibleConstructor(cls, paramTypes); + if (constructor == null) + throw new NoSuchMethodException("Cannot find a matching constructor for " + cls.getName() + " and given parameters"); + try { + return constructor.newInstance(params); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + /** + * Searches for a method by its name and arguments. + * @param c class + * @param name method name + * @param params method arguments + * @return method reference or null if a suitable method not found + */ + @Nullable + public static Method findMethod(Class c, String name, Object...params) { + Class[] paramTypes = getParamTypes(params); + + Method method = null; + try { + method = c.getDeclaredMethod(name, paramTypes); + } catch (NoSuchMethodException e) { + try { + method = c.getMethod(name, paramTypes); + } catch (NoSuchMethodException e1) { + // + } + } + if (method != null) + method.setAccessible(true); + + return method; + } + + /** + * Invokes a method by reflection. + * @param obj object instance + * @param name method name + * @param params method arguments + * @return method result + * @throws NoSuchMethodException if a suitable method not found + */ + public static T invokeMethod(Object obj, String name, Object...params) throws NoSuchMethodException + { + Class[] paramTypes = getParamTypes(params); + + final Class aClass = obj.getClass(); + Method method; + try { + method = aClass.getDeclaredMethod(name, paramTypes); + } catch (NoSuchMethodException e) { + method = aClass.getMethod(name, paramTypes); + } + method.setAccessible(true); + try { + //noinspection unchecked + return (T) method.invoke(obj, params); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + /** + * Constructs an array of argument types from an array of actual values. Values can not contain nulls. + * @param params arguments + * @return the array of argument types + */ + public static Class[] getParamTypes(Object... params) { + List paramClasses = new ArrayList<>(); + for (Object param : params) { + if (param == null) + throw new IllegalStateException("Null parameter"); + + final Class aClass = param.getClass(); + if (List.class.isAssignableFrom(aClass)) { + paramClasses.add(List.class); + } else if (Set.class.isAssignableFrom(aClass)) { + paramClasses.add(Set.class); + } else if (Map.class.isAssignableFrom(aClass)) { + paramClasses.add(Map.class); + } else if (Element.class.isAssignableFrom(aClass)) { + paramClasses.add(Element.class); + } else { + paramClasses.add(aClass); + } + } + return paramClasses.toArray(new Class[paramClasses.size()]); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/bali/util/StringHelper.java b/modules/global/src/com/haulmont/bali/util/StringHelper.java index 6d143548fd..d0b3678d51 100644 --- a/modules/global/src/com/haulmont/bali/util/StringHelper.java +++ b/modules/global/src/com/haulmont/bali/util/StringHelper.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.bali.util; - -public final class StringHelper { - - private StringHelper() { - } - - /** - * Removes extra (more than one) whitespace characters from any place of the string.
- * Examples:
- * " aaa bbb ccc ddd " becomes "aaa bbb ccc ddd" - * - */ - public static String removeExtraSpaces(String str) { - if (str == null || str.isEmpty()) - return str; - - StringBuilder sb = new StringBuilder(); - - int pos = 0; - boolean prevWS = true; - - for (int i = 0; i < str.length(); i++) { - if (Character.isWhitespace(str.charAt(i)) || i == str.length() - 1) { - if (!prevWS) { - sb.append(str.substring(pos, i)).append(str.charAt(i)); - } - prevWS = true; - } else { - if (prevWS) - pos = i; - prevWS = false; - } - } - if (Character.isWhitespace(sb.charAt(sb.length() - 1))) - sb.deleteCharAt(sb.length() - 1); - - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.bali.util; + +public final class StringHelper { + + private StringHelper() { + } + + /** + * Removes extra (more than one) whitespace characters from any place of the string.
+ * Examples:
+ * " aaa bbb ccc ddd " becomes "aaa bbb ccc ddd" + * + */ + public static String removeExtraSpaces(String str) { + if (str == null || str.isEmpty()) + return str; + + StringBuilder sb = new StringBuilder(); + + int pos = 0; + boolean prevWS = true; + + for (int i = 0; i < str.length(); i++) { + if (Character.isWhitespace(str.charAt(i)) || i == str.length() - 1) { + if (!prevWS) { + sb.append(str.substring(pos, i)).append(str.charAt(i)); + } + prevWS = true; + } else { + if (prevWS) + pos = i; + prevWS = false; + } + } + if (Character.isWhitespace(sb.charAt(sb.length() - 1))) + sb.deleteCharAt(sb.length() - 1); + + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/annotations/Composition.java b/modules/global/src/com/haulmont/chile/core/annotations/Composition.java index 4bc5681765..a154ccea64 100644 --- a/modules/global/src/com/haulmont/chile/core/annotations/Composition.java +++ b/modules/global/src/com/haulmont/chile/core/annotations/Composition.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.annotations; - -import java.lang.annotation.Target; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Marks a reference as composition. - * Composition implies ownership, that is the referenced object exists only as part of the owning entity. - *

An attribute marked with this annotation yields the {@link com.haulmont.chile.core.model.MetaProperty} - * of type {@link com.haulmont.chile.core.model.MetaProperty.Type#COMPOSITION}

- */ -@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Composition { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Marks a reference as composition. + * Composition implies ownership, that is the referenced object exists only as part of the owning entity. + *

An attribute marked with this annotation yields the {@link com.haulmont.chile.core.model.MetaProperty} + * of type {@link com.haulmont.chile.core.model.MetaProperty.Type#COMPOSITION}

+ */ +@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Composition { } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/annotations/MetaClass.java b/modules/global/src/com/haulmont/chile/core/annotations/MetaClass.java index 773f411567..7678b662f6 100644 --- a/modules/global/src/com/haulmont/chile/core/annotations/MetaClass.java +++ b/modules/global/src/com/haulmont/chile/core/annotations/MetaClass.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.annotations; - -import java.lang.annotation.Target; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Target({java.lang.annotation.ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface MetaClass { - String name(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.annotations; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Target({java.lang.annotation.ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MetaClass { + String name(); +} diff --git a/modules/global/src/com/haulmont/chile/core/annotations/MetaProperty.java b/modules/global/src/com/haulmont/chile/core/annotations/MetaProperty.java index 1c9e6aa46a..b585141780 100644 --- a/modules/global/src/com/haulmont/chile/core/annotations/MetaProperty.java +++ b/modules/global/src/com/haulmont/chile/core/annotations/MetaProperty.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This annotation is used to define a non-persistent attribute, or to specify additional properties of a persistent - * attribute. - * - */ -@Target({java.lang.annotation.ElementType.METHOD, ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface MetaProperty { - - /** - * Whether the attribute is required. - */ - boolean mandatory() default false; - - /** - * Explicitly defined datatype that overrides a datatype inferred from the attribute Java type. - */ - String datatype() default ""; - - /** - * Related properties are fetched from the database when this property is included in a view. - */ - String[] related() default ""; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used to define a non-persistent attribute, or to specify additional properties of a persistent + * attribute. + * + */ +@Target({java.lang.annotation.ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MetaProperty { + + /** + * Whether the attribute is required. + */ + boolean mandatory() default false; + + /** + * Explicitly defined datatype that overrides a datatype inferred from the attribute Java type. + */ + String datatype() default ""; + + /** + * Related properties are fetched from the database when this property is included in a view. + */ + String[] related() default ""; +} diff --git a/modules/global/src/com/haulmont/chile/core/annotations/NamePattern.java b/modules/global/src/com/haulmont/chile/core/annotations/NamePattern.java index 7453b32b08..13d4f12e0d 100644 --- a/modules/global/src/com/haulmont/chile/core/annotations/NamePattern.java +++ b/modules/global/src/com/haulmont/chile/core/annotations/NamePattern.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.annotations; - -import com.haulmont.cuba.core.entity.annotation.MetaAnnotation; - -import java.lang.annotation.Target; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Defines an instance name format pattern in the form {0}|{1}, where - *
    - *
  • {0} - format string as for {@link String#format}, or a name of this object method, returning string, - * with {@code #} symbol in the beginning.
  • - *
  • {1} - comma-separated list of field names, corresponding to format {0}. These fields are also used for - * defining a {@code _minimal} view of this entity.
  • - *
- * Extra spaces between parts are not allowed. - * - *
Format string example: {@code @NamePattern("%s : %s|name,address")} - * - *
Method example: - * {@code @NamePattern("#getCaption|login,name")} - *
- * public class User extends StandardEntity {
- * ...
- *     public String getCaption() {
- *         String pattern = AppContext.getProperty("cuba.user.namePattern");
- *         if (StringUtils.isBlank(pattern)) {
- *             pattern = "{1} [{0}]";
- *         }
- *         MessageFormat fmt = new MessageFormat(pattern);
- *         return fmt.format(new Object[] {login, name});
- *     }
- * }
- * 
- */ -@Target({java.lang.annotation.ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@MetaAnnotation -public @interface NamePattern { - String value(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.annotations; + +import com.haulmont.cuba.core.entity.annotation.MetaAnnotation; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Defines an instance name format pattern in the form {0}|{1}, where + *
    + *
  • {0} - format string as for {@link String#format}, or a name of this object method, returning string, + * with {@code #} symbol in the beginning.
  • + *
  • {1} - comma-separated list of field names, corresponding to format {0}. These fields are also used for + * defining a {@code _minimal} view of this entity.
  • + *
+ * Extra spaces between parts are not allowed. + * + *
Format string example: {@code @NamePattern("%s : %s|name,address")} + * + *
Method example: + * {@code @NamePattern("#getCaption|login,name")} + *
+ * public class User extends StandardEntity {
+ * ...
+ *     public String getCaption() {
+ *         String pattern = AppContext.getProperty("cuba.user.namePattern");
+ *         if (StringUtils.isBlank(pattern)) {
+ *             pattern = "{1} [{0}]";
+ *         }
+ *         MessageFormat fmt = new MessageFormat(pattern);
+ *         return fmt.format(new Object[] {login, name});
+ *     }
+ * }
+ * 
+ */ +@Target({java.lang.annotation.ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@MetaAnnotation +public @interface NamePattern { + String value(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/common/ValueListener.java b/modules/global/src/com/haulmont/chile/core/common/ValueListener.java index a69b144ad6..49ceece55f 100644 --- a/modules/global/src/com/haulmont/chile/core/common/ValueListener.java +++ b/modules/global/src/com/haulmont/chile/core/common/ValueListener.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.common; - -/** - * Interface to track changes in data model objects. - * - * @deprecated Use {@link com.haulmont.chile.core.model.Instance.PropertyChangeListener} - */ -@Deprecated -public interface ValueListener { - - /** - * Called by a data model object when an attribute changes. - * - * @param item data model object instance - * @param property changed attribute name - * @param prevValue previous value - * @param value current value - */ - void propertyChanged(Object item, String property, Object prevValue, Object value); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.common; + +/** + * Interface to track changes in data model objects. + * + * @deprecated Use {@link com.haulmont.chile.core.model.Instance.PropertyChangeListener} + */ +@Deprecated +public interface ValueListener { + + /** + * Called by a data model object when an attribute changes. + * + * @param item data model object instance + * @param property changed attribute name + * @param prevValue previous value + * @param value current value + */ + void propertyChanged(Object item, String property, Object prevValue, Object value); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/Datatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/Datatype.java index 7e16fcacbf..2405695c0a 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/Datatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/Datatype.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes; - -import com.haulmont.chile.core.annotations.JavaClass; - -import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.text.ParseException; -import java.util.Locale; - -/** - * Represents a data type of an entity property. - */ -public interface Datatype { - - /** Converts value to String. Returns an empty string for null value. */ - String format(@Nullable Object value); - - /** Converts value to String taking into account local formats. Returns an empty string for null value. */ - String format(@Nullable Object value, Locale locale); - - /** Parses value from String */ - @Nullable - T parse(@Nullable String value) throws ParseException; - - /** Parses value from String taking into account local formats */ - @Nullable - T parse(@Nullable String value, Locale locale) throws ParseException; - - /** Java class representing this Datatype */ - default Class getJavaClass() { - JavaClass annotation = getClass().getAnnotation(JavaClass.class); - if (annotation == null) - throw new IllegalStateException("Datatype " + this + " does not declare a Java class it works with. " + - "Either add @JavaClass annotation or implement getJavaClass() method."); - return annotation.value(); - } - - /** - * DEPRECATED. - * Use {@link DatatypeRegistry#getId(Datatype)} or {@link DatatypeRegistry#getIdByJavaClass(Class)} methods. - */ - @Deprecated - default String getName() { - try { - Field nameField = getClass().getField("NAME"); - if (Modifier.isStatic(nameField.getModifiers())) { - return (String) nameField.get(null); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - // ignore - } - throw new IllegalStateException("Cannot get datatype name. Do not use this method as it is deprecated."); - } - - @Deprecated - @Nullable - default T read(ResultSet resultSet, int index) throws SQLException { - throw new UnsupportedOperationException("Method is deprecated"); - } - - @Deprecated - default void write(PreparedStatement statement, int index, @Nullable Object value) throws SQLException { - throw new UnsupportedOperationException("Method is deprecated"); - } - - @Deprecated - default int getSqlType() { - throw new UnsupportedOperationException("Method is deprecated"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes; + +import com.haulmont.chile.core.annotations.JavaClass; + +import javax.annotation.Nullable; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.ParseException; +import java.util.Locale; + +/** + * Represents a data type of an entity property. + */ +public interface Datatype { + + /** Converts value to String. Returns an empty string for null value. */ + String format(@Nullable Object value); + + /** Converts value to String taking into account local formats. Returns an empty string for null value. */ + String format(@Nullable Object value, Locale locale); + + /** Parses value from String */ + @Nullable + T parse(@Nullable String value) throws ParseException; + + /** Parses value from String taking into account local formats */ + @Nullable + T parse(@Nullable String value, Locale locale) throws ParseException; + + /** Java class representing this Datatype */ + default Class getJavaClass() { + JavaClass annotation = getClass().getAnnotation(JavaClass.class); + if (annotation == null) + throw new IllegalStateException("Datatype " + this + " does not declare a Java class it works with. " + + "Either add @JavaClass annotation or implement getJavaClass() method."); + return annotation.value(); + } + + /** + * DEPRECATED. + * Use {@link DatatypeRegistry#getId(Datatype)} or {@link DatatypeRegistry#getIdByJavaClass(Class)} methods. + */ + @Deprecated + default String getName() { + try { + Field nameField = getClass().getField("NAME"); + if (Modifier.isStatic(nameField.getModifiers())) { + return (String) nameField.get(null); + } + } catch (NoSuchFieldException | IllegalAccessException e) { + // ignore + } + throw new IllegalStateException("Cannot get datatype name. Do not use this method as it is deprecated."); + } + + @Deprecated + @Nullable + default T read(ResultSet resultSet, int index) throws SQLException { + throw new UnsupportedOperationException("Method is deprecated"); + } + + @Deprecated + default void write(PreparedStatement statement, int index, @Nullable Object value) throws SQLException { + throw new UnsupportedOperationException("Method is deprecated"); + } + + @Deprecated + default int getSqlType() { + throw new UnsupportedOperationException("Method is deprecated"); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/Datatypes.java b/modules/global/src/com/haulmont/chile/core/datatypes/Datatypes.java index abd2b06e47..eef1bee62e 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/Datatypes.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/Datatypes.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes; - -import com.haulmont.cuba.core.global.AppBeans; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Set; - -/** - * Utility class for accessing datatypes and format strings. - * Consider using {@link DatatypeRegistry} and {@link FormatStringsRegistry} beans directly. - */ -public class Datatypes { - - /** - * Returns localized format strings. - * @param locale selected locale - * @return {@link FormatStrings} object, or null if no formats are registered for the locale - */ - @Nullable - public static FormatStrings getFormatStrings(Locale locale) { - return getFormatStringsRegistry().getFormatStrings(locale); - } - - /** - * Returns localized format strings. - * @param locale selected locale - * @return {@link FormatStrings} object. Throws exception if not found. - */ - @Nonnull - public static FormatStrings getFormatStringsNN(Locale locale) { - return getFormatStringsRegistry().getFormatStringsNN(locale); - } - - /** - * Get Datatype instance by its unique name - * @return Datatype instance - * @throws IllegalArgumentException if no datatype with the given name found - */ - @Nonnull - public static Datatype get(String name) { - return getDatatypeRegistry().get(name); - } - - /** - * Get Datatype instance by the corresponding Java class. This method tries to find matching supertype too. - * @return Datatype instance or null if not found - */ - @Nullable - public static Datatype get(Class clazz) { - return getDatatypeRegistry().get(clazz); - } - - /** - * Get Datatype instance by the corresponding Java class. This method tries to find matching supertype too. - * @return Datatype instance - * @throws IllegalArgumentException if no datatype suitable for the given type found - */ - @Nonnull - public static Datatype getNN(Class clazz) { - return getDatatypeRegistry().getNN(clazz); - } - - /** - * @return all registered Datatype ids. - */ - public static Set getIds() { - return getDatatypeRegistry().getIds(); - } - - private static DatatypeRegistry getDatatypeRegistry() { - return AppBeans.get(DatatypeRegistry.class); - } - - private static FormatStringsRegistry getFormatStringsRegistry() { - return AppBeans.get(FormatStringsRegistry.class); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes; + +import com.haulmont.cuba.core.global.AppBeans; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.Set; + +/** + * Utility class for accessing datatypes and format strings. + * Consider using {@link DatatypeRegistry} and {@link FormatStringsRegistry} beans directly. + */ +public class Datatypes { + + /** + * Returns localized format strings. + * @param locale selected locale + * @return {@link FormatStrings} object, or null if no formats are registered for the locale + */ + @Nullable + public static FormatStrings getFormatStrings(Locale locale) { + return getFormatStringsRegistry().getFormatStrings(locale); + } + + /** + * Returns localized format strings. + * @param locale selected locale + * @return {@link FormatStrings} object. Throws exception if not found. + */ + @Nonnull + public static FormatStrings getFormatStringsNN(Locale locale) { + return getFormatStringsRegistry().getFormatStringsNN(locale); + } + + /** + * Get Datatype instance by its unique name + * @return Datatype instance + * @throws IllegalArgumentException if no datatype with the given name found + */ + @Nonnull + public static Datatype get(String name) { + return getDatatypeRegistry().get(name); + } + + /** + * Get Datatype instance by the corresponding Java class. This method tries to find matching supertype too. + * @return Datatype instance or null if not found + */ + @Nullable + public static Datatype get(Class clazz) { + return getDatatypeRegistry().get(clazz); + } + + /** + * Get Datatype instance by the corresponding Java class. This method tries to find matching supertype too. + * @return Datatype instance + * @throws IllegalArgumentException if no datatype suitable for the given type found + */ + @Nonnull + public static Datatype getNN(Class clazz) { + return getDatatypeRegistry().getNN(clazz); + } + + /** + * @return all registered Datatype ids. + */ + public static Set getIds() { + return getDatatypeRegistry().getIds(); + } + + private static DatatypeRegistry getDatatypeRegistry() { + return AppBeans.get(DatatypeRegistry.class); + } + + private static FormatStringsRegistry getFormatStringsRegistry() { + return AppBeans.get(FormatStringsRegistry.class); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/Enumeration.java b/modules/global/src/com/haulmont/chile/core/datatypes/Enumeration.java index be1c284044..312e761088 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/Enumeration.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/Enumeration.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes; - -import java.util.List; - -public interface Enumeration extends Datatype { - List getValues(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes; + +import java.util.List; + +public interface Enumeration extends Datatype { + List getValues(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/FormatStrings.java b/modules/global/src/com/haulmont/chile/core/datatypes/FormatStrings.java index 400abc4831..8d4213fbda 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/FormatStrings.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/FormatStrings.java @@ -1,90 +1,90 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes; - -import java.text.DecimalFormatSymbols; - -/** - * Localized format strings container.
- * An instance of this class can be acquired through {@link Datatypes#getFormatStrings(java.util.Locale)}. - */ -public class FormatStrings { - - private DecimalFormatSymbols formatSymbols; - private String integerFormat; - private String doubleFormat; - private String decimalFormat; - private String dateFormat; - private String dateTimeFormat; - private String timeFormat; - private String trueString; - private String falseString; - - public FormatStrings(char decimalSeparator, char groupingSeparator, - String integerFormat, String doubleFormat, String decimalFormat, - String dateFormat, String dateTimeFormat, - String timeFormat, String trueString, String falseString) { - formatSymbols = new DecimalFormatSymbols(); - formatSymbols.setDecimalSeparator(decimalSeparator); - formatSymbols.setGroupingSeparator(groupingSeparator); - this.integerFormat = integerFormat; - this.doubleFormat = doubleFormat; - this.decimalFormat = decimalFormat; - this.dateFormat = dateFormat; - this.dateTimeFormat = dateTimeFormat; - this.timeFormat = timeFormat; - this.trueString = trueString; - this.falseString = falseString; - } - - public DecimalFormatSymbols getFormatSymbols() { - return formatSymbols; - } - - public String getIntegerFormat() { - return integerFormat; - } - - public String getDoubleFormat() { - return doubleFormat; - } - - public String getDecimalFormat() { - return decimalFormat; - } - - public String getDateFormat() { - return dateFormat; - } - - public String getDateTimeFormat() { - return dateTimeFormat; - } - - public String getTimeFormat() { - return timeFormat; - } - - public String getTrueString() { - return trueString; - } - - public String getFalseString() { - return falseString; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes; + +import java.text.DecimalFormatSymbols; + +/** + * Localized format strings container.
+ * An instance of this class can be acquired through {@link Datatypes#getFormatStrings(java.util.Locale)}. + */ +public class FormatStrings { + + private DecimalFormatSymbols formatSymbols; + private String integerFormat; + private String doubleFormat; + private String decimalFormat; + private String dateFormat; + private String dateTimeFormat; + private String timeFormat; + private String trueString; + private String falseString; + + public FormatStrings(char decimalSeparator, char groupingSeparator, + String integerFormat, String doubleFormat, String decimalFormat, + String dateFormat, String dateTimeFormat, + String timeFormat, String trueString, String falseString) { + formatSymbols = new DecimalFormatSymbols(); + formatSymbols.setDecimalSeparator(decimalSeparator); + formatSymbols.setGroupingSeparator(groupingSeparator); + this.integerFormat = integerFormat; + this.doubleFormat = doubleFormat; + this.decimalFormat = decimalFormat; + this.dateFormat = dateFormat; + this.dateTimeFormat = dateTimeFormat; + this.timeFormat = timeFormat; + this.trueString = trueString; + this.falseString = falseString; + } + + public DecimalFormatSymbols getFormatSymbols() { + return formatSymbols; + } + + public String getIntegerFormat() { + return integerFormat; + } + + public String getDoubleFormat() { + return doubleFormat; + } + + public String getDecimalFormat() { + return decimalFormat; + } + + public String getDateFormat() { + return dateFormat; + } + + public String getDateTimeFormat() { + return dateTimeFormat; + } + + public String getTimeFormat() { + return timeFormat; + } + + public String getTrueString() { + return trueString; + } + + public String getFalseString() { + return falseString; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/BigDecimalDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/BigDecimalDatatype.java index f184a12e7e..7f79d90bc8 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/BigDecimalDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/BigDecimalDatatype.java @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(BigDecimal.class) -public class BigDecimalDatatype extends NumberDatatype implements Datatype { - - public BigDecimalDatatype(Element element) { - super(element); - } - - @Override - protected NumberFormat createFormat() { - NumberFormat format = super.createFormat(); - if (format instanceof DecimalFormat) { - ((DecimalFormat) format).setParseBigDecimal(true); - } - return format; - } - - @Override - public String format(Object value) { - return value == null ? "" : createFormat().format(value); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getDecimalFormat(), formatSymbols); - return format.format(value); - } - - @Override - public BigDecimal parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - return (BigDecimal) parse(value, createFormat()); - } - - @Override - public BigDecimal parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - DecimalFormat format = new DecimalFormat(formatStrings.getDecimalFormat(), formatSymbols); - format.setParseBigDecimal(true); - return (BigDecimal) parse(value, format); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "decimal"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(BigDecimal.class) +public class BigDecimalDatatype extends NumberDatatype implements Datatype { + + public BigDecimalDatatype(Element element) { + super(element); + } + + @Override + protected NumberFormat createFormat() { + NumberFormat format = super.createFormat(); + if (format instanceof DecimalFormat) { + ((DecimalFormat) format).setParseBigDecimal(true); + } + return format; + } + + @Override + public String format(Object value) { + return value == null ? "" : createFormat().format(value); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getDecimalFormat(), formatSymbols); + return format.format(value); + } + + @Override + public BigDecimal parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + return (BigDecimal) parse(value, createFormat()); + } + + @Override + public BigDecimal parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + DecimalFormat format = new DecimalFormat(formatStrings.getDecimalFormat(), formatSymbols); + format.setParseBigDecimal(true); + return (BigDecimal) parse(value, format); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "decimal"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/BooleanDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/BooleanDatatype.java index f256d2df0d..7125a7eabf 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/BooleanDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/BooleanDatatype.java @@ -1,93 +1,93 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(Boolean.class) -public class BooleanDatatype implements Datatype { - - @Override - public String format(Object value) { - return value == null ? "" : Boolean.toString((Boolean) value); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - return (boolean) value ? formatStrings.getTrueString() : formatStrings.getFalseString(); - } - - protected Boolean parse(@Nullable String value, String trueString, String falseString) throws ParseException { - if (!StringUtils.isBlank(value)) { - String lowerCaseValue = StringUtils.lowerCase(value); - if (trueString.equals(lowerCaseValue)) { - return true; - } - if (falseString.equals(lowerCaseValue)) { - return false; - } - throw new ParseException(String.format("Can't parse '%s'", value), 0); - } - return null; - } - - @Override - public Boolean parse(String value) throws ParseException { - return parse(value, "true", "false"); - } - - @Override - public Boolean parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - return parse(value, formatStrings.getTrueString(), formatStrings.getFalseString()); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "boolean"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(Boolean.class) +public class BooleanDatatype implements Datatype { + + @Override + public String format(Object value) { + return value == null ? "" : Boolean.toString((Boolean) value); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + return (boolean) value ? formatStrings.getTrueString() : formatStrings.getFalseString(); + } + + protected Boolean parse(@Nullable String value, String trueString, String falseString) throws ParseException { + if (!StringUtils.isBlank(value)) { + String lowerCaseValue = StringUtils.lowerCase(value); + if (trueString.equals(lowerCaseValue)) { + return true; + } + if (falseString.equals(lowerCaseValue)) { + return false; + } + throw new ParseException(String.format("Can't parse '%s'", value), 0); + } + return null; + } + + @Override + public Boolean parse(String value) throws ParseException { + return parse(value, "true", "false"); + } + + @Override + public Boolean parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + return parse(value, formatStrings.getTrueString(), formatStrings.getFalseString()); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "boolean"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/ByteArrayDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/ByteArrayDatatype.java index 0f87719b16..238feee836 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/ByteArrayDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/ByteArrayDatatype.java @@ -1,67 +1,67 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import org.apache.commons.codec.binary.Base64; - -import java.nio.charset.StandardCharsets; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(byte[].class) -public class ByteArrayDatatype implements Datatype { - - @Override - public String format(Object value) { - if (value == null) - return ""; - - return new String(Base64.encodeBase64((byte[]) value), StandardCharsets.UTF_8); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) - return ""; - - return format(value); - } - - @Override - public byte[] parse(String value) throws ParseException { - if (value == null || value.length() == 0) - return null; - - return Base64.decodeBase64(value.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public byte[] parse(String value, Locale locale) throws ParseException { - return parse(value); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public static final String NAME = "byteArray"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import org.apache.commons.codec.binary.Base64; + +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(byte[].class) +public class ByteArrayDatatype implements Datatype { + + @Override + public String format(Object value) { + if (value == null) + return ""; + + return new String(Base64.encodeBase64((byte[]) value), StandardCharsets.UTF_8); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) + return ""; + + return format(value); + } + + @Override + public byte[] parse(String value) throws ParseException { + if (value == null || value.length() == 0) + return null; + + return Base64.decodeBase64(value.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public byte[] parse(String value, Locale locale) throws ParseException { + return parse(value); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public static final String NAME = "byteArray"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateDatatype.java index be640f4bff..0c8de5f66c 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateDatatype.java @@ -1,136 +1,136 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.chile.core.datatypes.ParameterizedDatatype; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -/** - * DateDatatype works with java.sql.Date but is parametrized with - * java.util.Date to avoid problems with casting. - */ -@JavaClass(java.sql.Date.class) -public class DateDatatype implements Datatype, ParameterizedDatatype { - - protected String formatPattern; - - public DateDatatype(Element element) { - formatPattern = element.attributeValue("format"); - } - - @Override - public String format(Object value) { - if (value == null) { - return ""; - } - - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - } else { - format = DateFormat.getDateInstance(); - } - return format.format((value)); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getDateFormat()); - return format.format(value); - } - - protected java.sql.Date normalize(java.util.Date dateTime) { - Calendar cal = Calendar.getInstance(); - cal.setTime(dateTime); - cal.set(Calendar.HOUR, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return new java.sql.Date(cal.getTimeInMillis()); - } - - @Override - public Date parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - format.setLenient(false); - } else { - format = DateFormat.getDateInstance(); - } - return normalize(format.parse(value.trim())); - } - - @Override - public Date parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getDateFormat()); - format.setLenient(false); - - return normalize(format.parse(value.trim())); - } - - @Override - public Map getParameters() { - return ParamsMap.of("format", formatPattern); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "date"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.chile.core.datatypes.ParameterizedDatatype; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +/** + * DateDatatype works with java.sql.Date but is parametrized with + * java.util.Date to avoid problems with casting. + */ +@JavaClass(java.sql.Date.class) +public class DateDatatype implements Datatype, ParameterizedDatatype { + + protected String formatPattern; + + public DateDatatype(Element element) { + formatPattern = element.attributeValue("format"); + } + + @Override + public String format(Object value) { + if (value == null) { + return ""; + } + + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + } else { + format = DateFormat.getDateInstance(); + } + return format.format((value)); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getDateFormat()); + return format.format(value); + } + + protected java.sql.Date normalize(java.util.Date dateTime) { + Calendar cal = Calendar.getInstance(); + cal.setTime(dateTime); + cal.set(Calendar.HOUR, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return new java.sql.Date(cal.getTimeInMillis()); + } + + @Override + public Date parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + format.setLenient(false); + } else { + format = DateFormat.getDateInstance(); + } + return normalize(format.parse(value.trim())); + } + + @Override + public Date parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getDateFormat()); + format.setLenient(false); + + return normalize(format.parse(value.trim())); + } + + @Override + public Map getParameters() { + return ParamsMap.of("format", formatPattern); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "date"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateTimeDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateTimeDatatype.java index fcc1f1fd40..7c62837fcd 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateTimeDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DateTimeDatatype.java @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.chile.core.datatypes.ParameterizedDatatype; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -@JavaClass(Date.class) -public class DateTimeDatatype implements Datatype, ParameterizedDatatype { - - private String formatPattern; - - public DateTimeDatatype(Element element) { - formatPattern = element.attributeValue("format"); - } - - @Override - public String format(Object value) { - if (value == null) { - return ""; - } else { - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - } else { - format = DateFormat.getDateInstance(); - } - return format.format((value)); - } - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getDateTimeFormat()); - return format.format(value); - } - - @Override - public Date parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - } else { - format = DateFormat.getDateInstance(); - } - return format.parse(value.trim()); - } - - @Override - public Date parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getDateTimeFormat()); - return format.parse(value.trim()); - } - - - @Override - public Map getParameters() { - return ParamsMap.of("format", formatPattern); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "dateTime"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.chile.core.datatypes.ParameterizedDatatype; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +@JavaClass(Date.class) +public class DateTimeDatatype implements Datatype, ParameterizedDatatype { + + private String formatPattern; + + public DateTimeDatatype(Element element) { + formatPattern = element.attributeValue("format"); + } + + @Override + public String format(Object value) { + if (value == null) { + return ""; + } else { + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + } else { + format = DateFormat.getDateInstance(); + } + return format.format((value)); + } + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getDateTimeFormat()); + return format.format(value); + } + + @Override + public Date parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + } else { + format = DateFormat.getDateInstance(); + } + return format.parse(value.trim()); + } + + @Override + public Date parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getDateTimeFormat()); + return format.parse(value.trim()); + } + + + @Override + public Map getParameters() { + return ParamsMap.of("format", formatPattern); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "dateTime"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DoubleDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DoubleDatatype.java index edafa5cce5..63e15c42fb 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/DoubleDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/DoubleDatatype.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(Double.class) -public class DoubleDatatype extends NumberDatatype implements Datatype { - - public DoubleDatatype(Element element) { - super(element); - } - - @Override - public String format(Object value) { - return value == null ? "" : createFormat().format(value); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getDoubleFormat(), formatSymbols); - return format.format(value); - } - - @Override - public Double parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - return parse(value, createFormat()).doubleValue(); - } - - @Override - public Double parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getDoubleFormat(), formatSymbols); - return parse(value, format).doubleValue(); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "double"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(Double.class) +public class DoubleDatatype extends NumberDatatype implements Datatype { + + public DoubleDatatype(Element element) { + super(element); + } + + @Override + public String format(Object value) { + return value == null ? "" : createFormat().format(value); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getDoubleFormat(), formatSymbols); + return format.format(value); + } + + @Override + public Double parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + return parse(value, createFormat()).doubleValue(); + } + + @Override + public Double parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getDoubleFormat(), formatSymbols); + return parse(value, format).doubleValue(); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "double"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumClass.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumClass.java index 82f7007da7..610179ce06 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumClass.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumClass.java @@ -1,26 +1,26 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.datatypes.impl; - -/** - * Interface to be implemented by enums that serve as entity attribute types. - * @param type of value stored in the database - * - */ -public interface EnumClass { - T getId(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.datatypes.impl; + +/** + * Interface to be implemented by enums that serve as entity attribute types. + * @param type of value stored in the database + * + */ +public interface EnumClass { + T getId(); +} diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumerationImpl.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumerationImpl.java index bf0c21208d..a2933fc8d7 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumerationImpl.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/EnumerationImpl.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.datatypes.Enumeration; -import org.apache.commons.lang.StringUtils; - -import java.text.ParseException; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -public class EnumerationImpl implements Enumeration { - - private Class javaClass; - - public EnumerationImpl(Class javaClass) { - this.javaClass = javaClass; - } - - @Override - public Class getJavaClass() { - return javaClass; - } - - @Override - public String format(Object value) { - if (value == null) return ""; - - final Object v = ((EnumClass) value).getId(); - return String.valueOf(v); - } - - @Override - public String format(Object value, Locale locale) { - return format(value); - } - - @Override - public T parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) - return null; - - for (Enum enumValue : javaClass.getEnumConstants()) { - Object enumId = ((EnumClass) enumValue).getId(); - if (value.equals(enumId.toString())) - return (T) enumValue; - } - return null; - } - - @Override - public T parse(String value, Locale locale) throws ParseException { - return parse(value); - } - - @Override - public List getValues() { - final Enum[] enums = javaClass.getEnumConstants(); - return Arrays.asList(enums); - } - - @Override - public String toString() { - return javaClass.getName(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.datatypes.Enumeration; +import org.apache.commons.lang.StringUtils; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public class EnumerationImpl implements Enumeration { + + private Class javaClass; + + public EnumerationImpl(Class javaClass) { + this.javaClass = javaClass; + } + + @Override + public Class getJavaClass() { + return javaClass; + } + + @Override + public String format(Object value) { + if (value == null) return ""; + + final Object v = ((EnumClass) value).getId(); + return String.valueOf(v); + } + + @Override + public String format(Object value, Locale locale) { + return format(value); + } + + @Override + public T parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) + return null; + + for (Enum enumValue : javaClass.getEnumConstants()) { + Object enumId = ((EnumClass) enumValue).getId(); + if (value.equals(enumId.toString())) + return (T) enumValue; + } + return null; + } + + @Override + public T parse(String value, Locale locale) throws ParseException { + return parse(value); + } + + @Override + public List getValues() { + final Enum[] enums = javaClass.getEnumConstants(); + return Arrays.asList(enums); + } + + @Override + public String toString() { + return javaClass.getName(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/IntegerDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/IntegerDatatype.java index 6541fd4d3b..6d515b592f 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/IntegerDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/IntegerDatatype.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(Integer.class) -public class IntegerDatatype extends NumberDatatype implements Datatype { - - public IntegerDatatype(Element element) { - super(element); - } - - @Override - public String format(Object value) { - return value == null ? "" : createFormat().format(value); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) - return ""; - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) - return format(value); - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); - return format.format(value); - } - - @Override - public Integer parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) - return null; - - return parse(value, createFormat()).intValue(); - } - - @Override - public Integer parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) - return null; - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) - return parse(value); - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); - return parse(value, format).intValue(); - } - - @Override - protected Number parse(String value, NumberFormat format) throws ParseException { - format.setParseIntegerOnly(true); - - Number result = super.parse(value, format); - if (!hasValidIntegerRange(result)) { - throw new ParseException(String.format("Integer range exceeded: \"%s\"", value), 0); - } - return result; - } - - protected boolean hasValidIntegerRange(Number result) throws ParseException { - if (result instanceof Long) { - Long longResult = (Long) result; - - if (longResult > Integer.MAX_VALUE || longResult < Integer.MIN_VALUE) { - return false; - } - } else { - Double doubleResult = (Double) result; - if (doubleResult > Integer.MAX_VALUE || doubleResult < Integer.MIN_VALUE) { - return false; - } - } - return true; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "int"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(Integer.class) +public class IntegerDatatype extends NumberDatatype implements Datatype { + + public IntegerDatatype(Element element) { + super(element); + } + + @Override + public String format(Object value) { + return value == null ? "" : createFormat().format(value); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) + return ""; + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) + return format(value); + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); + return format.format(value); + } + + @Override + public Integer parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) + return null; + + return parse(value, createFormat()).intValue(); + } + + @Override + public Integer parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) + return null; + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) + return parse(value); + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); + return parse(value, format).intValue(); + } + + @Override + protected Number parse(String value, NumberFormat format) throws ParseException { + format.setParseIntegerOnly(true); + + Number result = super.parse(value, format); + if (!hasValidIntegerRange(result)) { + throw new ParseException(String.format("Integer range exceeded: \"%s\"", value), 0); + } + return result; + } + + protected boolean hasValidIntegerRange(Number result) throws ParseException { + if (result instanceof Long) { + Long longResult = (Long) result; + + if (longResult > Integer.MAX_VALUE || longResult < Integer.MIN_VALUE) { + return false; + } + } else { + Double doubleResult = (Double) result; + if (doubleResult > Integer.MAX_VALUE || doubleResult < Integer.MIN_VALUE) { + return false; + } + } + return true; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "int"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/LongDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/LongDatatype.java index 9f9a21ea9a..e35f25832d 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/LongDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/LongDatatype.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(Long.class) -public class LongDatatype extends NumberDatatype implements Datatype { - - public LongDatatype(Element element) { - super(element); - } - - @Override - public String format(Object value) { - return value == null ? "" : createFormat().format(value); - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); - return format.format(value); - } - - @Override - public Long parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - return parse(value, createFormat()).longValue(); - } - - @Override - public Long parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); - NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); - - return parse(value, format).longValue(); - } - - @Override - protected Number parse(String value, NumberFormat format) throws ParseException { - format.setParseIntegerOnly(true); - - Number result = super.parse(value, format); - if (!hasValidLongRange(result)) { - throw new ParseException(String.format("Integer range exceeded: \"%s\"", value), 0); - } - return result; - } - - protected boolean hasValidLongRange(Number result) throws ParseException { - if (result instanceof Double) { - Double doubleResult = (Double) result; - if (doubleResult > Long.MAX_VALUE || doubleResult < Long.MIN_VALUE) { - return false; - } - } - return true; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "long"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(Long.class) +public class LongDatatype extends NumberDatatype implements Datatype { + + public LongDatatype(Element element) { + super(element); + } + + @Override + public String format(Object value) { + return value == null ? "" : createFormat().format(value); + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); + return format.format(value); + } + + @Override + public Long parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + return parse(value, createFormat()).longValue(); + } + + @Override + public Long parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DecimalFormatSymbols formatSymbols = formatStrings.getFormatSymbols(); + NumberFormat format = new DecimalFormat(formatStrings.getIntegerFormat(), formatSymbols); + + return parse(value, format).longValue(); + } + + @Override + protected Number parse(String value, NumberFormat format) throws ParseException { + format.setParseIntegerOnly(true); + + Number result = super.parse(value, format); + if (!hasValidLongRange(result)) { + throw new ParseException(String.format("Integer range exceeded: \"%s\"", value), 0); + } + return result; + } + + protected boolean hasValidLongRange(Number result) throws ParseException { + if (result instanceof Double) { + Double doubleResult = (Double) result; + if (doubleResult > Long.MAX_VALUE || doubleResult < Long.MIN_VALUE) { + return false; + } + } + return true; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "long"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/NumberDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/NumberDatatype.java index 875172eded..5e6e7efacf 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/NumberDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/NumberDatatype.java @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.datatypes.ParameterizedDatatype; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.text.*; -import java.util.Map; - -public abstract class NumberDatatype implements ParameterizedDatatype { - - protected String formatPattern; - protected String decimalSeparator; - protected String groupingSeparator; - - protected NumberDatatype(String formatPattern, String decimalSeparator, String groupingSeparator) { - this.formatPattern = formatPattern; - this.decimalSeparator = decimalSeparator; - this.groupingSeparator = groupingSeparator; - } - - protected NumberDatatype(Element element) { - formatPattern = element.attributeValue("format"); - decimalSeparator = element.attributeValue("decimalSeparator"); - groupingSeparator = element.attributeValue("groupingSeparator"); - } - - @Override - public Map getParameters() { - return ParamsMap.of( - "format", formatPattern, - "decimalSeparator", decimalSeparator, - "groupingSeparator", groupingSeparator); - } - - /** - * Creates non-localized format. - */ - protected NumberFormat createFormat() { - if (formatPattern != null) { - DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(); - - if (!StringUtils.isBlank(decimalSeparator)) - formatSymbols.setDecimalSeparator(decimalSeparator.charAt(0)); - - if (!StringUtils.isBlank(groupingSeparator)) - formatSymbols.setGroupingSeparator(groupingSeparator.charAt(0)); - - return new DecimalFormat(formatPattern, formatSymbols); - } else { - return NumberFormat.getNumberInstance(); - } - } - - protected Number parse(String value, NumberFormat format) throws ParseException { - ParsePosition pos = new ParsePosition(0); - Number res = format.parse(value.trim(), pos); - if (pos.getIndex() != value.length()) { - throw new ParseException( - String.format("Unparseable number: \"%s\"", value), - pos.getErrorIndex() - ); - } - return res; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.datatypes.ParameterizedDatatype; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.text.*; +import java.util.Map; + +public abstract class NumberDatatype implements ParameterizedDatatype { + + protected String formatPattern; + protected String decimalSeparator; + protected String groupingSeparator; + + protected NumberDatatype(String formatPattern, String decimalSeparator, String groupingSeparator) { + this.formatPattern = formatPattern; + this.decimalSeparator = decimalSeparator; + this.groupingSeparator = groupingSeparator; + } + + protected NumberDatatype(Element element) { + formatPattern = element.attributeValue("format"); + decimalSeparator = element.attributeValue("decimalSeparator"); + groupingSeparator = element.attributeValue("groupingSeparator"); + } + + @Override + public Map getParameters() { + return ParamsMap.of( + "format", formatPattern, + "decimalSeparator", decimalSeparator, + "groupingSeparator", groupingSeparator); + } + + /** + * Creates non-localized format. + */ + protected NumberFormat createFormat() { + if (formatPattern != null) { + DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(); + + if (!StringUtils.isBlank(decimalSeparator)) + formatSymbols.setDecimalSeparator(decimalSeparator.charAt(0)); + + if (!StringUtils.isBlank(groupingSeparator)) + formatSymbols.setGroupingSeparator(groupingSeparator.charAt(0)); + + return new DecimalFormat(formatPattern, formatSymbols); + } else { + return NumberFormat.getNumberInstance(); + } + } + + protected Number parse(String value, NumberFormat format) throws ParseException { + ParsePosition pos = new ParsePosition(0); + Number res = format.parse(value.trim(), pos); + if (pos.getIndex() != value.length()) { + throw new ParseException( + String.format("Unparseable number: \"%s\"", value), + pos.getErrorIndex() + ); + } + return res; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/StringDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/StringDatatype.java index b8fdc3b8a0..c7c1e77812 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/StringDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/StringDatatype.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; - -import java.text.ParseException; -import java.util.Locale; - -@JavaClass(String.class) -public class StringDatatype implements Datatype { - - @Override - public String format(Object value) { - return value == null ? "" : (String) value; - } - - @Override - public String format(Object value, Locale locale) { - return format(value); - } - - @Override - public String parse(String value) { - return value; - } - - @Override - public String parse(String value, Locale locale) throws ParseException { - return value; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "string"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; + +import java.text.ParseException; +import java.util.Locale; + +@JavaClass(String.class) +public class StringDatatype implements Datatype { + + @Override + public String format(Object value) { + return value == null ? "" : (String) value; + } + + @Override + public String format(Object value, Locale locale) { + return format(value); + } + + @Override + public String parse(String value) { + return value; + } + + @Override + public String parse(String value, Locale locale) throws ParseException { + return value; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "string"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/TimeDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/TimeDatatype.java index fd4fc86f03..fc0abb4ccb 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/TimeDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/TimeDatatype.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.FormatStrings; -import com.haulmont.chile.core.datatypes.FormatStringsRegistry; -import com.haulmont.chile.core.datatypes.ParameterizedDatatype; -import com.haulmont.cuba.core.global.AppBeans; -import org.apache.commons.lang.StringUtils; -import org.dom4j.Element; - -import java.sql.Time; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -/** - * TimeDatatype works with java.sql.Time but is parametrized with java.util.Date - * to avoid problems with casting, e.g. org.apache.openjpa.util.java$util$Date$proxy. - */ -@JavaClass(Time.class) -public class TimeDatatype implements Datatype, ParameterizedDatatype { - - private String formatPattern; - - public TimeDatatype(Element element) { - formatPattern = element.attributeValue("format"); - } - - @Override - public String format(Object value) { - if (value == null) { - return ""; - } else { - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - } else { - format = DateFormat.getTimeInstance(); - } - format.setLenient(false); - return format.format(value); - } - } - - @Override - public String format(Object value, Locale locale) { - if (value == null) { - return ""; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return format(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getTimeFormat()); - format.setLenient(false); - - return format.format(value); - } - - @Override - public Date parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - DateFormat format; - if (formatPattern != null) { - format = new SimpleDateFormat(formatPattern); - } else { - format = DateFormat.getTimeInstance(); - } - - return format.parse(value.trim()); - } - - @Override - public Date parse(String value, Locale locale) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } - - FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); - if (formatStrings == null) { - return parse(value); - } - - DateFormat format = new SimpleDateFormat(formatStrings.getTimeFormat()); - return format.parse(value.trim()); - } - - @Override - public Map getParameters() { - return ParamsMap.of("format", formatPattern); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "time"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.FormatStrings; +import com.haulmont.chile.core.datatypes.FormatStringsRegistry; +import com.haulmont.chile.core.datatypes.ParameterizedDatatype; +import com.haulmont.cuba.core.global.AppBeans; +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; + +import java.sql.Time; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +/** + * TimeDatatype works with java.sql.Time but is parametrized with java.util.Date + * to avoid problems with casting, e.g. org.apache.openjpa.util.java$util$Date$proxy. + */ +@JavaClass(Time.class) +public class TimeDatatype implements Datatype, ParameterizedDatatype { + + private String formatPattern; + + public TimeDatatype(Element element) { + formatPattern = element.attributeValue("format"); + } + + @Override + public String format(Object value) { + if (value == null) { + return ""; + } else { + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + } else { + format = DateFormat.getTimeInstance(); + } + format.setLenient(false); + return format.format(value); + } + } + + @Override + public String format(Object value, Locale locale) { + if (value == null) { + return ""; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return format(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getTimeFormat()); + format.setLenient(false); + + return format.format(value); + } + + @Override + public Date parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + DateFormat format; + if (formatPattern != null) { + format = new SimpleDateFormat(formatPattern); + } else { + format = DateFormat.getTimeInstance(); + } + + return format.parse(value.trim()); + } + + @Override + public Date parse(String value, Locale locale) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } + + FormatStrings formatStrings = AppBeans.get(FormatStringsRegistry.class).getFormatStrings(locale); + if (formatStrings == null) { + return parse(value); + } + + DateFormat format = new SimpleDateFormat(formatStrings.getTimeFormat()); + return format.parse(value.trim()); + } + + @Override + public Map getParameters() { + return ParamsMap.of("format", formatPattern); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "time"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/datatypes/impl/UUIDDatatype.java b/modules/global/src/com/haulmont/chile/core/datatypes/impl/UUIDDatatype.java index 1d92f87c09..1879f1f51b 100644 --- a/modules/global/src/com/haulmont/chile/core/datatypes/impl/UUIDDatatype.java +++ b/modules/global/src/com/haulmont/chile/core/datatypes/impl/UUIDDatatype.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.datatypes.impl; - -import com.haulmont.chile.core.annotations.JavaClass; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.cuba.core.global.UuidProvider; -import org.apache.commons.lang.StringUtils; - -import java.text.ParseException; -import java.util.Locale; -import java.util.UUID; - -@JavaClass(UUID.class) -public class UUIDDatatype implements Datatype { - - @Override - public String format(Object value) { - return value == null ? "" : value.toString(); - } - - @Override - public String format(Object value, Locale locale) { - return format(value); - } - - @Override - public UUID parse(String value) throws ParseException { - if (StringUtils.isBlank(value)) { - return null; - } else { - try { - return UuidProvider.fromString(value.trim()); - } catch (Exception e) { - throw new ParseException("Error parsing UUID", 0); - } - } - } - - @Override - public UUID parse(String value, Locale locale) throws ParseException { - return parse(value); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - @Deprecated - public final static String NAME = "uuid"; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.datatypes.impl; + +import com.haulmont.chile.core.annotations.JavaClass; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.cuba.core.global.UuidProvider; +import org.apache.commons.lang.StringUtils; + +import java.text.ParseException; +import java.util.Locale; +import java.util.UUID; + +@JavaClass(UUID.class) +public class UUIDDatatype implements Datatype { + + @Override + public String format(Object value) { + return value == null ? "" : value.toString(); + } + + @Override + public String format(Object value, Locale locale) { + return format(value); + } + + @Override + public UUID parse(String value) throws ParseException { + if (StringUtils.isBlank(value)) { + return null; + } else { + try { + return UuidProvider.fromString(value.trim()); + } catch (Exception e) { + throw new ParseException("Error parsing UUID", 0); + } + } + } + + @Override + public UUID parse(String value, Locale locale) throws ParseException { + return parse(value); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + @Deprecated + public final static String NAME = "uuid"; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/Instance.java b/modules/global/src/com/haulmont/chile/core/model/Instance.java index c1d9a4e4c6..9d01619500 100644 --- a/modules/global/src/com/haulmont/chile/core/model/Instance.java +++ b/modules/global/src/com/haulmont/chile/core/model/Instance.java @@ -1,184 +1,184 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.model; - -import com.haulmont.chile.core.common.ValueListener; - -import javax.annotation.Nullable; -import java.io.Serializable; - -/** - * Interface to be implemented by data model objects. - */ -public interface Instance extends Serializable { - - /** - * @return metaclass of this object. Throws exception if the metaclass is not found. - */ - MetaClass getMetaClass(); - - /** - * @return Instance name as defined by {@link com.haulmont.chile.core.annotations.NamePattern} - * or {@code toString()}. - */ - String getInstanceName(); - - /** - * Get an attribute value. - * @param name attribute name according to JavaBeans notation - * @return attribute value - */ - @Nullable - T getValue(String name); - - /** - * Set an attribute value. - *
- * An implementor should first read a current value of the attribute, and then call an appropriate setter - * method only if the new value differs. This ensures triggering of {@link PropertyChangeListener}s only if the attribute - * was actually changed. - * - * @param name attribute name according to JavaBeans notation - * @param value attribute value - */ - void setValue(String name, Object value); - - /** - * Get an attribute value. Locates the attribute by the given path in object graph starting from this instance. - *
- * The path must consist of attribute names according to JavaBeans notation, separated by dots, e.g. - * {@code car.driver.name}. - * - * @param propertyPath path to an attribute - * @return attribute value. If any traversing attribute value is null or is not an {@link Instance}, this method - * stops here and returns this value. - */ - @Nullable - T getValueEx(String propertyPath); - - /** - * Set an attribute value. Locates the attribute by the given path in object graph starting from this instance. - *
The path must consist of attribute names according to JavaBeans notation, separated by dots, e.g. - * {@code car.driver.name}. - *
In the example above this method first gets value of {@code car.driver} attribute, and if it is not - * null and is an {@link Instance}, sets value of {@code name} attribute in it. If the value returned from - * {@code getValueEx("car.driver")} is null or is not an {@link Instance}, this method throws - * {@link IllegalStateException}. - *
An implementor should first read a current value of the attribute, and then call an appropriate setter - * method only if the new value differs. This ensures triggering of {@link PropertyChangeListener}s only if the attribute - * was actually changed. - * - * @param propertyPath path to an attribute - * @param value attribute value - */ - void setValueEx(String propertyPath, Object value); - - /** - * Add listener to track attributes changes. - * - * @deprecated Use {@link #addPropertyChangeListener(PropertyChangeListener)} - * @param listener listener - */ - @Deprecated - void addListener(ValueListener listener); - - /** - * Remove listener. - * - * @deprecated User {@link #removePropertyChangeListener(PropertyChangeListener)} - * @param listener listener to remove - */ - @Deprecated - void removeListener(ValueListener listener); - - /** - * Add listener to track attributes changes. - * @param listener listener - */ - void addPropertyChangeListener(PropertyChangeListener listener); - - /** - * Remove listener. - * @param listener listener to remove - */ - void removePropertyChangeListener(PropertyChangeListener listener); - - /** - * Remove all {@link PropertyChangeListener}s. - */ - void removeAllListeners(); - - /** - * Event object for {@link com.haulmont.chile.core.model.Instance.PropertyChangeListener}. - */ - class PropertyChangeEvent { - private final Instance item; - private final String property; - private final Object prevValue; - private final Object value; - - public PropertyChangeEvent(Instance item, String property, Object prevValue, Object value) { - this.item = item; - this.property = property; - this.prevValue = prevValue; - this.value = value; - } - - /** - * @return property name - */ - public String getProperty() { - return property; - } - - /** - * @return data model object - */ - public Instance getItem() { - return item; - } - - /** - * @return previous value of property - */ - @Nullable - public Object getPrevValue() { - return prevValue; - } - - /** - * @return current value of property - */ - @Nullable - public Object getValue() { - return value; - } - } - - /** - * Interface to track changes in data model objects. - */ - @FunctionalInterface - interface PropertyChangeListener { - /** - * Called when value of instance property changed. - * - * @param e event object - */ - void propertyChanged(PropertyChangeEvent e); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.model; + +import com.haulmont.chile.core.common.ValueListener; + +import javax.annotation.Nullable; +import java.io.Serializable; + +/** + * Interface to be implemented by data model objects. + */ +public interface Instance extends Serializable { + + /** + * @return metaclass of this object. Throws exception if the metaclass is not found. + */ + MetaClass getMetaClass(); + + /** + * @return Instance name as defined by {@link com.haulmont.chile.core.annotations.NamePattern} + * or {@code toString()}. + */ + String getInstanceName(); + + /** + * Get an attribute value. + * @param name attribute name according to JavaBeans notation + * @return attribute value + */ + @Nullable + T getValue(String name); + + /** + * Set an attribute value. + *
+ * An implementor should first read a current value of the attribute, and then call an appropriate setter + * method only if the new value differs. This ensures triggering of {@link PropertyChangeListener}s only if the attribute + * was actually changed. + * + * @param name attribute name according to JavaBeans notation + * @param value attribute value + */ + void setValue(String name, Object value); + + /** + * Get an attribute value. Locates the attribute by the given path in object graph starting from this instance. + *
+ * The path must consist of attribute names according to JavaBeans notation, separated by dots, e.g. + * {@code car.driver.name}. + * + * @param propertyPath path to an attribute + * @return attribute value. If any traversing attribute value is null or is not an {@link Instance}, this method + * stops here and returns this value. + */ + @Nullable + T getValueEx(String propertyPath); + + /** + * Set an attribute value. Locates the attribute by the given path in object graph starting from this instance. + *
The path must consist of attribute names according to JavaBeans notation, separated by dots, e.g. + * {@code car.driver.name}. + *
In the example above this method first gets value of {@code car.driver} attribute, and if it is not + * null and is an {@link Instance}, sets value of {@code name} attribute in it. If the value returned from + * {@code getValueEx("car.driver")} is null or is not an {@link Instance}, this method throws + * {@link IllegalStateException}. + *
An implementor should first read a current value of the attribute, and then call an appropriate setter + * method only if the new value differs. This ensures triggering of {@link PropertyChangeListener}s only if the attribute + * was actually changed. + * + * @param propertyPath path to an attribute + * @param value attribute value + */ + void setValueEx(String propertyPath, Object value); + + /** + * Add listener to track attributes changes. + * + * @deprecated Use {@link #addPropertyChangeListener(PropertyChangeListener)} + * @param listener listener + */ + @Deprecated + void addListener(ValueListener listener); + + /** + * Remove listener. + * + * @deprecated User {@link #removePropertyChangeListener(PropertyChangeListener)} + * @param listener listener to remove + */ + @Deprecated + void removeListener(ValueListener listener); + + /** + * Add listener to track attributes changes. + * @param listener listener + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Remove listener. + * @param listener listener to remove + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Remove all {@link PropertyChangeListener}s. + */ + void removeAllListeners(); + + /** + * Event object for {@link com.haulmont.chile.core.model.Instance.PropertyChangeListener}. + */ + class PropertyChangeEvent { + private final Instance item; + private final String property; + private final Object prevValue; + private final Object value; + + public PropertyChangeEvent(Instance item, String property, Object prevValue, Object value) { + this.item = item; + this.property = property; + this.prevValue = prevValue; + this.value = value; + } + + /** + * @return property name + */ + public String getProperty() { + return property; + } + + /** + * @return data model object + */ + public Instance getItem() { + return item; + } + + /** + * @return previous value of property + */ + @Nullable + public Object getPrevValue() { + return prevValue; + } + + /** + * @return current value of property + */ + @Nullable + public Object getValue() { + return value; + } + } + + /** + * Interface to track changes in data model objects. + */ + @FunctionalInterface + interface PropertyChangeListener { + /** + * Called when value of instance property changed. + * + * @param e event object + */ + void propertyChanged(PropertyChangeEvent e); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/MetaClass.java b/modules/global/src/com/haulmont/chile/core/model/MetaClass.java index 7dd21f041e..ce0b652e19 100644 --- a/modules/global/src/com/haulmont/chile/core/model/MetaClass.java +++ b/modules/global/src/com/haulmont/chile/core/model/MetaClass.java @@ -1,88 +1,88 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.List; - -/** - * Metadata object representing an entity. - * - */ -public interface MetaClass extends MetadataObject { - - /** - * @return containing MetaModel instance. Null signifies a temporary metaclass, not associated with an entity class. - * - */ - @Nullable - MetaModel getModel(); - - /** - * @return corresponding Java class - */ - Class getJavaClass(); - - /** - * Immediate ancestor of the object, or null if there is no one. - */ - @Nullable - MetaClass getAncestor(); - - /** - * All ancestors of the metaclass, in order going up from the immediate ancestor. - */ - List getAncestors(); - - /** - * All descendants of the metaclass, recursively. Order is undefined. - */ - Collection getDescendants(); - - /** - * Get MetaProperty by its name. - * @return MetaProperty instance, or null if no such property found - */ - @Nullable - MetaProperty getProperty(String name); - - /** - * Get MetaProperty by its name. - * @return MetaProperty instance. Throws exception if not found. - */ - MetaProperty getPropertyNN(String name); - - /** - * Returns MetaPropertyPath object, representing path to the property from the current class - * @param propertyPath dot-separated string - * @return MetaPropertyPath instance, or null if the input parameter doesn't represent a valid path. - */ - @Nullable - MetaPropertyPath getPropertyPath(String propertyPath); - - /** - * @return collection of meta properties directly owned by this metaclass. - */ - Collection getOwnProperties(); - - /** - * @return collection of meta properties owned by this metaclass and all its ancestors. - */ - Collection getProperties(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; + +/** + * Metadata object representing an entity. + * + */ +public interface MetaClass extends MetadataObject { + + /** + * @return containing MetaModel instance. Null signifies a temporary metaclass, not associated with an entity class. + * + */ + @Nullable + MetaModel getModel(); + + /** + * @return corresponding Java class + */ + Class getJavaClass(); + + /** + * Immediate ancestor of the object, or null if there is no one. + */ + @Nullable + MetaClass getAncestor(); + + /** + * All ancestors of the metaclass, in order going up from the immediate ancestor. + */ + List getAncestors(); + + /** + * All descendants of the metaclass, recursively. Order is undefined. + */ + Collection getDescendants(); + + /** + * Get MetaProperty by its name. + * @return MetaProperty instance, or null if no such property found + */ + @Nullable + MetaProperty getProperty(String name); + + /** + * Get MetaProperty by its name. + * @return MetaProperty instance. Throws exception if not found. + */ + MetaProperty getPropertyNN(String name); + + /** + * Returns MetaPropertyPath object, representing path to the property from the current class + * @param propertyPath dot-separated string + * @return MetaPropertyPath instance, or null if the input parameter doesn't represent a valid path. + */ + @Nullable + MetaPropertyPath getPropertyPath(String propertyPath); + + /** + * @return collection of meta properties directly owned by this metaclass. + */ + Collection getOwnProperties(); + + /** + * @return collection of meta properties owned by this metaclass and all its ancestors. + */ + Collection getProperties(); +} diff --git a/modules/global/src/com/haulmont/chile/core/model/MetaModel.java b/modules/global/src/com/haulmont/chile/core/model/MetaModel.java index 299bb50566..c08bb4cbf6 100644 --- a/modules/global/src/com/haulmont/chile/core/model/MetaModel.java +++ b/modules/global/src/com/haulmont/chile/core/model/MetaModel.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import java.util.Collection; - -/** - * Container and entry point for metadata objects - * - */ -public interface MetaModel extends MetadataObject { - - /** - * Get MetaClass by its unique name - * @return MetaClass instance, null if not found - */ - MetaClass getClass(String name); - - /** - * Get MetaClass by corresponding entity's Java class - * @return MetaClass instance, null if not found - */ - MetaClass getClass(Class clazz); - - /** - * All metaclasses - */ - Collection getClasses(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import java.util.Collection; + +/** + * Container and entry point for metadata objects + * + */ +public interface MetaModel extends MetadataObject { + + /** + * Get MetaClass by its unique name + * @return MetaClass instance, null if not found + */ + MetaClass getClass(String name); + + /** + * Get MetaClass by corresponding entity's Java class + * @return MetaClass instance, null if not found + */ + MetaClass getClass(Class clazz); + + /** + * All metaclasses + */ + Collection getClasses(); +} diff --git a/modules/global/src/com/haulmont/chile/core/model/MetaProperty.java b/modules/global/src/com/haulmont/chile/core/model/MetaProperty.java index 7605ad33de..f4474e286c 100644 --- a/modules/global/src/com/haulmont/chile/core/model/MetaProperty.java +++ b/modules/global/src/com/haulmont/chile/core/model/MetaProperty.java @@ -1,102 +1,102 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import javax.annotation.Nullable; -import java.lang.reflect.AnnotatedElement; - -/** - * Metadata object representing an entity attribute. - */ -public interface MetaProperty extends MetadataObject { - - /** - * Property type - */ - enum Type { - - /** Simple value type, e.g. String, Number */ - DATATYPE, - - /** Enumeration */ - ENUM, - - /** Reference type. Attribute of this type contains a related entity. */ - ASSOCIATION, - - /** - * Reference type. Attribute of this type contains a related entity. - * Composition implies ownership, that is the referenced object exists only as part of the owning entity. - */ - COMPOSITION - } - - /** - * @return containing MetaModel instance. Null signifies a temporary metaclass, not associated with an entity class. - */ - @Nullable - MetaModel getModel(); - - /** - * @return MetaClass, containing this MetaProperty.
- * In case of {@link com.haulmont.cuba.core.entity.annotation.Extends} returns extended meta class. - */ - MetaClass getDomain(); - - /** - * @return Range of this property. - */ - Range getRange(); - - /** - * @return property type (DATATYPE, ENUM, ASSOCIATION, COMPOSITION) - */ - Type getType(); - - /** - * @return true if the corresponding entity attribute must contain a value - */ - boolean isMandatory(); - - /** - * @return true if the corresponding entity attribute is read-only - */ - boolean isReadOnly(); - - /** - * @return a MetaProperty from the opposite side of relation, or null if this is not a reference property - */ - @Nullable - MetaProperty getInverse(); - - /** - * @return corresponding Java field or method as AnnotatedElement object - */ - AnnotatedElement getAnnotatedElement(); - - /** - * @return Java class of the corresponding field or method's return type - */ - Class getJavaType(); - - /** - * @return Java class which declares the corresponding field or method - */ - @Nullable - Class getDeclaringClass(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import javax.annotation.Nullable; +import java.lang.reflect.AnnotatedElement; + +/** + * Metadata object representing an entity attribute. + */ +public interface MetaProperty extends MetadataObject { + + /** + * Property type + */ + enum Type { + + /** Simple value type, e.g. String, Number */ + DATATYPE, + + /** Enumeration */ + ENUM, + + /** Reference type. Attribute of this type contains a related entity. */ + ASSOCIATION, + + /** + * Reference type. Attribute of this type contains a related entity. + * Composition implies ownership, that is the referenced object exists only as part of the owning entity. + */ + COMPOSITION + } + + /** + * @return containing MetaModel instance. Null signifies a temporary metaclass, not associated with an entity class. + */ + @Nullable + MetaModel getModel(); + + /** + * @return MetaClass, containing this MetaProperty.
+ * In case of {@link com.haulmont.cuba.core.entity.annotation.Extends} returns extended meta class. + */ + MetaClass getDomain(); + + /** + * @return Range of this property. + */ + Range getRange(); + + /** + * @return property type (DATATYPE, ENUM, ASSOCIATION, COMPOSITION) + */ + Type getType(); + + /** + * @return true if the corresponding entity attribute must contain a value + */ + boolean isMandatory(); + + /** + * @return true if the corresponding entity attribute is read-only + */ + boolean isReadOnly(); + + /** + * @return a MetaProperty from the opposite side of relation, or null if this is not a reference property + */ + @Nullable + MetaProperty getInverse(); + + /** + * @return corresponding Java field or method as AnnotatedElement object + */ + AnnotatedElement getAnnotatedElement(); + + /** + * @return Java class of the corresponding field or method's return type + */ + Class getJavaType(); + + /** + * @return Java class which declares the corresponding field or method + */ + @Nullable + Class getDeclaringClass(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/MetaPropertyPath.java b/modules/global/src/com/haulmont/chile/core/model/MetaPropertyPath.java index e34121143d..9d04a1bf67 100644 --- a/modules/global/src/com/haulmont/chile/core/model/MetaPropertyPath.java +++ b/modules/global/src/com/haulmont/chile/core/model/MetaPropertyPath.java @@ -1,152 +1,152 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import org.apache.commons.lang.text.StrBuilder; - -import java.io.Serializable; -import java.util.Arrays; - -/** - * Object representing a relative path to a property from certain MetaClass - * - */ -public class MetaPropertyPath implements Serializable { - - private static final long serialVersionUID = -3149651267513333787L; - - private MetaClass metaClass; - private MetaProperty[] metaProperties; - private String[] path; - - public MetaPropertyPath(MetaClass metaClass, MetaProperty... metaProperties) { - this.metaClass = metaClass; - this.metaProperties = metaProperties; - - this.path = new String[metaProperties.length]; - for (int i = 0; i < metaProperties.length; i++) { - path[i] = metaProperties[i].getName(); - } - } - - public MetaPropertyPath(MetaPropertyPath parentPath, MetaProperty... addProperties) { - this.metaClass = parentPath.getMetaClass(); - - this.metaProperties = new MetaProperty[parentPath.metaProperties.length + addProperties.length]; - System.arraycopy(parentPath.metaProperties, 0, this.metaProperties, 0, parentPath.metaProperties.length); - System.arraycopy(addProperties, 0, this.metaProperties, parentPath.metaProperties.length, addProperties.length); - - this.path = new String[this.metaProperties.length]; - for (int i = 0; i < this.metaProperties.length; i++) { - this.path[i] = this.metaProperties[i].getName(); - } - } - - /** - * MetaClass which is the path origin - */ - public MetaClass getMetaClass() { - return metaClass; - } - - /** - * Array of MetaProperties between the originating MetaClass and target MetaProperty - */ - public MetaProperty[] getMetaProperties() { - return metaProperties; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MetaPropertyPath that = (MetaPropertyPath) o; - - if (!metaClass.equals(that.metaClass)) return false; - if (!Arrays.equals(metaProperties, that.metaProperties)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = metaClass.hashCode(); - result = 31 * result + Arrays.hashCode(metaProperties); - return result; - } - - /** - * Range of the target MetaProperty - */ - public Range getRange() { - return metaProperties[metaProperties.length - 1].getRange(); - } - - /** - * Java class of the target MetaProperty range - */ - public Class getRangeJavaClass() { - if (metaProperties.length < 1) { - throw new RuntimeException("Empty property path at metaclass " + metaClass.getName() + " - possibly wrong property name"); - } - return getTypeClass(metaProperties[metaProperties.length - 1]); - } - - /** - * Path as String array - */ - public String[] getPath() { - return path; - } - - /** - * Target MetaProperty - */ - public MetaProperty getMetaProperty() { - return metaProperties[metaProperties.length - 1]; - } - - /** - * Tests if this path is a nested property of the given path. - */ - public boolean startsWith(MetaPropertyPath other) { - if (other.getPath().length > path.length) - return false; - MetaProperty[] subarray = Arrays.copyOf(this.metaProperties, other.getMetaProperties().length); - return Arrays.equals(subarray, other.metaProperties); - } - - @Override - public String toString() { - return new StrBuilder().appendWithSeparators(path, ".").toString(); - } - - private Class getTypeClass(MetaProperty metaProperty) { - Range range = metaProperty.getRange(); - if (range.isDatatype()) { - return range.asDatatype().getJavaClass(); - } else if (range.isClass()) { - return range.asClass().getJavaClass(); - } else if (range.isEnum()) { - return range.asEnumeration().getJavaClass(); - } else { - throw new UnsupportedOperationException(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import org.apache.commons.lang.text.StrBuilder; + +import java.io.Serializable; +import java.util.Arrays; + +/** + * Object representing a relative path to a property from certain MetaClass + * + */ +public class MetaPropertyPath implements Serializable { + + private static final long serialVersionUID = -3149651267513333787L; + + private MetaClass metaClass; + private MetaProperty[] metaProperties; + private String[] path; + + public MetaPropertyPath(MetaClass metaClass, MetaProperty... metaProperties) { + this.metaClass = metaClass; + this.metaProperties = metaProperties; + + this.path = new String[metaProperties.length]; + for (int i = 0; i < metaProperties.length; i++) { + path[i] = metaProperties[i].getName(); + } + } + + public MetaPropertyPath(MetaPropertyPath parentPath, MetaProperty... addProperties) { + this.metaClass = parentPath.getMetaClass(); + + this.metaProperties = new MetaProperty[parentPath.metaProperties.length + addProperties.length]; + System.arraycopy(parentPath.metaProperties, 0, this.metaProperties, 0, parentPath.metaProperties.length); + System.arraycopy(addProperties, 0, this.metaProperties, parentPath.metaProperties.length, addProperties.length); + + this.path = new String[this.metaProperties.length]; + for (int i = 0; i < this.metaProperties.length; i++) { + this.path[i] = this.metaProperties[i].getName(); + } + } + + /** + * MetaClass which is the path origin + */ + public MetaClass getMetaClass() { + return metaClass; + } + + /** + * Array of MetaProperties between the originating MetaClass and target MetaProperty + */ + public MetaProperty[] getMetaProperties() { + return metaProperties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MetaPropertyPath that = (MetaPropertyPath) o; + + if (!metaClass.equals(that.metaClass)) return false; + if (!Arrays.equals(metaProperties, that.metaProperties)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = metaClass.hashCode(); + result = 31 * result + Arrays.hashCode(metaProperties); + return result; + } + + /** + * Range of the target MetaProperty + */ + public Range getRange() { + return metaProperties[metaProperties.length - 1].getRange(); + } + + /** + * Java class of the target MetaProperty range + */ + public Class getRangeJavaClass() { + if (metaProperties.length < 1) { + throw new RuntimeException("Empty property path at metaclass " + metaClass.getName() + " - possibly wrong property name"); + } + return getTypeClass(metaProperties[metaProperties.length - 1]); + } + + /** + * Path as String array + */ + public String[] getPath() { + return path; + } + + /** + * Target MetaProperty + */ + public MetaProperty getMetaProperty() { + return metaProperties[metaProperties.length - 1]; + } + + /** + * Tests if this path is a nested property of the given path. + */ + public boolean startsWith(MetaPropertyPath other) { + if (other.getPath().length > path.length) + return false; + MetaProperty[] subarray = Arrays.copyOf(this.metaProperties, other.getMetaProperties().length); + return Arrays.equals(subarray, other.metaProperties); + } + + @Override + public String toString() { + return new StrBuilder().appendWithSeparators(path, ".").toString(); + } + + private Class getTypeClass(MetaProperty metaProperty) { + Range range = metaProperty.getRange(); + if (range.isDatatype()) { + return range.asDatatype().getJavaClass(); + } else if (range.isClass()) { + return range.asClass().getJavaClass(); + } else if (range.isEnum()) { + return range.asEnumeration().getJavaClass(); + } else { + throw new UnsupportedOperationException(); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/MetadataObject.java b/modules/global/src/com/haulmont/chile/core/model/MetadataObject.java index 5bcb6460c6..3bfb2437e0 100644 --- a/modules/global/src/com/haulmont/chile/core/model/MetadataObject.java +++ b/modules/global/src/com/haulmont/chile/core/model/MetadataObject.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import java.util.Map; - -/** - * Ancestor of main metadata objects: {@link com.haulmont.chile.core.model.MetaClass} and {@link com.haulmont.chile.core.model.MetaProperty} - * - */ -public interface MetadataObject { - - /** - * MetadataObject unique name. - */ - String getName(); - - /** - * MetadataObject annotations. Annotations here are simply name-value pairs, not directly correlated with Java annotations. - */ - Map getAnnotations(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import java.util.Map; + +/** + * Ancestor of main metadata objects: {@link com.haulmont.chile.core.model.MetaClass} and {@link com.haulmont.chile.core.model.MetaProperty} + * + */ +public interface MetadataObject { + + /** + * MetadataObject unique name. + */ + String getName(); + + /** + * MetadataObject annotations. Annotations here are simply name-value pairs, not directly correlated with Java annotations. + */ + Map getAnnotations(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/Range.java b/modules/global/src/com/haulmont/chile/core/model/Range.java index aba51a3431..d7030f056e 100644 --- a/modules/global/src/com/haulmont/chile/core/model/Range.java +++ b/modules/global/src/com/haulmont/chile/core/model/Range.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Enumeration; - -/** - * Object encapsulating common properties of {@link MetaProperty}. - * - */ -public interface Range { - - /** Is this property of a simple type? */ - boolean isDatatype(); - - /** Is this property a reference? */ - boolean isClass(); - - /** Is this property an enumeration? */ - boolean isEnum(); - - /** Get this property Datatype. Throws IllegalStateException if this property is not of a simple type. */ - Datatype asDatatype(); - - /** Get this property Enumeration. Throws IllegalStateException if this property is not an enumeration. */ - Enumeration asEnumeration(); - - /** Get this property MetaClass. Throws IllegalStateException if this property is not a reference. */ - MetaClass asClass(); - - /** Is this property ordered? True for ordered collections. */ - boolean isOrdered(); - - /** Relation type for reference property */ - enum Cardinality { - NONE, - ONE_TO_ONE, - MANY_TO_ONE, - ONE_TO_MANY, - MANY_TO_MANY; - - public boolean isMany() { - return equals(ONE_TO_MANY) || equals(MANY_TO_MANY); - } - } - - /** Get relation type for this property if it is a reference. */ - Cardinality getCardinality(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Enumeration; + +/** + * Object encapsulating common properties of {@link MetaProperty}. + * + */ +public interface Range { + + /** Is this property of a simple type? */ + boolean isDatatype(); + + /** Is this property a reference? */ + boolean isClass(); + + /** Is this property an enumeration? */ + boolean isEnum(); + + /** Get this property Datatype. Throws IllegalStateException if this property is not of a simple type. */ + Datatype asDatatype(); + + /** Get this property Enumeration. Throws IllegalStateException if this property is not an enumeration. */ + Enumeration asEnumeration(); + + /** Get this property MetaClass. Throws IllegalStateException if this property is not a reference. */ + MetaClass asClass(); + + /** Is this property ordered? True for ordered collections. */ + boolean isOrdered(); + + /** Relation type for reference property */ + enum Cardinality { + NONE, + ONE_TO_ONE, + MANY_TO_ONE, + ONE_TO_MANY, + MANY_TO_MANY; + + public boolean isMany() { + return equals(ONE_TO_MANY) || equals(MANY_TO_MANY); + } + } + + /** Get relation type for this property if it is a reference. */ + Cardinality getCardinality(); +} diff --git a/modules/global/src/com/haulmont/chile/core/model/Session.java b/modules/global/src/com/haulmont/chile/core/model/Session.java index db21bf23fd..8316616987 100644 --- a/modules/global/src/com/haulmont/chile/core/model/Session.java +++ b/modules/global/src/com/haulmont/chile/core/model/Session.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model; - -import javax.annotation.Nullable; -import java.util.Collection; - -/** - * Metadata model entry point. - *
Metadata consists of a set of interrelated {@link MetaClass} instances. - *
The whole metadata is split into named models. One can obtain {@link MetaClass} instances through the - * {@link MetaModel} references or directly from the Session. - */ -public interface Session { - - MetaModel getModel(String name); - - Collection getModels(); - - /** - * Search MetaClass by its name in the whole metamodel. - * @param name entity name - * @return MetaClass instance or null if not found - */ - @Nullable - MetaClass getClass(String name); - - /** - * Search MetaClass by its name in the whole metamodel. - * @param name entity name - * @return MetaClass instance. Throws exception if not found. - */ - MetaClass getClassNN(String name); - - /** - * Search MetaClass by the corresponding Java class in the whole metamodel. - * @param clazz Java class defining the entity - * @return MetaClass instance or null if not found - */ - @Nullable - MetaClass getClass(Class clazz); - - /** - * Search MetaClass by the corresponding Java class in the whole metamodel. - * @param clazz Java class defining the entity - * @return MetaClass instance. Throws exception if not found. - */ - MetaClass getClassNN(Class clazz); - - /** - * @return collection of all MetaClasses in the whole metamodel - */ - Collection getClasses(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model; + +import javax.annotation.Nullable; +import java.util.Collection; + +/** + * Metadata model entry point. + *
Metadata consists of a set of interrelated {@link MetaClass} instances. + *
The whole metadata is split into named models. One can obtain {@link MetaClass} instances through the + * {@link MetaModel} references or directly from the Session. + */ +public interface Session { + + MetaModel getModel(String name); + + Collection getModels(); + + /** + * Search MetaClass by its name in the whole metamodel. + * @param name entity name + * @return MetaClass instance or null if not found + */ + @Nullable + MetaClass getClass(String name); + + /** + * Search MetaClass by its name in the whole metamodel. + * @param name entity name + * @return MetaClass instance. Throws exception if not found. + */ + MetaClass getClassNN(String name); + + /** + * Search MetaClass by the corresponding Java class in the whole metamodel. + * @param clazz Java class defining the entity + * @return MetaClass instance or null if not found + */ + @Nullable + MetaClass getClass(Class clazz); + + /** + * Search MetaClass by the corresponding Java class in the whole metamodel. + * @param clazz Java class defining the entity + * @return MetaClass instance. Throws exception if not found. + */ + MetaClass getClassNN(Class clazz); + + /** + * @return collection of all MetaClasses in the whole metamodel + */ + Collection getClasses(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/AbstractInstance.java b/modules/global/src/com/haulmont/chile/core/model/impl/AbstractInstance.java index 48ccf0347a..243671df7e 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/AbstractInstance.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/AbstractInstance.java @@ -1,146 +1,146 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.common.ValueListener; -import com.haulmont.chile.core.common.compatibility.InstancePropertyChangeListenerWrapper; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.chile.core.model.utils.MethodsCache; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class AbstractInstance implements Instance { - - protected static final int PROPERTY_CHANGE_LISTENERS_INITIAL_CAPACITY = 4; - - protected transient Collection> __propertyChangeListeners; - - private static transient Map methodCacheMap = new ConcurrentHashMap<>(); - - protected void propertyChanged(String s, Object prev, Object curr) { - if (__propertyChangeListeners != null) { - for (Object referenceObject : __propertyChangeListeners.toArray()) { - @SuppressWarnings("unchecked") - WeakReference reference = (WeakReference) referenceObject; - - PropertyChangeListener listener = reference.get(); - if (listener == null) { - __propertyChangeListeners.remove(reference); - } else { - listener.propertyChanged(new PropertyChangeEvent(this, s, prev, curr)); - } - } - } - } - - @Override - public String getInstanceName() { - return InstanceUtils.getInstanceName(this); - } - - @Override - public void addListener(ValueListener listener) { - addPropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener)); - } - - @Override - public void removeListener(ValueListener listener) { - removePropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener)); - } - - @Override - public void addPropertyChangeListener(PropertyChangeListener listener) { - if (__propertyChangeListeners == null) { - __propertyChangeListeners = new ArrayList<>(PROPERTY_CHANGE_LISTENERS_INITIAL_CAPACITY); - } - __propertyChangeListeners.add(new WeakReference<>(listener)); - } - - @Override - public void removePropertyChangeListener(PropertyChangeListener listener) { - if (__propertyChangeListeners != null) { - for (Iterator> it = __propertyChangeListeners.iterator(); it.hasNext(); ) { - PropertyChangeListener iteratorListener = it.next().get(); - if (iteratorListener == null || iteratorListener.equals(listener)) { - it.remove(); - } - } - } - } - - @Override - public void removeAllListeners() { - if (__propertyChangeListeners != null) { - __propertyChangeListeners.clear(); - } - } - - @SuppressWarnings("unchecked") - @Override - public T getValue(String name) { - return (T) getMethodsCache().invokeGetter(this, name); - } - - protected MethodsCache getMethodsCache() { - Class cls = getClass(); - MethodsCache cache = methodCacheMap.get(cls); - if (cache == null) { - cache = new MethodsCache(cls); - methodCacheMap.put(cls, cache); - } - return cache; - } - - @Override - public void setValue(String name, Object value) { - setValue(name, value, true); - } - - /** - * Set value to property in instance - * - * For internal use only. Use {@link #setValue(String, Object)} - * - * @param name property name - * @param value value - * @param checkEquals check equals for previous and new value. - * If flag is true and objects equals, then setter will not be invoked - */ - public void setValue(String name, Object value, boolean checkEquals) { - Object oldValue = getValue(name); - if ((!checkEquals) || (!InstanceUtils.propertyValueEquals(oldValue, value))) { - getMethodsCache().invokeSetter(this, name, value); - } - } - - @Override - public T getValueEx(String name) { - return InstanceUtils.getValueEx(this, name); - } - - @Override - public void setValueEx(String name, Object value) { - InstanceUtils.setValueEx(this, name, value); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.common.ValueListener; +import com.haulmont.chile.core.common.compatibility.InstancePropertyChangeListenerWrapper; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.chile.core.model.utils.MethodsCache; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class AbstractInstance implements Instance { + + protected static final int PROPERTY_CHANGE_LISTENERS_INITIAL_CAPACITY = 4; + + protected transient Collection> __propertyChangeListeners; + + private static transient Map methodCacheMap = new ConcurrentHashMap<>(); + + protected void propertyChanged(String s, Object prev, Object curr) { + if (__propertyChangeListeners != null) { + for (Object referenceObject : __propertyChangeListeners.toArray()) { + @SuppressWarnings("unchecked") + WeakReference reference = (WeakReference) referenceObject; + + PropertyChangeListener listener = reference.get(); + if (listener == null) { + __propertyChangeListeners.remove(reference); + } else { + listener.propertyChanged(new PropertyChangeEvent(this, s, prev, curr)); + } + } + } + } + + @Override + public String getInstanceName() { + return InstanceUtils.getInstanceName(this); + } + + @Override + public void addListener(ValueListener listener) { + addPropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener)); + } + + @Override + public void removeListener(ValueListener listener) { + removePropertyChangeListener(new InstancePropertyChangeListenerWrapper(listener)); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + if (__propertyChangeListeners == null) { + __propertyChangeListeners = new ArrayList<>(PROPERTY_CHANGE_LISTENERS_INITIAL_CAPACITY); + } + __propertyChangeListeners.add(new WeakReference<>(listener)); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + if (__propertyChangeListeners != null) { + for (Iterator> it = __propertyChangeListeners.iterator(); it.hasNext(); ) { + PropertyChangeListener iteratorListener = it.next().get(); + if (iteratorListener == null || iteratorListener.equals(listener)) { + it.remove(); + } + } + } + } + + @Override + public void removeAllListeners() { + if (__propertyChangeListeners != null) { + __propertyChangeListeners.clear(); + } + } + + @SuppressWarnings("unchecked") + @Override + public T getValue(String name) { + return (T) getMethodsCache().invokeGetter(this, name); + } + + protected MethodsCache getMethodsCache() { + Class cls = getClass(); + MethodsCache cache = methodCacheMap.get(cls); + if (cache == null) { + cache = new MethodsCache(cls); + methodCacheMap.put(cls, cache); + } + return cache; + } + + @Override + public void setValue(String name, Object value) { + setValue(name, value, true); + } + + /** + * Set value to property in instance + * + * For internal use only. Use {@link #setValue(String, Object)} + * + * @param name property name + * @param value value + * @param checkEquals check equals for previous and new value. + * If flag is true and objects equals, then setter will not be invoked + */ + public void setValue(String name, Object value, boolean checkEquals) { + Object oldValue = getValue(name); + if ((!checkEquals) || (!InstanceUtils.propertyValueEquals(oldValue, value))) { + getMethodsCache().invokeSetter(this, name, value); + } + } + + @Override + public T getValueEx(String name) { + return InstanceUtils.getValueEx(this, name); + } + + @Override + public void setValueEx(String name, Object value) { + InstanceUtils.setValueEx(this, name, value); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/AbstractRange.java b/modules/global/src/com/haulmont/chile/core/model/impl/AbstractRange.java index 07b046b8af..52da2df242 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/AbstractRange.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/AbstractRange.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.model.Range; - -public abstract class AbstractRange implements Range { - - private Cardinality cardinality = Cardinality.NONE; - private boolean ordered; - - public AbstractRange() { - super(); - } - - @Override - public Cardinality getCardinality() { - return cardinality; - } - - @Override - public boolean isOrdered() { - return ordered; - } - - public void setCardinality(Cardinality cardinality) { - this.cardinality = cardinality; - } - - public void setOrdered(boolean ordered) { - this.ordered = ordered; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.model.Range; + +public abstract class AbstractRange implements Range { + + private Cardinality cardinality = Cardinality.NONE; + private boolean ordered; + + public AbstractRange() { + super(); + } + + @Override + public Cardinality getCardinality() { + return cardinality; + } + + @Override + public boolean isOrdered() { + return ordered; + } + + public void setCardinality(Cardinality cardinality) { + this.cardinality = cardinality; + } + + public void setOrdered(boolean ordered) { + this.ordered = ordered; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/ClassRange.java b/modules/global/src/com/haulmont/chile/core/model/impl/ClassRange.java index 3af4050772..74bb481af4 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/ClassRange.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/ClassRange.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.Range; - -public class ClassRange extends AbstractRange implements Range { - private final MetaClass metaClass; - - public ClassRange(MetaClass metaClass) { - this.metaClass = metaClass; - } - - @Override - public MetaClass asClass() { - return metaClass; - } - - @Override - public Datatype asDatatype() { - throw new IllegalStateException("Range is class"); - } - - @Override - public Enumeration asEnumeration() { - throw new IllegalStateException("Range is class"); - } - - @Override - public boolean isClass() { - return true; - } - - @Override - public boolean isDatatype() { - return false; - } - - @Override - public boolean isEnum() { - return false; - } - - @Override - public String toString() { - return "Range{metaClass=" + metaClass + "}"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.Range; + +public class ClassRange extends AbstractRange implements Range { + private final MetaClass metaClass; + + public ClassRange(MetaClass metaClass) { + this.metaClass = metaClass; + } + + @Override + public MetaClass asClass() { + return metaClass; + } + + @Override + public Datatype asDatatype() { + throw new IllegalStateException("Range is class"); + } + + @Override + public Enumeration asEnumeration() { + throw new IllegalStateException("Range is class"); + } + + @Override + public boolean isClass() { + return true; + } + + @Override + public boolean isDatatype() { + return false; + } + + @Override + public boolean isEnum() { + return false; + } + + @Override + public String toString() { + return "Range{metaClass=" + metaClass + "}"; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/DatatypeRange.java b/modules/global/src/com/haulmont/chile/core/model/impl/DatatypeRange.java index 5dc3bbddb6..9764063772 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/DatatypeRange.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/DatatypeRange.java @@ -1,67 +1,67 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.Range; - -public class DatatypeRange extends AbstractRange implements Range { - - private final Datatype datatype; - - public DatatypeRange(Datatype datatype) { - this.datatype = datatype; - } - - @Override - public MetaClass asClass() { - throw new IllegalStateException("Range is datatype"); - } - - @Override - public Datatype asDatatype() { - return datatype; - } - - @Override - public Enumeration asEnumeration() { - throw new IllegalStateException("Range is datatype"); - } - - @Override - public boolean isClass() { - return false; - } - - @Override - public boolean isDatatype() { - return true; - } - - @Override - public boolean isEnum() { - return false; - } - - @Override - public String toString() { - return "Range{datatype=" + datatype + "}"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.Range; + +public class DatatypeRange extends AbstractRange implements Range { + + private final Datatype datatype; + + public DatatypeRange(Datatype datatype) { + this.datatype = datatype; + } + + @Override + public MetaClass asClass() { + throw new IllegalStateException("Range is datatype"); + } + + @Override + public Datatype asDatatype() { + return datatype; + } + + @Override + public Enumeration asEnumeration() { + throw new IllegalStateException("Range is datatype"); + } + + @Override + public boolean isClass() { + return false; + } + + @Override + public boolean isDatatype() { + return true; + } + + @Override + public boolean isEnum() { + return false; + } + + @Override + public String toString() { + return "Range{datatype=" + datatype + "}"; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/EnumerationRange.java b/modules/global/src/com/haulmont/chile/core/model/impl/EnumerationRange.java index 6b0bcc3a22..4d3cf71aec 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/EnumerationRange.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/EnumerationRange.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Enumeration; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.Range; - -public class EnumerationRange extends AbstractRange implements Range { - - private Enumeration enumeration; - - public EnumerationRange(Enumeration enumeration) { - super(); - this.enumeration = enumeration; - } - - @Override - public MetaClass asClass() { - throw new IllegalStateException("Range is enumeration"); - } - - @Override - public Datatype asDatatype() { - throw new IllegalStateException("Range is enumeration"); - } - - @Override - public Enumeration asEnumeration() { - return enumeration; - } - - @Override - public boolean isClass() { - return false; - } - - @Override - public boolean isDatatype() { - return false; - } - - @Override - public boolean isEnum() { - return true; - } - - @Override - public String toString() { - return "Range{enum=" + enumeration + "}"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Enumeration; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.Range; + +public class EnumerationRange extends AbstractRange implements Range { + + private Enumeration enumeration; + + public EnumerationRange(Enumeration enumeration) { + super(); + this.enumeration = enumeration; + } + + @Override + public MetaClass asClass() { + throw new IllegalStateException("Range is enumeration"); + } + + @Override + public Datatype asDatatype() { + throw new IllegalStateException("Range is enumeration"); + } + + @Override + public Enumeration asEnumeration() { + return enumeration; + } + + @Override + public boolean isClass() { + return false; + } + + @Override + public boolean isDatatype() { + return false; + } + + @Override + public boolean isEnum() { + return true; + } + + @Override + public String toString() { + return "Range{enum=" + enumeration + "}"; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/MetaClassImpl.java b/modules/global/src/com/haulmont/chile/core/model/impl/MetaClassImpl.java index 63058c2117..74b22ea7d4 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/MetaClassImpl.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/MetaClassImpl.java @@ -1,204 +1,204 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.model.*; - -import java.io.InvalidObjectException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.*; - -@SuppressWarnings({"TransientFieldNotInitialized"}) -public class MetaClassImpl extends MetadataObjectImpl implements MetaClass { - - private transient Map propertyByName = new HashMap<>(); - private transient Map ownPropertyByName = new HashMap<>(); - - private transient final MetaModel model; - private transient Class javaClass; - - protected transient List ancestors = new ArrayList<>(3); - protected transient Collection descendants = new ArrayList<>(1); - - private static final long serialVersionUID = 7862691995170873154L; - - public MetaClassImpl(MetaModel model, String className) { - super(); - - this.model = model; - this.name = className; - - ((MetaModelImpl) model).registerClass(this); - } - - protected Object readResolve() throws InvalidObjectException { - Session session = SessionImpl.serializationSupportSession; - if (session == null) { - return Proxy.newProxyInstance( - this.getClass().getClassLoader(), - new Class[] { MetaClass.class }, - new MetaClassInvocationHandler(name) - ); - } else { - return session.getClass(name); - } - } - - @Override - public MetaClass getAncestor() { - if (ancestors.size() == 0) { - return null; - } else { - return ancestors.get(0); - } - } - - @Override - public List getAncestors() { - return new ArrayList<>(ancestors); - } - - @Override - public Collection getDescendants() { - return new ArrayList<>(descendants); - } - - @Override - public MetaModel getModel() { - return model; - } - - @Override - public Class getJavaClass() { - return javaClass; - } - - @Override - public Collection getProperties() { - return propertyByName.values(); - } - - @Override - public MetaProperty getProperty(String name) { - return propertyByName.get(name); - } - - @Override - public MetaProperty getPropertyNN(String name) { - MetaProperty property = getProperty(name); - if (property == null) - throw new IllegalArgumentException("Property '" + name + "' not found in " + getName()); - return property; - } - - @Override - public MetaPropertyPath getPropertyPath(String propertyPath) { - String[] properties = propertyPath.split("[.]"); - List metaProperties = new ArrayList<>(); - - MetaProperty currentProperty; - MetaClass currentClass = this; - - for (String property : properties) { - if (currentClass == null) return null; - currentProperty = currentClass.getProperty(property); - if (currentProperty == null) return null; - - final Range range = currentProperty.getRange(); - currentClass = range.isClass() ? range.asClass() : null; - - metaProperties.add(currentProperty); - } - - return new MetaPropertyPath(this, metaProperties.toArray(new MetaProperty[metaProperties.size()])); - } - - @Override - public Collection getOwnProperties() { - return ownPropertyByName.values(); - } - - public void setJavaClass(Class javaClass) { - this.javaClass = javaClass; - ((MetaModelImpl) model).registerClass(this); - } - - public void addAncestor(MetaClass ancestorClass) { - if (!ancestors.contains(ancestorClass)) { - ancestors.add(ancestorClass); - for (MetaProperty metaProperty : ancestorClass.getProperties()) { - propertyByName.put(metaProperty.getName(), metaProperty); - } - } - if (!((MetaClassImpl) ancestorClass).descendants.contains(this)) - ((MetaClassImpl) ancestorClass).descendants.add(this); - } - - public void registerProperty(MetaProperty metaProperty) { - propertyByName.put(metaProperty.getName(), metaProperty); - ownPropertyByName.put(metaProperty.getName(), metaProperty); - for (MetaClass descendant : descendants) { - ((MetaClassImpl) descendant).registerAncestorProperty(metaProperty); - } - } - - public void registerAncestorProperty(MetaProperty metaProperty) { - final MetaProperty prop = propertyByName.get(metaProperty.getName()); - if (prop == null) { - propertyByName.put(metaProperty.getName(), metaProperty); - for (MetaClass descendant : descendants) { - ((MetaClassImpl) descendant).registerAncestorProperty(metaProperty); - } - } - } - - @Override - public String toString() { - return name; - } - - private static class MetaClassInvocationHandler implements InvocationHandler { - - private String name; - private volatile MetaClass metaClass; - - public MetaClassInvocationHandler(String name) { - this.name = name; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if ("hashCode".equals(method.getName())) { - return hashCode(); - } - if (metaClass == null) { - synchronized (this) { - if (metaClass == null) { - Session session = SessionImpl.serializationSupportSession; - if (session == null) - throw new IllegalStateException("SerializationSupportSession is not initialized"); - metaClass = session.getClass(name); - } - } - } - return method.invoke(metaClass, args); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.model.*; + +import java.io.InvalidObjectException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.*; + +@SuppressWarnings({"TransientFieldNotInitialized"}) +public class MetaClassImpl extends MetadataObjectImpl implements MetaClass { + + private transient Map propertyByName = new HashMap<>(); + private transient Map ownPropertyByName = new HashMap<>(); + + private transient final MetaModel model; + private transient Class javaClass; + + protected transient List ancestors = new ArrayList<>(3); + protected transient Collection descendants = new ArrayList<>(1); + + private static final long serialVersionUID = 7862691995170873154L; + + public MetaClassImpl(MetaModel model, String className) { + super(); + + this.model = model; + this.name = className; + + ((MetaModelImpl) model).registerClass(this); + } + + protected Object readResolve() throws InvalidObjectException { + Session session = SessionImpl.serializationSupportSession; + if (session == null) { + return Proxy.newProxyInstance( + this.getClass().getClassLoader(), + new Class[] { MetaClass.class }, + new MetaClassInvocationHandler(name) + ); + } else { + return session.getClass(name); + } + } + + @Override + public MetaClass getAncestor() { + if (ancestors.size() == 0) { + return null; + } else { + return ancestors.get(0); + } + } + + @Override + public List getAncestors() { + return new ArrayList<>(ancestors); + } + + @Override + public Collection getDescendants() { + return new ArrayList<>(descendants); + } + + @Override + public MetaModel getModel() { + return model; + } + + @Override + public Class getJavaClass() { + return javaClass; + } + + @Override + public Collection getProperties() { + return propertyByName.values(); + } + + @Override + public MetaProperty getProperty(String name) { + return propertyByName.get(name); + } + + @Override + public MetaProperty getPropertyNN(String name) { + MetaProperty property = getProperty(name); + if (property == null) + throw new IllegalArgumentException("Property '" + name + "' not found in " + getName()); + return property; + } + + @Override + public MetaPropertyPath getPropertyPath(String propertyPath) { + String[] properties = propertyPath.split("[.]"); + List metaProperties = new ArrayList<>(); + + MetaProperty currentProperty; + MetaClass currentClass = this; + + for (String property : properties) { + if (currentClass == null) return null; + currentProperty = currentClass.getProperty(property); + if (currentProperty == null) return null; + + final Range range = currentProperty.getRange(); + currentClass = range.isClass() ? range.asClass() : null; + + metaProperties.add(currentProperty); + } + + return new MetaPropertyPath(this, metaProperties.toArray(new MetaProperty[metaProperties.size()])); + } + + @Override + public Collection getOwnProperties() { + return ownPropertyByName.values(); + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + ((MetaModelImpl) model).registerClass(this); + } + + public void addAncestor(MetaClass ancestorClass) { + if (!ancestors.contains(ancestorClass)) { + ancestors.add(ancestorClass); + for (MetaProperty metaProperty : ancestorClass.getProperties()) { + propertyByName.put(metaProperty.getName(), metaProperty); + } + } + if (!((MetaClassImpl) ancestorClass).descendants.contains(this)) + ((MetaClassImpl) ancestorClass).descendants.add(this); + } + + public void registerProperty(MetaProperty metaProperty) { + propertyByName.put(metaProperty.getName(), metaProperty); + ownPropertyByName.put(metaProperty.getName(), metaProperty); + for (MetaClass descendant : descendants) { + ((MetaClassImpl) descendant).registerAncestorProperty(metaProperty); + } + } + + public void registerAncestorProperty(MetaProperty metaProperty) { + final MetaProperty prop = propertyByName.get(metaProperty.getName()); + if (prop == null) { + propertyByName.put(metaProperty.getName(), metaProperty); + for (MetaClass descendant : descendants) { + ((MetaClassImpl) descendant).registerAncestorProperty(metaProperty); + } + } + } + + @Override + public String toString() { + return name; + } + + private static class MetaClassInvocationHandler implements InvocationHandler { + + private String name; + private volatile MetaClass metaClass; + + public MetaClassInvocationHandler(String name) { + this.name = name; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if ("hashCode".equals(method.getName())) { + return hashCode(); + } + if (metaClass == null) { + synchronized (this) { + if (metaClass == null) { + Session session = SessionImpl.serializationSupportSession; + if (session == null) + throw new IllegalStateException("SerializationSupportSession is not initialized"); + metaClass = session.getClass(name); + } + } + } + return method.invoke(metaClass, args); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/MetaModelImpl.java b/modules/global/src/com/haulmont/chile/core/model/impl/MetaModelImpl.java index cca658c3fc..7a800db1e4 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/MetaModelImpl.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/MetaModelImpl.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaModel; -import com.haulmont.chile.core.model.Session; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class MetaModelImpl extends MetadataObjectImpl implements MetaModel { - - private static final long serialVersionUID = -2951212408198161458L; - - private Map classByName = new HashMap<>(); - private Map classByClass = new HashMap<>(); - - public MetaModelImpl(Session session, String name) { - this.name = name; - ((SessionImpl) session).addModel(this); - } - - @Override - public MetaClass getClass(String name) { - return classByName.get(name); - } - - @Override - public MetaClass getClass(Class clazz) { - return classByClass.get(clazz); - } - - @Override - public Collection getClasses() { - return classByName.values(); - } - - public void registerClass(MetaClassImpl clazz) { - classByName.put(clazz.getName(), clazz); - if (clazz.getJavaClass() != null) { - classByClass.put(clazz.getJavaClass(), clazz); - } - } - - public void registerClass(String name, Class javaClass, MetaClassImpl clazz) { - classByName.put(name, clazz); - classByClass.put(javaClass, clazz); - } - - public Map getClassByName() { - return Collections.unmodifiableMap(classByName); - } - - public Map getClassByClass() { - return Collections.unmodifiableMap(classByClass); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaModel; +import com.haulmont.chile.core.model.Session; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class MetaModelImpl extends MetadataObjectImpl implements MetaModel { + + private static final long serialVersionUID = -2951212408198161458L; + + private Map classByName = new HashMap<>(); + private Map classByClass = new HashMap<>(); + + public MetaModelImpl(Session session, String name) { + this.name = name; + ((SessionImpl) session).addModel(this); + } + + @Override + public MetaClass getClass(String name) { + return classByName.get(name); + } + + @Override + public MetaClass getClass(Class clazz) { + return classByClass.get(clazz); + } + + @Override + public Collection getClasses() { + return classByName.values(); + } + + public void registerClass(MetaClassImpl clazz) { + classByName.put(clazz.getName(), clazz); + if (clazz.getJavaClass() != null) { + classByClass.put(clazz.getJavaClass(), clazz); + } + } + + public void registerClass(String name, Class javaClass, MetaClassImpl clazz) { + classByName.put(name, clazz); + classByClass.put(javaClass, clazz); + } + + public Map getClassByName() { + return Collections.unmodifiableMap(classByName); + } + + public Map getClassByClass() { + return Collections.unmodifiableMap(classByClass); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/MetaPropertyImpl.java b/modules/global/src/com/haulmont/chile/core/model/impl/MetaPropertyImpl.java index 9db3bcc6b9..eca0c62c37 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/MetaPropertyImpl.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/MetaPropertyImpl.java @@ -1,185 +1,185 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.model.*; - -import java.io.InvalidObjectException; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -@SuppressWarnings({"TransientFieldNotInitialized"}) -public class MetaPropertyImpl extends MetadataObjectImpl implements MetaProperty { - - private MetaClass domain; - private transient final MetaModel model; - - private transient boolean mandatory; - private transient boolean readOnly; - private transient Type type; - private transient Range range; - - private transient MetaProperty inverse; - - private transient AnnotatedElement annotatedElement; - private transient Class javaType; - private transient Class declaringClass; - - private static final long serialVersionUID = -2827471157045502206L; - - public MetaPropertyImpl(MetaClass domain, String name) { - this.domain = domain; - this.model = domain.getModel(); - this.name = name; - - ((MetaClassImpl) domain).registerProperty(this); - } - - protected Object readResolve() throws InvalidObjectException { - Session session = SessionImpl.serializationSupportSession; - if (session == null) { - return Proxy.newProxyInstance( - this.getClass().getClassLoader(), - new Class[]{MetaProperty.class}, - new MetaPropertyInvocationHandler(domain, name) - ); - } else { - return domain.getProperty(name); - } - } - - @Override - public MetaClass getDomain() { - return domain; - } - - public void setDomain(MetaClass domain) { - this.domain = domain; - } - - @Override - public MetaProperty getInverse() { - return inverse; - } - - public void setInverse(MetaProperty inverse) { - this.inverse = inverse; - } - - @Override - public MetaModel getModel() { - return model; - } - - @Override - public Range getRange() { - return range; - } - - @Override - public AnnotatedElement getAnnotatedElement() { - return annotatedElement; - } - - public void setAnnotatedElement(AnnotatedElement annotatedElement) { - this.annotatedElement = annotatedElement; - } - - @Override - public Class getJavaType() { - return javaType; - } - - public void setJavaType(Class javaType) { - this.javaType = javaType; - } - - @Override - public Class getDeclaringClass() { - return declaringClass; - } - - public void setDeclaringClass(Class declaringClass) { - this.declaringClass = declaringClass; - } - - public void setRange(Range range) { - this.range = range; - } - - @Override - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } - - @Override - public boolean isMandatory() { - return mandatory; - } - - public void setMandatory(boolean mandatory) { - this.mandatory = mandatory; - } - - @Override - public boolean isReadOnly() { - return readOnly; - } - - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - @Override - public String toString() { - return domain.getName() + "." + name; - } - - private static class MetaPropertyInvocationHandler implements InvocationHandler { - - private MetaClass domain; - private String name; - private volatile MetaProperty metaProperty; - - public MetaPropertyInvocationHandler(MetaClass domain, String name) { - this.domain = domain; - this.name = name; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if ("hashCode".equals(method.getName())) { - return hashCode(); - } - if (metaProperty == null) { - synchronized (this) { - if (metaProperty == null) { - metaProperty = domain.getProperty(name); - } - } - } - return method.invoke(metaProperty, args); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.model.*; + +import java.io.InvalidObjectException; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +@SuppressWarnings({"TransientFieldNotInitialized"}) +public class MetaPropertyImpl extends MetadataObjectImpl implements MetaProperty { + + private MetaClass domain; + private transient final MetaModel model; + + private transient boolean mandatory; + private transient boolean readOnly; + private transient Type type; + private transient Range range; + + private transient MetaProperty inverse; + + private transient AnnotatedElement annotatedElement; + private transient Class javaType; + private transient Class declaringClass; + + private static final long serialVersionUID = -2827471157045502206L; + + public MetaPropertyImpl(MetaClass domain, String name) { + this.domain = domain; + this.model = domain.getModel(); + this.name = name; + + ((MetaClassImpl) domain).registerProperty(this); + } + + protected Object readResolve() throws InvalidObjectException { + Session session = SessionImpl.serializationSupportSession; + if (session == null) { + return Proxy.newProxyInstance( + this.getClass().getClassLoader(), + new Class[]{MetaProperty.class}, + new MetaPropertyInvocationHandler(domain, name) + ); + } else { + return domain.getProperty(name); + } + } + + @Override + public MetaClass getDomain() { + return domain; + } + + public void setDomain(MetaClass domain) { + this.domain = domain; + } + + @Override + public MetaProperty getInverse() { + return inverse; + } + + public void setInverse(MetaProperty inverse) { + this.inverse = inverse; + } + + @Override + public MetaModel getModel() { + return model; + } + + @Override + public Range getRange() { + return range; + } + + @Override + public AnnotatedElement getAnnotatedElement() { + return annotatedElement; + } + + public void setAnnotatedElement(AnnotatedElement annotatedElement) { + this.annotatedElement = annotatedElement; + } + + @Override + public Class getJavaType() { + return javaType; + } + + public void setJavaType(Class javaType) { + this.javaType = javaType; + } + + @Override + public Class getDeclaringClass() { + return declaringClass; + } + + public void setDeclaringClass(Class declaringClass) { + this.declaringClass = declaringClass; + } + + public void setRange(Range range) { + this.range = range; + } + + @Override + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @Override + public boolean isMandatory() { + return mandatory; + } + + public void setMandatory(boolean mandatory) { + this.mandatory = mandatory; + } + + @Override + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + @Override + public String toString() { + return domain.getName() + "." + name; + } + + private static class MetaPropertyInvocationHandler implements InvocationHandler { + + private MetaClass domain; + private String name; + private volatile MetaProperty metaProperty; + + public MetaPropertyInvocationHandler(MetaClass domain, String name) { + this.domain = domain; + this.name = name; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if ("hashCode".equals(method.getName())) { + return hashCode(); + } + if (metaProperty == null) { + synchronized (this) { + if (metaProperty == null) { + metaProperty = domain.getProperty(name); + } + } + } + return method.invoke(metaProperty, args); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/MetadataObjectImpl.java b/modules/global/src/com/haulmont/chile/core/model/impl/MetadataObjectImpl.java index ef816e1eaa..4e2bb151ae 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/MetadataObjectImpl.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/MetadataObjectImpl.java @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import com.haulmont.chile.core.model.MetadataObject; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings({"TransientFieldNotInitialized"}) -public abstract class MetadataObjectImpl implements MetadataObject, Serializable { - - private static final long serialVersionUID = 5179324236413815312L; - - protected String name; - - private transient Map annotations = new HashMap<>(); - - @Override - public String getName() { - return name; - } - - @Override - public Map getAnnotations() { - return annotations; - } - - public void setName(String name) { - this.name = name; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import com.haulmont.chile.core.model.MetadataObject; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings({"TransientFieldNotInitialized"}) +public abstract class MetadataObjectImpl implements MetadataObject, Serializable { + + private static final long serialVersionUID = 5179324236413815312L; + + protected String name; + + private transient Map annotations = new HashMap<>(); + + @Override + public String getName() { + return name; + } + + @Override + public Map getAnnotations() { + return annotations; + } + + public void setName(String name) { + this.name = name; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/impl/SessionImpl.java b/modules/global/src/com/haulmont/chile/core/model/impl/SessionImpl.java index 31b56c49c0..33d38a7bc9 100644 --- a/modules/global/src/com/haulmont/chile/core/model/impl/SessionImpl.java +++ b/modules/global/src/com/haulmont/chile/core/model/impl/SessionImpl.java @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.chile.core.model.impl; - -import java.util.*; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaModel; -import com.haulmont.chile.core.model.Session; - -import javax.annotation.Nullable; - -public class SessionImpl implements Session { - - private final Map models = new HashMap<>(); - - static Session serializationSupportSession; - - public static void setSerializationSupportSession(Session serializationSupportSession) { - SessionImpl.serializationSupportSession = serializationSupportSession; - } - - @Override - public MetaModel getModel(String name) { - return models.get(name); - } - - @Override - public Collection getModels() { - return models.values(); - } - - @Nullable - @Override - public MetaClass getClass(String name) { - for (MetaModel model : models.values()) { - final MetaClass metaClass = model.getClass(name); - if (metaClass != null) { - return metaClass; - } - } - - return null; - } - - @Override - public MetaClass getClassNN(String name) { - MetaClass metaClass = getClass(name); - if (metaClass == null) { - throw new IllegalArgumentException("MetaClass not found for " + name); - } - return metaClass; - } - - @Nullable - @Override - public MetaClass getClass(Class clazz) { - for (MetaModel model : models.values()) { - final MetaClass metaClass = model.getClass(clazz); - if (metaClass != null) { - return metaClass; - } - } - - return null; - } - - @Override - public MetaClass getClassNN(Class clazz) { - MetaClass metaClass = getClass(clazz); - if (metaClass == null) { - throw new IllegalArgumentException("MetaClass not found for " + clazz); - } - return metaClass; - } - - @Override - public Collection getClasses() { - final List classes = new ArrayList<>(); - for (MetaModel model : models.values()) { - classes.addAll(model.getClasses()); - } - - return classes; - } - - public void addModel(MetaModelImpl model) { - models.put(model.getName(), model); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.chile.core.model.impl; + +import java.util.*; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaModel; +import com.haulmont.chile.core.model.Session; + +import javax.annotation.Nullable; + +public class SessionImpl implements Session { + + private final Map models = new HashMap<>(); + + static Session serializationSupportSession; + + public static void setSerializationSupportSession(Session serializationSupportSession) { + SessionImpl.serializationSupportSession = serializationSupportSession; + } + + @Override + public MetaModel getModel(String name) { + return models.get(name); + } + + @Override + public Collection getModels() { + return models.values(); + } + + @Nullable + @Override + public MetaClass getClass(String name) { + for (MetaModel model : models.values()) { + final MetaClass metaClass = model.getClass(name); + if (metaClass != null) { + return metaClass; + } + } + + return null; + } + + @Override + public MetaClass getClassNN(String name) { + MetaClass metaClass = getClass(name); + if (metaClass == null) { + throw new IllegalArgumentException("MetaClass not found for " + name); + } + return metaClass; + } + + @Nullable + @Override + public MetaClass getClass(Class clazz) { + for (MetaModel model : models.values()) { + final MetaClass metaClass = model.getClass(clazz); + if (metaClass != null) { + return metaClass; + } + } + + return null; + } + + @Override + public MetaClass getClassNN(Class clazz) { + MetaClass metaClass = getClass(clazz); + if (metaClass == null) { + throw new IllegalArgumentException("MetaClass not found for " + clazz); + } + return metaClass; + } + + @Override + public Collection getClasses() { + final List classes = new ArrayList<>(); + for (MetaModel model : models.values()) { + classes.addAll(model.getClasses()); + } + + return classes; + } + + public void addModel(MetaModelImpl model) { + models.put(model.getName(), model); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java b/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java index faac692b49..1191270c86 100644 --- a/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java +++ b/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java @@ -1,309 +1,309 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.model.utils; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.impl.AbstractInstance; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.DevelopmentException; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.MetadataTools; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -/** - * Utility class to work with {@link Instance}s. - */ -public final class InstanceUtils { - - private static final Pattern INSTANCE_NAME_SPLIT_PATTERN = Pattern.compile("[,;]"); - - private InstanceUtils() { - } - - /** - * Converts a string of identifiers separated by dots to an array. A part of the given string, enclosed in square - * brackets, treated as single identifier. For example: - *
-     *     car.driver.name
-     *     [car.field].driver.name
-     * 
- * @param path value path as string - * @return value path as array - */ - public static String[] parseValuePath(String path) { - List elements = new ArrayList<>(4); - - int bracketCount = 0; - - StringBuilder buffer = new StringBuilder(); - - for (int i = 0; i < path.length(); i++) { - char c = path.charAt(i); - if (c == '[') - bracketCount++; - if (c == ']') - bracketCount--; - - if ('.' != c || bracketCount > 0) - buffer.append(c); - - if ('.' == c && bracketCount == 0) { - String element = buffer.toString(); - if (!"".equals(element)) { - elements.add(element); - } else { - throw new IllegalStateException("Wrong value path format"); - } - buffer = new StringBuilder(); - } - } - elements.add(buffer.toString()); - - return elements.toArray(new String[elements.size()]); - } - - /** - * Converts an array of identifiers to a dot-separated string, enclosing identifiers, containing dots, in square - * brackets. - * @param path value path as array - * @return value path as string - */ - public static String formatValuePath(String[] path) { - StringBuilder buffer = new StringBuilder(); - int i = 1; - for (String s : path) { - if (s.contains(".")) { - buffer.append("[").append(s).append("]"); - } else { - buffer.append(s); - } - if (i < path.length) buffer.append("."); - i++; - } - return buffer.toString(); - } - - /** - * Get value of an attribute according to the rules described in {@link Instance#getValueEx(String)}. - * @param instance instance - * @param propertyPath attribute path - * @return attribute value - */ - public static T getValueEx(Instance instance, String propertyPath) { - String[] properties = parseValuePath(propertyPath); - //noinspection unchecked - return getValueEx(instance, properties); - } - - /** - * Get value of an attribute according to the rules described in {@link Instance#getValueEx(String)}. - * @param instance instance - * @param properties path to the attribute - * @return attribute value - */ - public static T getValueEx(Instance instance, String[] properties) { - Object currentValue = null; - Instance currentInstance = instance; - for (String property : properties) { - if (currentInstance == null) - break; - - currentValue = currentInstance.getValue(property); - if (currentValue == null) - break; - - currentInstance = currentValue instanceof Instance ? (Instance) currentValue : null; - } - return (T) currentValue; - } - - /** - * Set value of an attribute according to the rules described in {@link Instance#setValueEx(String, Object)}. - * @param instance instance - * @param propertyPath path to the attribute - * @param value attribute value - */ - public static void setValueEx(Instance instance, String propertyPath, Object value) { - String[] properties = parseValuePath(propertyPath); - setValueEx(instance, properties, value); - } - - /** - * Set value of an attribute according to the rules described in {@link Instance#setValueEx(String, Object)}. - * @param instance instance - * @param properties path to the attribute - * @param value attribute value - */ - public static void setValueEx(Instance instance, String[] properties, Object value) { - if (properties.length > 1) { - String[] subarray = (String[]) ArrayUtils.subarray(properties, 0, properties.length - 1); - String intermediatePath = formatValuePath(subarray); - - instance = instance.getValueEx(intermediatePath); - - if (instance != null) { - String property = properties[properties.length - 1]; - instance.setValue(property, value); - } else { - throw new IllegalStateException(String.format("Can't find property '%s' value", intermediatePath)); - } - } else { - instance.setValue(properties[0], value); - } - } - - /** - * Use com.haulmont.cuba.core.global.MetadataTools#copy instead - */ - @Deprecated - public static Instance copy(Instance source) { - return AppBeans.get(MetadataTools.NAME, MetadataTools.class).copy(source); - } - - /** - * Use com.haulmont.cuba.core.global.MetadataTools#copy instead - */ - @Deprecated - public static void copy(Instance source, Instance dest) { - AppBeans.get(MetadataTools.NAME, MetadataTools.class).copy(source, dest); - } - - /** - * @return Instance name as defined by {@link com.haulmont.chile.core.annotations.NamePattern} - * or toString(). - * @param instance instance - */ - public static String getInstanceName(Instance instance) { - checkNotNullArgument(instance, "instance is null"); - - NamePatternRec rec = parseNamePattern(instance.getMetaClass()); - if (rec == null) { - return instance.toString(); - } else { - if (rec.methodName != null) { - try { - Method method = instance.getClass().getMethod(rec.methodName); - Object result = method.invoke(instance); - return (String) result; - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException("Error getting instance name", e); - } - } - - // lazy initialized messages, used only for enum values - Messages messages = null; - - Object[] values = new Object[rec.fields.length]; - for (int i = 0; i < rec.fields.length; i++) { - Object value = instance.getValue(rec.fields[i]); - if (value == null) { - values[i] = ""; - } else if (value instanceof Instance) { - values[i] = getInstanceName((Instance) value); - } else if (value instanceof EnumClass) { - if (messages == null) { - messages = AppBeans.get(Messages.NAME); - } - - values[i] = messages.getMessage((Enum)value); - } else { - values[i] = value; - } - } - - return String.format(rec.format, values); - } - } - - /** - * Parse a name pattern defined by {@link NamePattern} annotation. - * @param metaClass entity meta-class - * @return record containing the name pattern properties, or null if the @NamePattern is not defined for the meta-class - */ - @Nullable - public static NamePatternRec parseNamePattern(MetaClass metaClass) { - Map attributes = (Map) metaClass.getAnnotations().get(NamePattern.class.getName()); - if (attributes == null) - return null; - String pattern = (String) attributes.get("value"); - if (StringUtils.isBlank(pattern)) - return null; - - int pos = pattern.indexOf("|"); - if (pos < 0) - throw new DevelopmentException("Invalid name pattern: " + pattern); - - String format = StringUtils.substring(pattern, 0, pos); - String trimmedFormat = format.trim(); - String methodName = trimmedFormat.startsWith("#") ? trimmedFormat.substring(1) : null; - String fieldsStr = StringUtils.substring(pattern, pos + 1); - String[] fields = INSTANCE_NAME_SPLIT_PATTERN.split(fieldsStr); - return new NamePatternRec(format, methodName, fields); - } - - public static class NamePatternRec { - /** - * Name pattern string format - */ - public final String format; - /** - * Formatting method name or null - */ - public final String methodName; - /** - * Array of property names - */ - public final String[] fields; - - public NamePatternRec(String format, String methodName, String[] fields) { - this.fields = fields; - this.format = format; - this.methodName = methodName; - } - } - - /** - * Used by {@link AbstractInstance} to check whether property value has been changed. - * - * @param a an object - * @param b an object - * @return true if a equals to b, but in case of a is {@link AbstractInstance} returns true only if a are the same instance as b - */ - public static boolean propertyValueEquals(Object a, Object b) { - if (a == b) { - return true; - } - if (a instanceof AbstractInstance) { - return false; - } - return a != null && a.equals(b); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.model.utils; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.impl.AbstractInstance; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.DevelopmentException; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.MetadataTools; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +/** + * Utility class to work with {@link Instance}s. + */ +public final class InstanceUtils { + + private static final Pattern INSTANCE_NAME_SPLIT_PATTERN = Pattern.compile("[,;]"); + + private InstanceUtils() { + } + + /** + * Converts a string of identifiers separated by dots to an array. A part of the given string, enclosed in square + * brackets, treated as single identifier. For example: + *
+     *     car.driver.name
+     *     [car.field].driver.name
+     * 
+ * @param path value path as string + * @return value path as array + */ + public static String[] parseValuePath(String path) { + List elements = new ArrayList<>(4); + + int bracketCount = 0; + + StringBuilder buffer = new StringBuilder(); + + for (int i = 0; i < path.length(); i++) { + char c = path.charAt(i); + if (c == '[') + bracketCount++; + if (c == ']') + bracketCount--; + + if ('.' != c || bracketCount > 0) + buffer.append(c); + + if ('.' == c && bracketCount == 0) { + String element = buffer.toString(); + if (!"".equals(element)) { + elements.add(element); + } else { + throw new IllegalStateException("Wrong value path format"); + } + buffer = new StringBuilder(); + } + } + elements.add(buffer.toString()); + + return elements.toArray(new String[elements.size()]); + } + + /** + * Converts an array of identifiers to a dot-separated string, enclosing identifiers, containing dots, in square + * brackets. + * @param path value path as array + * @return value path as string + */ + public static String formatValuePath(String[] path) { + StringBuilder buffer = new StringBuilder(); + int i = 1; + for (String s : path) { + if (s.contains(".")) { + buffer.append("[").append(s).append("]"); + } else { + buffer.append(s); + } + if (i < path.length) buffer.append("."); + i++; + } + return buffer.toString(); + } + + /** + * Get value of an attribute according to the rules described in {@link Instance#getValueEx(String)}. + * @param instance instance + * @param propertyPath attribute path + * @return attribute value + */ + public static T getValueEx(Instance instance, String propertyPath) { + String[] properties = parseValuePath(propertyPath); + //noinspection unchecked + return getValueEx(instance, properties); + } + + /** + * Get value of an attribute according to the rules described in {@link Instance#getValueEx(String)}. + * @param instance instance + * @param properties path to the attribute + * @return attribute value + */ + public static T getValueEx(Instance instance, String[] properties) { + Object currentValue = null; + Instance currentInstance = instance; + for (String property : properties) { + if (currentInstance == null) + break; + + currentValue = currentInstance.getValue(property); + if (currentValue == null) + break; + + currentInstance = currentValue instanceof Instance ? (Instance) currentValue : null; + } + return (T) currentValue; + } + + /** + * Set value of an attribute according to the rules described in {@link Instance#setValueEx(String, Object)}. + * @param instance instance + * @param propertyPath path to the attribute + * @param value attribute value + */ + public static void setValueEx(Instance instance, String propertyPath, Object value) { + String[] properties = parseValuePath(propertyPath); + setValueEx(instance, properties, value); + } + + /** + * Set value of an attribute according to the rules described in {@link Instance#setValueEx(String, Object)}. + * @param instance instance + * @param properties path to the attribute + * @param value attribute value + */ + public static void setValueEx(Instance instance, String[] properties, Object value) { + if (properties.length > 1) { + String[] subarray = (String[]) ArrayUtils.subarray(properties, 0, properties.length - 1); + String intermediatePath = formatValuePath(subarray); + + instance = instance.getValueEx(intermediatePath); + + if (instance != null) { + String property = properties[properties.length - 1]; + instance.setValue(property, value); + } else { + throw new IllegalStateException(String.format("Can't find property '%s' value", intermediatePath)); + } + } else { + instance.setValue(properties[0], value); + } + } + + /** + * Use com.haulmont.cuba.core.global.MetadataTools#copy instead + */ + @Deprecated + public static Instance copy(Instance source) { + return AppBeans.get(MetadataTools.NAME, MetadataTools.class).copy(source); + } + + /** + * Use com.haulmont.cuba.core.global.MetadataTools#copy instead + */ + @Deprecated + public static void copy(Instance source, Instance dest) { + AppBeans.get(MetadataTools.NAME, MetadataTools.class).copy(source, dest); + } + + /** + * @return Instance name as defined by {@link com.haulmont.chile.core.annotations.NamePattern} + * or toString(). + * @param instance instance + */ + public static String getInstanceName(Instance instance) { + checkNotNullArgument(instance, "instance is null"); + + NamePatternRec rec = parseNamePattern(instance.getMetaClass()); + if (rec == null) { + return instance.toString(); + } else { + if (rec.methodName != null) { + try { + Method method = instance.getClass().getMethod(rec.methodName); + Object result = method.invoke(instance); + return (String) result; + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException("Error getting instance name", e); + } + } + + // lazy initialized messages, used only for enum values + Messages messages = null; + + Object[] values = new Object[rec.fields.length]; + for (int i = 0; i < rec.fields.length; i++) { + Object value = instance.getValue(rec.fields[i]); + if (value == null) { + values[i] = ""; + } else if (value instanceof Instance) { + values[i] = getInstanceName((Instance) value); + } else if (value instanceof EnumClass) { + if (messages == null) { + messages = AppBeans.get(Messages.NAME); + } + + values[i] = messages.getMessage((Enum)value); + } else { + values[i] = value; + } + } + + return String.format(rec.format, values); + } + } + + /** + * Parse a name pattern defined by {@link NamePattern} annotation. + * @param metaClass entity meta-class + * @return record containing the name pattern properties, or null if the @NamePattern is not defined for the meta-class + */ + @Nullable + public static NamePatternRec parseNamePattern(MetaClass metaClass) { + Map attributes = (Map) metaClass.getAnnotations().get(NamePattern.class.getName()); + if (attributes == null) + return null; + String pattern = (String) attributes.get("value"); + if (StringUtils.isBlank(pattern)) + return null; + + int pos = pattern.indexOf("|"); + if (pos < 0) + throw new DevelopmentException("Invalid name pattern: " + pattern); + + String format = StringUtils.substring(pattern, 0, pos); + String trimmedFormat = format.trim(); + String methodName = trimmedFormat.startsWith("#") ? trimmedFormat.substring(1) : null; + String fieldsStr = StringUtils.substring(pattern, pos + 1); + String[] fields = INSTANCE_NAME_SPLIT_PATTERN.split(fieldsStr); + return new NamePatternRec(format, methodName, fields); + } + + public static class NamePatternRec { + /** + * Name pattern string format + */ + public final String format; + /** + * Formatting method name or null + */ + public final String methodName; + /** + * Array of property names + */ + public final String[] fields; + + public NamePatternRec(String format, String methodName, String[] fields) { + this.fields = fields; + this.format = format; + this.methodName = methodName; + } + } + + /** + * Used by {@link AbstractInstance} to check whether property value has been changed. + * + * @param a an object + * @param b an object + * @return true if a equals to b, but in case of a is {@link AbstractInstance} returns true only if a are the same instance as b + */ + public static boolean propertyValueEquals(Object a, Object b) { + if (a == b) { + return true; + } + if (a instanceof AbstractInstance) { + return false; + } + return a != null && a.equals(b); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/utils/MethodsCache.java b/modules/global/src/com/haulmont/chile/core/model/utils/MethodsCache.java index 201eec8cb8..c6d6750484 100644 --- a/modules/global/src/com/haulmont/chile/core/model/utils/MethodsCache.java +++ b/modules/global/src/com/haulmont/chile/core/model/utils/MethodsCache.java @@ -1,77 +1,77 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.model.utils; - -import org.apache.commons.lang.StringUtils; - -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import java.util.HashMap; - -public class MethodsCache { - - private final transient Map getters = new HashMap<>(); - private final transient Map setters = new HashMap<>(); - - public MethodsCache(Class clazz) { - final Method[] methods = clazz.getMethods(); - for (Method method : methods) { - String name = method.getName(); - if (name.startsWith("get") && method.getParameterTypes().length == 0) { - name = StringUtils.uncapitalize(name.substring(3)); - method.setAccessible(true); - getters.put(name, method); - } - if (name.startsWith("is") && method.getParameterTypes().length == 0) { - name = StringUtils.uncapitalize(name.substring(2)); - method.setAccessible(true); - getters.put(name, method); - } else if (name.startsWith("set") && method.getParameterTypes().length == 1) { - name = StringUtils.uncapitalize(name.substring(3)); - method.setAccessible(true); - setters.put(name, method); - } - } - } - - public void invokeSetter(Object object, String property, Object value) { - final Method method = setters.get(property); - if (method == null) { - throw new IllegalArgumentException( - String.format("Can't find setter for property '%s' at %s", property, object.getClass())); - } - try { - method.invoke(object, value); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - public Object invokeGetter(Object object, String property) { - final Method method = getters.get(property); - if (method == null) { - throw new IllegalArgumentException( - String.format("Can't find getter for property '%s' at %s", property, object.getClass())); - } - try { - return method.invoke(object); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.model.utils; + +import org.apache.commons.lang.StringUtils; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.HashMap; + +public class MethodsCache { + + private final transient Map getters = new HashMap<>(); + private final transient Map setters = new HashMap<>(); + + public MethodsCache(Class clazz) { + final Method[] methods = clazz.getMethods(); + for (Method method : methods) { + String name = method.getName(); + if (name.startsWith("get") && method.getParameterTypes().length == 0) { + name = StringUtils.uncapitalize(name.substring(3)); + method.setAccessible(true); + getters.put(name, method); + } + if (name.startsWith("is") && method.getParameterTypes().length == 0) { + name = StringUtils.uncapitalize(name.substring(2)); + method.setAccessible(true); + getters.put(name, method); + } else if (name.startsWith("set") && method.getParameterTypes().length == 1) { + name = StringUtils.uncapitalize(name.substring(3)); + method.setAccessible(true); + setters.put(name, method); + } + } + } + + public void invokeSetter(Object object, String property, Object value) { + final Method method = setters.get(property); + if (method == null) { + throw new IllegalArgumentException( + String.format("Can't find setter for property '%s' at %s", property, object.getClass())); + } + try { + method.invoke(object, value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public Object invokeGetter(Object object, String property) { + final Method method = getters.get(property); + if (method == null) { + throw new IllegalArgumentException( + String.format("Can't find getter for property '%s' at %s", property, object.getClass())); + } + try { + return method.invoke(object); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/chile/core/model/utils/PrintUtils.java b/modules/global/src/com/haulmont/chile/core/model/utils/PrintUtils.java index e4549e1392..66da7326de 100644 --- a/modules/global/src/com/haulmont/chile/core/model/utils/PrintUtils.java +++ b/modules/global/src/com/haulmont/chile/core/model/utils/PrintUtils.java @@ -1,90 +1,90 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.chile.core.model.utils; - -import com.haulmont.chile.core.model.Session; -import com.haulmont.chile.core.model.MetaModel; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; - -import java.util.Collection; -import java.util.LinkedList; - -public final class PrintUtils { - - private PrintUtils() { - } - - public static String printModels(Session session) { - StringBuilder builder = new StringBuilder(); - for (MetaModel model : session.getModels()) { - builder.append(model.getName()).append("\n"); - } - - return builder.toString(); - } - - public static String printClassHierarchy(MetaModel model) { - StringBuilder builder = new StringBuilder(); - - Collection topLevelClasses = new LinkedList<>(); - for (MetaClass metaClass : model.getClasses()) { - if (metaClass.getAncestor() == null) { - topLevelClasses.add(metaClass); - } - } - - for (MetaClass topLevelClass : topLevelClasses) { - builder.append(printClassHierarchy(topLevelClass)); - } - - return builder.toString(); - } - - public static String printClassHierarchy(MetaClass metaClass) { - StringBuilder builder = new StringBuilder(); - - builder.append(metaClass.getName()).append("\n"); - for (MetaClass descendantClass : metaClass.getDescendants()) { - builder.append(shift(printClassHierarchy(descendantClass))); - } - - return builder.toString(); - } - - public static String printClass(MetaClass metaClass) { - StringBuilder builder = new StringBuilder(); - - builder.append(metaClass.getName()).append("\n"); - for (MetaProperty metaProperty : metaClass.getOwnProperties()) { - builder.append(shift(metaProperty.getName() + ": " + metaProperty.getRange())); - } - - return builder.toString(); - } - - private static String shift(String string) { - StringBuilder builder = new StringBuilder(); - - final String[] strings = string.split("\n"); - for (String s : strings) { - builder.append(" ").append(s).append("\n"); - } - - return builder.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.chile.core.model.utils; + +import com.haulmont.chile.core.model.Session; +import com.haulmont.chile.core.model.MetaModel; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; + +import java.util.Collection; +import java.util.LinkedList; + +public final class PrintUtils { + + private PrintUtils() { + } + + public static String printModels(Session session) { + StringBuilder builder = new StringBuilder(); + for (MetaModel model : session.getModels()) { + builder.append(model.getName()).append("\n"); + } + + return builder.toString(); + } + + public static String printClassHierarchy(MetaModel model) { + StringBuilder builder = new StringBuilder(); + + Collection topLevelClasses = new LinkedList<>(); + for (MetaClass metaClass : model.getClasses()) { + if (metaClass.getAncestor() == null) { + topLevelClasses.add(metaClass); + } + } + + for (MetaClass topLevelClass : topLevelClasses) { + builder.append(printClassHierarchy(topLevelClass)); + } + + return builder.toString(); + } + + public static String printClassHierarchy(MetaClass metaClass) { + StringBuilder builder = new StringBuilder(); + + builder.append(metaClass.getName()).append("\n"); + for (MetaClass descendantClass : metaClass.getDescendants()) { + builder.append(shift(printClassHierarchy(descendantClass))); + } + + return builder.toString(); + } + + public static String printClass(MetaClass metaClass) { + StringBuilder builder = new StringBuilder(); + + builder.append(metaClass.getName()).append("\n"); + for (MetaProperty metaProperty : metaClass.getOwnProperties()) { + builder.append(shift(metaProperty.getName() + ": " + metaProperty.getRange())); + } + + return builder.toString(); + } + + private static String shift(String string) { + StringBuilder builder = new StringBuilder(); + + final String[] strings = string.split("\n"); + for (String s : strings) { + builder.append(" ").append(s).append("\n"); + } + + return builder.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/ConfigStorageService.java b/modules/global/src/com/haulmont/cuba/core/app/ConfigStorageService.java index 4dfa4150a9..fc6c21043a 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/ConfigStorageService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/ConfigStorageService.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.config.AppPropertyEntity; - -import java.util.List; -import java.util.Map; - -/** - * Supports configuration parameters framework functionality. - * - */ -public interface ConfigStorageService { - - String NAME = "cuba_ConfigStorageService"; - - Map getDbProperties(); - - String getDbProperty(String name); - - void setDbProperty(String name, String value); - - List getAppProperties(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.config.AppPropertyEntity; + +import java.util.List; +import java.util.Map; + +/** + * Supports configuration parameters framework functionality. + * + */ +public interface ConfigStorageService { + + String NAME = "cuba_ConfigStorageService"; + + Map getDbProperties(); + + String getDbProperty(String name); + + void setDbProperty(String name, String value); + + List getAppProperties(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/DataService.java b/modules/global/src/com/haulmont/cuba/core/app/DataService.java index bacbd1ed00..ef6c64e3ce 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/DataService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/DataService.java @@ -1,72 +1,72 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.KeyValueEntity; -import com.haulmont.cuba.core.global.CommitContext; -import com.haulmont.cuba.core.global.LoadContext; -import com.haulmont.cuba.core.global.ValueLoadContext; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.Set; - -/** - * Middleware service interface to provide CRUD functionality. - *

Implementation delegates to {@link com.haulmont.cuba.core.global.DataManager}

- * - */ -public interface DataService { - - String NAME = "cuba_DataService"; - - /** - * Commits a collection of new or detached entity instances to the database. - * @param context {@link CommitContext} object, containing committing entities and other information - * @return set of committed instances - */ - Set commit(CommitContext context); - - /** - * Loads a single entity instance. - *

The depth of object graphs, starting from loaded instances, defined by {@link com.haulmont.cuba.core.global.View} - * object passed in {@link LoadContext}.

- * @param context {@link LoadContext} object, defining what and how to load - * @return the loaded detached object, or null if not found - */ - @Nullable - E load(LoadContext context); - - /** - * Loads collection of entity instances. - *

The depth of object graphs, starting from loaded instances, defined by {@link com.haulmont.cuba.core.global.View} - * object passed in {@link LoadContext}.

- * @param context {@link LoadContext} object, defining what and how to load - * @return a list of detached instances, or empty list if nothing found - */ - List loadList(LoadContext context); - - /** - * Returns the number of entity instances for the given query passed in the {@link LoadContext}. - * @param context defines the query - * @return number of instances in the database - */ - long getCount(LoadContext context); - - List loadValues(ValueLoadContext context); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.KeyValueEntity; +import com.haulmont.cuba.core.global.CommitContext; +import com.haulmont.cuba.core.global.LoadContext; +import com.haulmont.cuba.core.global.ValueLoadContext; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + +/** + * Middleware service interface to provide CRUD functionality. + *

Implementation delegates to {@link com.haulmont.cuba.core.global.DataManager}

+ * + */ +public interface DataService { + + String NAME = "cuba_DataService"; + + /** + * Commits a collection of new or detached entity instances to the database. + * @param context {@link CommitContext} object, containing committing entities and other information + * @return set of committed instances + */ + Set commit(CommitContext context); + + /** + * Loads a single entity instance. + *

The depth of object graphs, starting from loaded instances, defined by {@link com.haulmont.cuba.core.global.View} + * object passed in {@link LoadContext}.

+ * @param context {@link LoadContext} object, defining what and how to load + * @return the loaded detached object, or null if not found + */ + @Nullable + E load(LoadContext context); + + /** + * Loads collection of entity instances. + *

The depth of object graphs, starting from loaded instances, defined by {@link com.haulmont.cuba.core.global.View} + * object passed in {@link LoadContext}.

+ * @param context {@link LoadContext} object, defining what and how to load + * @return a list of detached instances, or empty list if nothing found + */ + List loadList(LoadContext context); + + /** + * Returns the number of entity instances for the given query passed in the {@link LoadContext}. + * @param context defines the query + * @return number of instances in the database + */ + long getCount(LoadContext context); + + List loadValues(ValueLoadContext context); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/EmailService.java b/modules/global/src/com/haulmont/cuba/core/app/EmailService.java index 5d2a7d39fb..32d9c8cefb 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/EmailService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/EmailService.java @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.SendingMessage; -import com.haulmont.cuba.core.global.EmailAttachment; -import com.haulmont.cuba.core.global.EmailException; -import com.haulmont.cuba.core.global.EmailInfo; - -import javax.annotation.Nullable; -import java.util.Date; - -/** - * Service for sending emails. - * - */ -public interface EmailService { - - String NAME = "cuba_EmailService"; - - /** - * Send email synchronously. - * - * @param address comma or semicolon separated list of addresses - * @param caption email subject - * @param body email body - * @param attachment email attachments - * @throws com.haulmont.cuba.core.global.EmailException - * in case of any errors - */ - void sendEmail(String address, String caption, String body, EmailAttachment... attachment) - throws EmailException; - - /** - * Send email synchronously. - * - * @param info email details - * @throws EmailException in case of any errors - */ - void sendEmail(EmailInfo info) throws EmailException; - - /** - * Send email asynchronously, with limited number of attempts. - *

- * The actual sending is performed by invoking the {@code EmailerAPI.processQueuedEmails()} (e.g. from a scheduled task). - * - * @param info email details - * @param attemptsCount count of attempts to send (1 attempt = 1 emailer cron tick) - * @param deadline Emailer tries to send message till deadline. - * If deadline has come and message has not been sent, status of this message is changed to - * {@link com.haulmont.cuba.core.global.SendingStatus#NOTSENT} - */ - void sendEmailAsync(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline); - - /** - * Send email asynchronously. - *

- * The actual sending is performed by invoking the {@code EmailerAPI.processQueuedEmails()} (e.g. from a scheduled task). - * - * @param info email details - */ - void sendEmailAsync(EmailInfo info); - - /** - * Load content text for given message. - * - * @return email content text - */ - String loadContentText(SendingMessage sendingMessage); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.SendingMessage; +import com.haulmont.cuba.core.global.EmailAttachment; +import com.haulmont.cuba.core.global.EmailException; +import com.haulmont.cuba.core.global.EmailInfo; + +import javax.annotation.Nullable; +import java.util.Date; + +/** + * Service for sending emails. + * + */ +public interface EmailService { + + String NAME = "cuba_EmailService"; + + /** + * Send email synchronously. + * + * @param address comma or semicolon separated list of addresses + * @param caption email subject + * @param body email body + * @param attachment email attachments + * @throws com.haulmont.cuba.core.global.EmailException + * in case of any errors + */ + void sendEmail(String address, String caption, String body, EmailAttachment... attachment) + throws EmailException; + + /** + * Send email synchronously. + * + * @param info email details + * @throws EmailException in case of any errors + */ + void sendEmail(EmailInfo info) throws EmailException; + + /** + * Send email asynchronously, with limited number of attempts. + *

+ * The actual sending is performed by invoking the {@code EmailerAPI.processQueuedEmails()} (e.g. from a scheduled task). + * + * @param info email details + * @param attemptsCount count of attempts to send (1 attempt = 1 emailer cron tick) + * @param deadline Emailer tries to send message till deadline. + * If deadline has come and message has not been sent, status of this message is changed to + * {@link com.haulmont.cuba.core.global.SendingStatus#NOTSENT} + */ + void sendEmailAsync(EmailInfo info, @Nullable Integer attemptsCount, @Nullable Date deadline); + + /** + * Send email asynchronously. + *

+ * The actual sending is performed by invoking the {@code EmailerAPI.processQueuedEmails()} (e.g. from a scheduled task). + * + * @param info email details + */ + void sendEmailAsync(EmailInfo info); + + /** + * Load content text for given message. + * + * @return email content text + */ + String loadContentText(SendingMessage sendingMessage); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/EntityLogService.java b/modules/global/src/com/haulmont/cuba/core/app/EntityLogService.java index aa2d376fb7..0058fa0834 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/EntityLogService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/EntityLogService.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -/** - * Supports entity log control from the client tier. - * - */ -public interface EntityLogService { - - String NAME = "cuba_EntityLogService"; - - boolean isEnabled(); - - void setEnabled(boolean enabled); - - void invalidateCache(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +/** + * Supports entity log control from the client tier. + * + */ +public interface EntityLogService { + + String NAME = "cuba_EntityLogService"; + + boolean isEnabled(); + + void setEnabled(boolean enabled); + + void invalidateCache(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/EntitySnapshotService.java b/modules/global/src/com/haulmont/cuba/core/app/EntitySnapshotService.java index 4c5a87d0b9..a38161a838 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/EntitySnapshotService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/EntitySnapshotService.java @@ -1,99 +1,99 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.global.View; -import com.haulmont.cuba.security.entity.User; - -import javax.annotation.Nullable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * Provides entity snapshots functionality. - */ -public interface EntitySnapshotService { - - String NAME = "cuba_EntitySnapshotService"; - - /** - * Get snapshots for entity by id - * @param metaClass Entity meta class - * @param id Entity id - * @return Snapshot list - */ - List getSnapshots(MetaClass metaClass, Object id); - - /** - * Create snapshot for entity and save it to database - * @param entity Entity - * @param view View - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view); - - /** - * Create snapshot for Entity with specific date and store it to database - * - * @param entity Entity - * @param view View - * @param snapshotDate Date - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate); - - /** - * Create snapshot for Entity with specific date and author and store it to database - * - * @param entity Entity - * @param view View - * @param snapshotDate Date - * @param author Author - * @return Snapshot - */ - EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author); - - /** - * Get entity from snapshot - * @param snapshot Snapshot - * @return Entity - */ - Entity extractEntity(EntitySnapshot snapshot); - - /** - * Get Diff for snapshots - * @param first First snapshot - * @param second Second snapshot - * @return Diff - */ - EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second); - - /** - * Translate snapshots for archival classes - * - * @param metaClass Metaclass - * @param id Entity Id - * @param classMapping Map of [OldClass -> NewClass] for migration - */ - void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.global.View; +import com.haulmont.cuba.security.entity.User; + +import javax.annotation.Nullable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * Provides entity snapshots functionality. + */ +public interface EntitySnapshotService { + + String NAME = "cuba_EntitySnapshotService"; + + /** + * Get snapshots for entity by id + * @param metaClass Entity meta class + * @param id Entity id + * @return Snapshot list + */ + List getSnapshots(MetaClass metaClass, Object id); + + /** + * Create snapshot for entity and save it to database + * @param entity Entity + * @param view View + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view); + + /** + * Create snapshot for Entity with specific date and store it to database + * + * @param entity Entity + * @param view View + * @param snapshotDate Date + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate); + + /** + * Create snapshot for Entity with specific date and author and store it to database + * + * @param entity Entity + * @param view View + * @param snapshotDate Date + * @param author Author + * @return Snapshot + */ + EntitySnapshot createSnapshot(Entity entity, View view, Date snapshotDate, User author); + + /** + * Get entity from snapshot + * @param snapshot Snapshot + * @return Entity + */ + Entity extractEntity(EntitySnapshot snapshot); + + /** + * Get Diff for snapshots + * @param first First snapshot + * @param second Second snapshot + * @return Diff + */ + EntityDiff getDifference(@Nullable EntitySnapshot first, EntitySnapshot second); + + /** + * Translate snapshots for archival classes + * + * @param metaClass Metaclass + * @param id Entity Id + * @param classMapping Map of [OldClass -> NewClass] for migration + */ + void migrateSnapshots(MetaClass metaClass, Object id, Map classMapping); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/FileStorageService.java b/modules/global/src/com/haulmont/cuba/core/app/FileStorageService.java index 808bffef39..6cc6558a2e 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/FileStorageService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/FileStorageService.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; - -/** - * Provides simple means to work with the file storage from the client tier. - *
- * Warning: files content is passed in byte arrays, which is acceptable only for relatively small files. Preferred - * way to work with file storage is through {@code FileUploadingAPI} and {@code FileDataProvider}. - */ -public interface FileStorageService { - - String NAME = "cuba_FileStorageService"; - - void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException; - - void removeFile(FileDescriptor fileDescr) throws FileStorageException; - - byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException; - - boolean fileExists(FileDescriptor fileDescr) throws FileStorageException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; + +/** + * Provides simple means to work with the file storage from the client tier. + *
+ * Warning: files content is passed in byte arrays, which is acceptable only for relatively small files. Preferred + * way to work with file storage is through {@code FileUploadingAPI} and {@code FileDataProvider}. + */ +public interface FileStorageService { + + String NAME = "cuba_FileStorageService"; + + void saveFile(FileDescriptor fileDescr, byte[] data) throws FileStorageException; + + void removeFile(FileDescriptor fileDescr) throws FileStorageException; + + byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException; + + boolean fileExists(FileDescriptor fileDescr) throws FileStorageException; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/FoldersService.java b/modules/global/src/com/haulmont/cuba/core/app/FoldersService.java index 1f6a1fe1c0..cb2b070920 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/FoldersService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/FoldersService.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.AppFolder; -import com.haulmont.cuba.core.entity.Folder; -import com.haulmont.cuba.security.entity.SearchFolder; - -import java.io.IOException; -import java.util.List; - -/** - * Folders pane support service. - * - */ -public interface FoldersService { - - String NAME = "cuba_FoldersService"; - - /** - * Load application folders available to a user. - * - * @return folders list - */ - List loadAppFolders(); - - /** - * Reload quantity and style information for supplied application folders. - * - * @param folders folders to reload - * @return reloaded folders list - */ - List reloadAppFolders(List folders); - - /** - * Load search folders for the current user. - * - * @return folders list - */ - List loadSearchFolders(); - - /** - * Export folder as zip archive. - * - * @param folder exported folder - * @return zip contents - * @throws IOException - */ - byte[] exportFolder(Folder folder) throws IOException; - - /** - * Import folder - * @param parentFolder - * @param bytes - * @return - * @throws IOException - */ - Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.AppFolder; +import com.haulmont.cuba.core.entity.Folder; +import com.haulmont.cuba.security.entity.SearchFolder; + +import java.io.IOException; +import java.util.List; + +/** + * Folders pane support service. + * + */ +public interface FoldersService { + + String NAME = "cuba_FoldersService"; + + /** + * Load application folders available to a user. + * + * @return folders list + */ + List loadAppFolders(); + + /** + * Reload quantity and style information for supplied application folders. + * + * @param folders folders to reload + * @return reloaded folders list + */ + List reloadAppFolders(List folders); + + /** + * Load search folders for the current user. + * + * @return folders list + */ + List loadSearchFolders(); + + /** + * Export folder as zip archive. + * + * @param folder exported folder + * @return zip contents + * @throws IOException + */ + byte[] exportFolder(Folder folder) throws IOException; + + /** + * Import folder + * @param parentFolder + * @param bytes + * @return + * @throws IOException + */ + Folder importFolder(Folder parentFolder, byte[] bytes) throws IOException; +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/LockService.java b/modules/global/src/com/haulmont/cuba/core/app/LockService.java index 4d8254ba26..98f4bace37 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/LockService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/LockService.java @@ -1,83 +1,83 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.LockInfo; - -import javax.annotation.Nullable; -import java.util.List; - -/** - * Service interface for pessimistic locking. - */ -public interface LockService { - - String NAME = "cuba_LockService"; - - /** - * Try to lock an arbitrary object. - * @param name locking object name - * @param id locking object ID - * @return - null in case of successful lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
- * - {@link LockInfo} instance in case of this object is already locked by someone - */ - @Nullable - LockInfo lock(String name, String id); - - /** - * Try to lock an entity. - * @param entity entity instance - * @return - null in case of successful lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this entity,
- * - {@link LockInfo} instance in case of this entity is already locked by someone - */ - @Nullable - LockInfo lock(Entity entity); - - /** - * Unlock an arbitrary object. - * @param name locking object name - * @param id locking object ID - */ - void unlock(String name, String id); - - /** - * Unlock an entity. - * @param entity entity instance - */ - void unlock(Entity entity); - - /** - * Get locking status for particular object - * @param name locking object name - * @param id locking object ID - * @return - null in case of no lock,
- * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
- * - {@link LockInfo} instance in case of this object is locked by someone - */ - @Nullable - LockInfo getLockInfo(String name, String id); - - /** - * List of current locks - */ - List getCurrentLocks(); - - void reloadConfiguration(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.LockInfo; + +import javax.annotation.Nullable; +import java.util.List; + +/** + * Service interface for pessimistic locking. + */ +public interface LockService { + + String NAME = "cuba_LockService"; + + /** + * Try to lock an arbitrary object. + * @param name locking object name + * @param id locking object ID + * @return - null in case of successful lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
+ * - {@link LockInfo} instance in case of this object is already locked by someone + */ + @Nullable + LockInfo lock(String name, String id); + + /** + * Try to lock an entity. + * @param entity entity instance + * @return - null in case of successful lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this entity,
+ * - {@link LockInfo} instance in case of this entity is already locked by someone + */ + @Nullable + LockInfo lock(Entity entity); + + /** + * Unlock an arbitrary object. + * @param name locking object name + * @param id locking object ID + */ + void unlock(String name, String id); + + /** + * Unlock an entity. + * @param entity entity instance + */ + void unlock(Entity entity); + + /** + * Get locking status for particular object + * @param name locking object name + * @param id locking object ID + * @return - null in case of no lock,
+ * - {@link com.haulmont.cuba.core.global.LockNotSupported} instance in case of locking is not configured for this object,
+ * - {@link LockInfo} instance in case of this object is locked by someone + */ + @Nullable + LockInfo getLockInfo(String name, String id); + + /** + * List of current locks + */ + List getCurrentLocks(); + + void reloadConfiguration(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/PersistenceManagerService.java b/modules/global/src/com/haulmont/cuba/core/app/PersistenceManagerService.java index 6d13a907eb..2ff6a245f9 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/PersistenceManagerService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/PersistenceManagerService.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -/** - * Exposes some of {@code PersistenceManagerAPI} methods and other DBMS-related information to the client tier. - * - */ -public interface PersistenceManagerService { - - String NAME = "cuba_PersistenceManagerService"; - - boolean useLazyCollection(String entityName); - - boolean useLookupScreen(String entityName); - - int getFetchUI(String entityName); - - int getMaxFetchUI(String entityName); - - /** - * @return current DBMS type set by {@code cuba.dbmsType} app property on Middleware - */ - String getDbmsType(); - - /** - * @return current DBMS version set by {@code cuba.dbmsVersion} app property on Middleware - */ - String getDbmsVersion(); - - /** - * @return regexp to extract a unique constraint name from an exception message. - *

See {@code DbmsFeatures.getUniqueConstraintViolationPattern()} - */ - String getUniqueConstraintViolationPattern(); - - /** - * @return default sort order of null values used by the current DBMS - */ - boolean isNullsLastSorting(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +/** + * Exposes some of {@code PersistenceManagerAPI} methods and other DBMS-related information to the client tier. + * + */ +public interface PersistenceManagerService { + + String NAME = "cuba_PersistenceManagerService"; + + boolean useLazyCollection(String entityName); + + boolean useLookupScreen(String entityName); + + int getFetchUI(String entityName); + + int getMaxFetchUI(String entityName); + + /** + * @return current DBMS type set by {@code cuba.dbmsType} app property on Middleware + */ + String getDbmsType(); + + /** + * @return current DBMS version set by {@code cuba.dbmsVersion} app property on Middleware + */ + String getDbmsVersion(); + + /** + * @return regexp to extract a unique constraint name from an exception message. + *

See {@code DbmsFeatures.getUniqueConstraintViolationPattern()} + */ + String getUniqueConstraintViolationPattern(); + + /** + * @return default sort order of null values used by the current DBMS + */ + boolean isNullsLastSorting(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/QueryResultsService.java b/modules/global/src/com/haulmont/cuba/core/app/QueryResultsService.java index e6d5d9ad8b..5c8a241242 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/QueryResultsService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/QueryResultsService.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app; - -import java.util.List; -import java.util.UUID; - -/** - * Interface provides functionality for working with previously selected query results - */ -public interface QueryResultsService { - String NAME = "cuba_QueryResultsService"; - - /** - * Stores {@code idList} collection as {@link com.haulmont.cuba.core.entity.QueryResult} records - */ - void insert(int queryKey, List idList); - - /** - * Deletes {@code QueryResult} records with given {@code queryKey} - */ - void delete(int queryKey); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app; + +import java.util.List; +import java.util.UUID; + +/** + * Interface provides functionality for working with previously selected query results + */ +public interface QueryResultsService { + String NAME = "cuba_QueryResultsService"; + + /** + * Stores {@code idList} collection as {@link com.haulmont.cuba.core.entity.QueryResult} records + */ + void insert(int queryKey, List idList); + + /** + * Deletes {@code QueryResult} records with given {@code queryKey} + */ + void delete(int queryKey); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/ServerInfoService.java b/modules/global/src/com/haulmont/cuba/core/app/ServerInfoService.java index fda290f839..e8668106fe 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/ServerInfoService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/ServerInfoService.java @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import java.util.List; -import java.util.TimeZone; - -/** - * Service interface to provide initial information for clients. Can be invoked before login when user session - * is not yet established. - * - */ -public interface ServerInfoService { - - String NAME = "cuba_ServerInfoService"; - - String getReleaseNumber(); - - String getReleaseTimestamp(); - - List getViews(); - - View getView(Class entityClass, String name); - - /** - * Return time zone used by server application. - * Useful for remote clients which may run on machines with another default time zone (like desktop client). - * - * @return server time zone - */ - TimeZone getTimeZone(); - - /** - * @return current time on the server in milliseconds - */ - long getTimeMillis(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import java.util.List; +import java.util.TimeZone; + +/** + * Service interface to provide initial information for clients. Can be invoked before login when user session + * is not yet established. + * + */ +public interface ServerInfoService { + + String NAME = "cuba_ServerInfoService"; + + String getReleaseNumber(); + + String getReleaseTimestamp(); + + List getViews(); + + View getView(Class entityClass, String name); + + /** + * Return time zone used by server application. + * Useful for remote clients which may run on machines with another default time zone (like desktop client). + * + * @return server time zone + */ + TimeZone getTimeZone(); + + /** + * @return current time on the server in milliseconds + */ + long getTimeMillis(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/UniqueNumbersService.java b/modules/global/src/com/haulmont/cuba/core/app/UniqueNumbersService.java index 961a4dd806..066aee5f49 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/UniqueNumbersService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/UniqueNumbersService.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.app; - -/** - * Provides sequences of unique numbers based on database sequences. - * - */ -public interface UniqueNumbersService { - - String NAME = "cuba_UniqueNumbersService"; - - /** - * Returns the next sequence value. - * - * @param domain sequence identifier - * @return next value - */ - long getNextNumber(String domain); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.app; + +/** + * Provides sequences of unique numbers based on database sequences. + * + */ +public interface UniqueNumbersService { + + String NAME = "cuba_UniqueNumbersService"; + + /** + * Returns the next sequence value. + * + * @param domain sequence identifier + * @return next value + */ + long getNextNumber(String domain); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheException.java b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheException.java index 8c7869023c..bae89a9df4 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheException.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheException.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.haulmont.cuba.core.global.SupportedByClient; - -/** - * @deprecated Will be removed in release 7.0 - */ -@Deprecated -@SupportedByClient -public class CacheException extends Exception { - private static final long serialVersionUID = 5306831032981161592L; - - public CacheException() { - } - - public CacheException(String message) { - super(message); - } - - public CacheException(String message, Throwable cause) { - super(message, cause); - } - - public CacheException(Throwable cause) { - super(cause); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.haulmont.cuba.core.global.SupportedByClient; + +/** + * @deprecated Will be removed in release 7.0 + */ +@Deprecated +@SupportedByClient +public class CacheException extends Exception { + private static final long serialVersionUID = 5306831032981161592L; + + public CacheException() { + } + + public CacheException(String message) { + super(message); + } + + public CacheException(String message, Throwable cause) { + super(message, cause); + } + + public CacheException(Throwable cause) { + super(cause); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSelector.java b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSelector.java index 3369495071..d63789a15c 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSelector.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSelector.java @@ -1,29 +1,29 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import java.util.Collection; - -/** - * Select items from CacheSet - * - */ -@Deprecated -public interface CacheSelector { - Collection select(CacheSet cacheSet); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import java.util.Collection; + +/** + * Select items from CacheSet + * + */ +@Deprecated +public interface CacheSelector { + Collection select(CacheSet cacheSet); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSet.java b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSet.java index b570634bc9..51468fdade 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSet.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheSet.java @@ -1,327 +1,327 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.google.common.collect.Sets; -import com.haulmont.bali.datastruct.Pair; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.Predicate; - -import java.util.*; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Set of elements for ObjectsCache. - * - * @deprecated Will be removed in release 7.0 - */ -@SuppressWarnings({"unused"}) -@Deprecated -public class CacheSet implements Cloneable { - protected boolean forUpdate = false; - protected Set addedItems = Sets.newHashSet(); - protected Set removedItems = Sets.newHashSet(); - - private Collection items; - - public CacheSet() { - this(Collections.emptyList()); - } - - public CacheSet(Collection items) { - this.items = items; - } - - public Collection getItems() { - if (isForUpdate()) { - return new DifferencesDecorator<>(items); - } else { - return items; - } - } - - public boolean isForUpdate() { - return forUpdate; - } - - public void setForUpdate(boolean forUpdate) { - this.forUpdate = forUpdate; - } - - - public Set getAddedItems() { - return addedItems; - } - - public void setAddedItems(Set addedItems) { - this.addedItems = addedItems; - } - - public Set getRemovedItems() { - return removedItems; - } - - public void setRemovedItems(Set removedItems) { - this.removedItems = removedItems; - } - - /** - * Single predicate query - * - * @param selector Selector - * @return CacheSet - */ - public CacheSet query(Predicate selector) { - checkNotNull(selector); - - LinkedList setItems = new LinkedList<>(); - CollectionUtils.select(items, selector, setItems); - return new CacheSet(setItems); - } - - /** - * Sequential filtering by selectors - * - * @param selectors Selectors - * @return CacheSet - */ - public CacheSet querySequential(Predicate... selectors) { - checkNotNull(selectors); - - Collection resultCollection = new ArrayList<>(items); - Collection filterCollection = new LinkedList<>(); - Collection tempCollection; - - int i = 0; - while ((i < selectors.length) && (resultCollection.size() > 0)) { - CollectionUtils.select(resultCollection, selectors[i], filterCollection); - - tempCollection = resultCollection; - resultCollection = filterCollection; - filterCollection = tempCollection; - - filterCollection.clear(); - i++; - } - - return new CacheSet(resultCollection); - } - - /** - * Conjunction count matches - * - * @param selectors Selectors - * @return CacheSet - */ - public int countConjunction(Predicate... selectors) { - checkNotNull(selectors); - - ConjunctionPredicate predicate = new ConjunctionPredicate(selectors); - - return CollectionUtils.countMatches(items, predicate); - } - - public Pair countConjunction(Collection selectors, Predicate amplifyingSelector) { - checkNotNull(selectors); - checkNotNull(amplifyingSelector); - - ConjunctionPredicate conjunctionPredicate = new ConjunctionPredicate(selectors); - - int count1 = 0; - int count2 = 0; - - for (Object item : items) { - if (conjunctionPredicate.evaluate(item)) { - count1++; - if (amplifyingSelector.evaluate(item)) { - count2++; - } - } - } - - return new Pair<>(count1, count2); - } - - /** - * Conjunction filtering by selectors - * - * @param selectors Selectors - * @return CacheSet - */ - public CacheSet queryConjunction(Predicate... selectors) { - return query(new ConjunctionPredicate(selectors)); - } - - @Override - public Object clone() throws CloneNotSupportedException { - CacheSet cloneInstance = (CacheSet) super.clone(); - cloneInstance.items = new ArrayList<>(items); - return cloneInstance; - } - - /** - * Size - * - * @return Cache set size - */ - public int getSize() { - return (items != null) ? items.size() : 0; - } - - /** - * Predicate with conjunction operation - */ - public static class ConjunctionPredicate implements Predicate { - - private Predicate[] selectors; - - public ConjunctionPredicate(Predicate... selectors) { - checkNotNull(selectors); - this.selectors = selectors; - } - - public ConjunctionPredicate(Collection selectors) { - checkNotNull(selectors); - - this.selectors = new Predicate[selectors.size()]; - int i = 0; - for (Predicate selector : selectors) { - this.selectors[i++] = selector; - } - } - - @Override - public boolean evaluate(Object object) { - checkNotNull(selectors); - for (Predicate p : selectors) { - if (!p.evaluate(object)) - return false; - } - return true; - } - } - - public class DifferencesDecorator implements Collection { - protected Collection items; - - - public DifferencesDecorator(Collection items) { - this.items = items; - } - - @Override - public int size() { - return items.size(); - } - - @Override - public boolean isEmpty() { - return items.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return items.contains(o); - } - - @Override - public Iterator iterator() { - return new IteratorDecorator(items.iterator()); - } - - @Override - public Object[] toArray() { - return items.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return items.toArray(a); - } - - @Override - public boolean add(E o) { - addedItems.add(o); - return items.add(o); - } - - @Override - public boolean remove(Object o) { - removedItems.add(o); - return items.remove(o); - } - - @Override - public boolean containsAll(Collection c) { - return items.containsAll(c); - } - - @Override - public boolean addAll(Collection c) { - addedItems.addAll(c); - return items.addAll(c); - } - - @Override - public boolean retainAll(Collection c) { - for (E item : items) { - if (!c.contains(item)) - removedItems.add(item); - } - return items.retainAll(c); - } - - @Override - public boolean removeAll(Collection c) { - removedItems.addAll(c); - return items.removeAll(c); - } - - @Override - public void clear() { - items.clear(); - } - - protected class IteratorDecorator implements Iterator { - protected Iterator iterator; - protected E current; - - public IteratorDecorator(Iterator iterator) { - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public E next() { - current = iterator.next(); - return current; - } - - @Override - public void remove() { - removedItems.add(current); - iterator.remove(); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.google.common.collect.Sets; +import com.haulmont.bali.datastruct.Pair; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; + +import java.util.*; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Set of elements for ObjectsCache. + * + * @deprecated Will be removed in release 7.0 + */ +@SuppressWarnings({"unused"}) +@Deprecated +public class CacheSet implements Cloneable { + protected boolean forUpdate = false; + protected Set addedItems = Sets.newHashSet(); + protected Set removedItems = Sets.newHashSet(); + + private Collection items; + + public CacheSet() { + this(Collections.emptyList()); + } + + public CacheSet(Collection items) { + this.items = items; + } + + public Collection getItems() { + if (isForUpdate()) { + return new DifferencesDecorator<>(items); + } else { + return items; + } + } + + public boolean isForUpdate() { + return forUpdate; + } + + public void setForUpdate(boolean forUpdate) { + this.forUpdate = forUpdate; + } + + + public Set getAddedItems() { + return addedItems; + } + + public void setAddedItems(Set addedItems) { + this.addedItems = addedItems; + } + + public Set getRemovedItems() { + return removedItems; + } + + public void setRemovedItems(Set removedItems) { + this.removedItems = removedItems; + } + + /** + * Single predicate query + * + * @param selector Selector + * @return CacheSet + */ + public CacheSet query(Predicate selector) { + checkNotNull(selector); + + LinkedList setItems = new LinkedList<>(); + CollectionUtils.select(items, selector, setItems); + return new CacheSet(setItems); + } + + /** + * Sequential filtering by selectors + * + * @param selectors Selectors + * @return CacheSet + */ + public CacheSet querySequential(Predicate... selectors) { + checkNotNull(selectors); + + Collection resultCollection = new ArrayList<>(items); + Collection filterCollection = new LinkedList<>(); + Collection tempCollection; + + int i = 0; + while ((i < selectors.length) && (resultCollection.size() > 0)) { + CollectionUtils.select(resultCollection, selectors[i], filterCollection); + + tempCollection = resultCollection; + resultCollection = filterCollection; + filterCollection = tempCollection; + + filterCollection.clear(); + i++; + } + + return new CacheSet(resultCollection); + } + + /** + * Conjunction count matches + * + * @param selectors Selectors + * @return CacheSet + */ + public int countConjunction(Predicate... selectors) { + checkNotNull(selectors); + + ConjunctionPredicate predicate = new ConjunctionPredicate(selectors); + + return CollectionUtils.countMatches(items, predicate); + } + + public Pair countConjunction(Collection selectors, Predicate amplifyingSelector) { + checkNotNull(selectors); + checkNotNull(amplifyingSelector); + + ConjunctionPredicate conjunctionPredicate = new ConjunctionPredicate(selectors); + + int count1 = 0; + int count2 = 0; + + for (Object item : items) { + if (conjunctionPredicate.evaluate(item)) { + count1++; + if (amplifyingSelector.evaluate(item)) { + count2++; + } + } + } + + return new Pair<>(count1, count2); + } + + /** + * Conjunction filtering by selectors + * + * @param selectors Selectors + * @return CacheSet + */ + public CacheSet queryConjunction(Predicate... selectors) { + return query(new ConjunctionPredicate(selectors)); + } + + @Override + public Object clone() throws CloneNotSupportedException { + CacheSet cloneInstance = (CacheSet) super.clone(); + cloneInstance.items = new ArrayList<>(items); + return cloneInstance; + } + + /** + * Size + * + * @return Cache set size + */ + public int getSize() { + return (items != null) ? items.size() : 0; + } + + /** + * Predicate with conjunction operation + */ + public static class ConjunctionPredicate implements Predicate { + + private Predicate[] selectors; + + public ConjunctionPredicate(Predicate... selectors) { + checkNotNull(selectors); + this.selectors = selectors; + } + + public ConjunctionPredicate(Collection selectors) { + checkNotNull(selectors); + + this.selectors = new Predicate[selectors.size()]; + int i = 0; + for (Predicate selector : selectors) { + this.selectors[i++] = selector; + } + } + + @Override + public boolean evaluate(Object object) { + checkNotNull(selectors); + for (Predicate p : selectors) { + if (!p.evaluate(object)) + return false; + } + return true; + } + } + + public class DifferencesDecorator implements Collection { + protected Collection items; + + + public DifferencesDecorator(Collection items) { + this.items = items; + } + + @Override + public int size() { + return items.size(); + } + + @Override + public boolean isEmpty() { + return items.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return items.contains(o); + } + + @Override + public Iterator iterator() { + return new IteratorDecorator(items.iterator()); + } + + @Override + public Object[] toArray() { + return items.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return items.toArray(a); + } + + @Override + public boolean add(E o) { + addedItems.add(o); + return items.add(o); + } + + @Override + public boolean remove(Object o) { + removedItems.add(o); + return items.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return items.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + addedItems.addAll(c); + return items.addAll(c); + } + + @Override + public boolean retainAll(Collection c) { + for (E item : items) { + if (!c.contains(item)) + removedItems.add(item); + } + return items.retainAll(c); + } + + @Override + public boolean removeAll(Collection c) { + removedItems.addAll(c); + return items.removeAll(c); + } + + @Override + public void clear() { + items.clear(); + } + + protected class IteratorDecorator implements Iterator { + protected Iterator iterator; + protected E current; + + public IteratorDecorator(Iterator iterator) { + this.iterator = iterator; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public E next() { + current = iterator.next(); + return current; + } + + @Override + public void remove() { + removedItems.add(current); + iterator.remove(); + } + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheStatistics.java b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheStatistics.java index acf12eb22d..6c65ce5a3a 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/CacheStatistics.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/CacheStatistics.java @@ -1,93 +1,93 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import java.util.Date; - -/** - * Statistics cache life cycle - * - * @deprecated Will be removed in release 7.0 - */ -@Deprecated -public class CacheStatistics { - - private String cacheName; - private int objectsCount = 0; - - private Date lastUpdateTime; - private long lastUpdateDuration; - private long averageUpdateDuration; - - public CacheStatistics(ObjectsCacheInstance cacheInstance) { - this.cacheName = cacheInstance.getName(); - } - - public String getCacheName() { - return cacheName; - } - - public int getObjectsCount() { - return objectsCount; - } - - public void setObjectsCount(int objectsCount) { - this.objectsCount = objectsCount; - } - - public Date getLastUpdateTime() { - return lastUpdateTime; - } - - public void setLastUpdateTime(Date lastUpdateTime) { - this.lastUpdateTime = lastUpdateTime; - } - - public long getLastUpdateDuration() { - return lastUpdateDuration; - } - - public void setLastUpdateDuration(long lastUpdateDuration) { - this.lastUpdateDuration = lastUpdateDuration; - } - - public long getAverageUpdateDuration() { - return averageUpdateDuration; - } - - public void setAverageUpdateDuration(long averageUpdateDuration) { - this.averageUpdateDuration = averageUpdateDuration; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append("Cache: ").append(cacheName).append("\n"); - sb.append("Count: ").append(objectsCount).append("\n"); - - if (lastUpdateTime != null) - sb.append("Last update: ").append(lastUpdateTime).append("\n"); - - sb.append("Last update duration: ").append(lastUpdateDuration).append(" millis \n"); - - sb.append("Average update duration: ").append(averageUpdateDuration).append(" millis \n"); - - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import java.util.Date; + +/** + * Statistics cache life cycle + * + * @deprecated Will be removed in release 7.0 + */ +@Deprecated +public class CacheStatistics { + + private String cacheName; + private int objectsCount = 0; + + private Date lastUpdateTime; + private long lastUpdateDuration; + private long averageUpdateDuration; + + public CacheStatistics(ObjectsCacheInstance cacheInstance) { + this.cacheName = cacheInstance.getName(); + } + + public String getCacheName() { + return cacheName; + } + + public int getObjectsCount() { + return objectsCount; + } + + public void setObjectsCount(int objectsCount) { + this.objectsCount = objectsCount; + } + + public Date getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(Date lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public long getLastUpdateDuration() { + return lastUpdateDuration; + } + + public void setLastUpdateDuration(long lastUpdateDuration) { + this.lastUpdateDuration = lastUpdateDuration; + } + + public long getAverageUpdateDuration() { + return averageUpdateDuration; + } + + public void setAverageUpdateDuration(long averageUpdateDuration) { + this.averageUpdateDuration = averageUpdateDuration; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("Cache: ").append(cacheName).append("\n"); + sb.append("Count: ").append(objectsCount).append("\n"); + + if (lastUpdateTime != null) + sb.append("Last update: ").append(lastUpdateTime).append("\n"); + + sb.append("Last update duration: ").append(lastUpdateDuration).append(" millis \n"); + + sb.append("Average update duration: ").append(averageUpdateDuration).append(" millis \n"); + + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheController.java b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheController.java index 9f65b4dc05..fa8801202d 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheController.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheController.java @@ -1,46 +1,46 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import java.util.Map; - -/** - * Interface defining methods for manage cache content and modify cache properties in runtime - * - * @deprecated Will be removed in release 7.0 - */ -@Deprecated -public interface ObjectsCacheController { - - /** - * Get a controllable cache - * @return Cache instance - */ - ObjectsCacheInstance getCache(); - - /** - * Reload cache content - */ - void reloadCache(); - - /** - * Update cache content - * @param params Update params - */ - void updateCache(Map params); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import java.util.Map; + +/** + * Interface defining methods for manage cache content and modify cache properties in runtime + * + * @deprecated Will be removed in release 7.0 + */ +@Deprecated +public interface ObjectsCacheController { + + /** + * Get a controllable cache + * @return Cache instance + */ + ObjectsCacheInstance getCache(); + + /** + * Reload cache content + */ + void reloadCache(); + + /** + * Update cache content + * @param params Update params + */ + void updateCache(Map params); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheInstance.java b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheInstance.java index 94890ebf1e..c6f41dd32c 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheInstance.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheInstance.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import com.haulmont.bali.datastruct.Pair; -import org.apache.commons.collections4.Predicate; - -import java.util.Collection; - -/** - * Objects cache interface. - * - * @deprecated Will be removed in release 7.0 - */ -@Deprecated -public interface ObjectsCacheInstance { - String getName(); - - CacheStatistics getStatistics(); - - Collection execute(CacheSelector cacheSelector); - - int count(Predicate... selectors); - - Pair count(Collection selectors, Predicate amplifyingSelector); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import com.haulmont.bali.datastruct.Pair; +import org.apache.commons.collections4.Predicate; + +import java.util.Collection; + +/** + * Objects cache interface. + * + * @deprecated Will be removed in release 7.0 + */ +@Deprecated +public interface ObjectsCacheInstance { + String getName(); + + CacheStatistics getStatistics(); + + Collection execute(CacheSelector cacheSelector); + + int count(Predicate... selectors); + + Pair count(Collection selectors, Predicate amplifyingSelector); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerService.java b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerService.java index db55eb14dc..76d9cfefa5 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/cache/ObjectsCacheManagerService.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.cache; - -import java.util.Map; - -/** - * Service for manage application caches. - * - * @deprecated Will be removed in release 7.0. - */ -@Deprecated -public interface ObjectsCacheManagerService { - String NAME = "cuba_ObjectsCacheManagerService"; - - /** - * Update cache content - * @param cacheName Cache instance name - * @param params Params for update - */ - void updateCache(String cacheName, Map params); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.cache; + +import java.util.Map; + +/** + * Service for manage application caches. + * + * @deprecated Will be removed in release 7.0. + */ +@Deprecated +public interface ObjectsCacheManagerService { + String NAME = "cuba_ObjectsCacheManagerService"; + + /** + * Update cache content + * @param cacheName Cache instance name + * @param params Params for update + */ + void updateCache(String cacheName, Map params); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributes.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributes.java index 7cce24a839..0ca44ca911 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributes.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributes.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; - -import javax.annotation.Nullable; -import java.util.Collection; - -public interface DynamicAttributes { - String NAME = "cuba_DynamicAttributesService"; - - /** - * Get all categories linked with metaClass from cache - */ - Collection getCategoriesForMetaClass(MetaClass metaClass); - - /** - * Get all categories attributes for metaClass from cache - */ - Collection getAttributesForMetaClass(MetaClass metaClass); - - /** - * Get certain category attribute for metaClass by attribute's code - */ - @Nullable - CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; + +import javax.annotation.Nullable; +import java.util.Collection; + +public interface DynamicAttributes { + String NAME = "cuba_DynamicAttributesService"; + + /** + * Get all categories linked with metaClass from cache + */ + Collection getCategoriesForMetaClass(MetaClass metaClass); + + /** + * Get all categories attributes for metaClass from cache + */ + Collection getAttributesForMetaClass(MetaClass metaClass); + + /** + * Get certain category attribute for metaClass by attribute's code + */ + @Nullable + CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCache.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCache.java index 0edbf8b333..21b982553c 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCache.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCache.java @@ -1,97 +1,97 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.google.common.collect.Multimap; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; -import java.io.Serializable; -import java.util.*; - -@Immutable -public class DynamicAttributesCache implements Serializable { - protected final Multimap categoriesCache; - protected final Map> attributesCache; - protected final Date creationDate; - - public DynamicAttributesCache(Multimap categoriesCache, - Map> attributesCache, - Date creationDate) { - this.categoriesCache = categoriesCache; - this.attributesCache = attributesCache; - this.creationDate = creationDate; - } - - public Collection getCategoriesForMetaClass(MetaClass metaClass) { - MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); - return new ArrayList<>(categoriesCache.get(targetMetaClass.getName())); - } - - public Collection getAttributesForMetaClass(MetaClass metaClass) { - MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); - Collection categories = categoriesCache.get(targetMetaClass.getName()); - List categoryAttributes = new ArrayList<>(); - for (Category category : categories) { - categoryAttributes.addAll(Collections2.filter(category.getCategoryAttrs(), new Predicate() { - @Override - public boolean apply(@Nullable CategoryAttribute input) { - return input != null && StringUtils.isNotBlank(input.getCode()); - } - })); - } - return categoryAttributes; - } - - @Nullable - public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { - code = DynamicAttributesUtils.decodeAttributeCode(code); - MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); - Map attributes = attributesCache.get(targetMetaClass.getName()); - if (attributes != null) { - return attributes.get(code); - } - - return null; - } - - protected MetaClass resolveTargetMetaClass(MetaClass metaClass) { - if (metaClass == null) { - return null; - } - - Metadata metadata = AppBeans.get(Metadata.NAME); - MetaClass targetMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); - if (targetMetaClass == null) { - targetMetaClass = metaClass; - } - return targetMetaClass; - } - - public Date getCreationDate() { - return creationDate; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Multimap; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import java.io.Serializable; +import java.util.*; + +@Immutable +public class DynamicAttributesCache implements Serializable { + protected final Multimap categoriesCache; + protected final Map> attributesCache; + protected final Date creationDate; + + public DynamicAttributesCache(Multimap categoriesCache, + Map> attributesCache, + Date creationDate) { + this.categoriesCache = categoriesCache; + this.attributesCache = attributesCache; + this.creationDate = creationDate; + } + + public Collection getCategoriesForMetaClass(MetaClass metaClass) { + MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); + return new ArrayList<>(categoriesCache.get(targetMetaClass.getName())); + } + + public Collection getAttributesForMetaClass(MetaClass metaClass) { + MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); + Collection categories = categoriesCache.get(targetMetaClass.getName()); + List categoryAttributes = new ArrayList<>(); + for (Category category : categories) { + categoryAttributes.addAll(Collections2.filter(category.getCategoryAttrs(), new Predicate() { + @Override + public boolean apply(@Nullable CategoryAttribute input) { + return input != null && StringUtils.isNotBlank(input.getCode()); + } + })); + } + return categoryAttributes; + } + + @Nullable + public CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { + code = DynamicAttributesUtils.decodeAttributeCode(code); + MetaClass targetMetaClass = resolveTargetMetaClass(metaClass); + Map attributes = attributesCache.get(targetMetaClass.getName()); + if (attributes != null) { + return attributes.get(code); + } + + return null; + } + + protected MetaClass resolveTargetMetaClass(MetaClass metaClass) { + if (metaClass == null) { + return null; + } + + Metadata metadata = AppBeans.get(Metadata.NAME); + MetaClass targetMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); + if (targetMetaClass == null) { + targetMetaClass = metaClass; + } + return targetMetaClass; + } + + public Date getCreationDate() { + return creationDate; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheService.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheService.java index a5872a34aa..60cb45d018 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesCacheService.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import javax.annotation.Nullable; -import java.util.Date; - -public interface DynamicAttributesCacheService { - String NAME = "cuba_DynamicAttributesCacheService"; - - /** - * Reload dynamic attributes cache from database - */ - void loadCache(); - - @Nullable - DynamicAttributesCache getCacheIfNewer(Date clientCacheDate); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import javax.annotation.Nullable; +import java.util.Date; + +public interface DynamicAttributesCacheService { + String NAME = "cuba_DynamicAttributesCacheService"; + + /** + * Reload dynamic attributes cache from database + */ + void loadCache(); + + @Nullable + DynamicAttributesCache getCacheIfNewer(Date clientCacheDate); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaClass.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaClass.java index 01045cf80d..4b8467b350 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaClass.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaClass.java @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaModel; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.impl.MetadataObjectImpl; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; - -import javax.annotation.Nullable; -import java.util.*; - -public class DynamicAttributesMetaClass extends MetadataObjectImpl implements MetaClass { - - private Map properties = new LinkedHashMap<>(); - private Map attributes = new LinkedHashMap<>(); - - public void addProperty(MetaProperty property, CategoryAttribute attribute) { - properties.put(property.getName(), property); - attributes.put(property.getName(), attribute); - } - - @Nullable - @Override - public MetaClass getAncestor() { - return null; - } - - @Override - public List getAncestors() { - return Collections.emptyList(); - } - - @Override - public Collection getDescendants() { - return Collections.emptyList(); - } - - @Override - public MetaModel getModel() { - return null; // temporary metaclass - } - - @Override - public Class getJavaClass() { - return Object.class; - } - - @Override - public MetaProperty getProperty(String name) { - return properties.get(name); - } - - @Override - public MetaProperty getPropertyNN(String name) { - MetaProperty property = getProperty(name); - if (property == null) - throw new IllegalArgumentException("Property '" + name + "' not found in " + getName()); - return property; - } - - @Override - public MetaPropertyPath getPropertyPath(String propertyPath) { - MetaProperty currentProperty; - - currentProperty = this.getProperty(propertyPath); - if (currentProperty == null) return null; - - return new MetaPropertyPath(this, currentProperty); - } - - @Override - public Collection getOwnProperties() { - return properties.values(); - } - - @Override - public Collection getProperties() { - return properties.values(); - } - - public Collection getPropertiesFilteredByCategory(final Category category) { - return Collections2.filter(getProperties(), new Predicate() { - @Override - public boolean apply(@Nullable MetaProperty input) { - if (input != null && category != null) { - CategoryAttribute categoryAttribute = attributes.get(input.getName()); - return category.equals(categoryAttribute.getCategory()); - } else { - return false; - } - } - }); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaModel; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.impl.MetadataObjectImpl; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; + +import javax.annotation.Nullable; +import java.util.*; + +public class DynamicAttributesMetaClass extends MetadataObjectImpl implements MetaClass { + + private Map properties = new LinkedHashMap<>(); + private Map attributes = new LinkedHashMap<>(); + + public void addProperty(MetaProperty property, CategoryAttribute attribute) { + properties.put(property.getName(), property); + attributes.put(property.getName(), attribute); + } + + @Nullable + @Override + public MetaClass getAncestor() { + return null; + } + + @Override + public List getAncestors() { + return Collections.emptyList(); + } + + @Override + public Collection getDescendants() { + return Collections.emptyList(); + } + + @Override + public MetaModel getModel() { + return null; // temporary metaclass + } + + @Override + public Class getJavaClass() { + return Object.class; + } + + @Override + public MetaProperty getProperty(String name) { + return properties.get(name); + } + + @Override + public MetaProperty getPropertyNN(String name) { + MetaProperty property = getProperty(name); + if (property == null) + throw new IllegalArgumentException("Property '" + name + "' not found in " + getName()); + return property; + } + + @Override + public MetaPropertyPath getPropertyPath(String propertyPath) { + MetaProperty currentProperty; + + currentProperty = this.getProperty(propertyPath); + if (currentProperty == null) return null; + + return new MetaPropertyPath(this, currentProperty); + } + + @Override + public Collection getOwnProperties() { + return properties.values(); + } + + @Override + public Collection getProperties() { + return properties.values(); + } + + public Collection getPropertiesFilteredByCategory(final Category category) { + return Collections2.filter(getProperties(), new Predicate() { + @Override + public boolean apply(@Nullable MetaProperty input) { + if (input != null && category != null) { + CategoryAttribute categoryAttribute = attributes.get(input.getName()); + return category.equals(categoryAttribute.getCategory()); + } else { + return false; + } + } + }); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaProperty.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaProperty.java index de5f6ddf17..036b27d2a4 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaProperty.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesMetaProperty.java @@ -1,160 +1,160 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.*; -import com.haulmont.chile.core.model.impl.ClassRange; -import com.haulmont.chile.core.model.impl.DatatypeRange; -import com.haulmont.chile.core.model.impl.MetadataObjectImpl; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; - -/** - * Specific MetaProperty for dynamic attribute. - * - */ -public class DynamicAttributesMetaProperty extends MetadataObjectImpl implements MetaProperty { - - private static final long serialVersionUID = 839160118855669248L; - - protected final MetaClass metaClass; - protected final transient Range range; - protected final Class javaClass; - protected final Boolean mandatory; - protected final AnnotatedElement annotatedElement = new FakeAnnotatedElement(); - protected final CategoryAttribute attribute; - protected final Type type; - - public DynamicAttributesMetaProperty(MetaClass metaClass, CategoryAttribute attribute) { - this.attribute = attribute; - this.javaClass = DynamicAttributesUtils.getAttributeClass(attribute); - this.metaClass = metaClass; - this.name = DynamicAttributesUtils.encodeAttributeCode(attribute.getCode()); - this.mandatory = attribute.getRequired(); - - Metadata metadata = AppBeans.get(Metadata.NAME); - Session metadataSession = metadata.getSession(); - if (Entity.class.isAssignableFrom(javaClass)) { - range = new ClassRange(metadataSession.getClass(javaClass)); - this.type = Type.ASSOCIATION; - } else { - this.range = new DatatypeRange(Datatypes.getNN(javaClass)); - this.type = Type.DATATYPE; - } - } - - @Override - public MetaModel getModel() { - return metaClass.getModel(); - } - - @Override - public MetaClass getDomain() { - return metaClass; - } - - @Override - public Range getRange() { - return range; - } - - @Override - public Type getType() { - return type; - } - - @Override - public boolean isMandatory() { - return Boolean.TRUE.equals(mandatory); - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - public MetaProperty getInverse() { - return null; - } - - @Override - public AnnotatedElement getAnnotatedElement() { - return annotatedElement; - } - - @Override - public Class getJavaType() { - return javaClass; - } - - @Override - public Class getDeclaringClass() { - return null; - } - - protected static class FakeAnnotatedElement implements AnnotatedElement, Serializable { - - @Override - public boolean isAnnotationPresent(Class annotationClass) { - return false; - } - - @Override - public T getAnnotation(Class annotationClass) { - return null; - } - - @Override - public Annotation[] getAnnotations() { - return new Annotation[0]; - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return new Annotation[0]; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof DynamicAttributesMetaProperty)) return false; - - DynamicAttributesMetaProperty that = (DynamicAttributesMetaProperty) o; - - return metaClass.equals(that.metaClass) && name.equals(that.name); - - } - - @Override - public int hashCode() { - return 31 * metaClass.hashCode() + name.hashCode(); - } - - public CategoryAttribute getAttribute() { - return attribute; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.*; +import com.haulmont.chile.core.model.impl.ClassRange; +import com.haulmont.chile.core.model.impl.DatatypeRange; +import com.haulmont.chile.core.model.impl.MetadataObjectImpl; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; + +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; + +/** + * Specific MetaProperty for dynamic attribute. + * + */ +public class DynamicAttributesMetaProperty extends MetadataObjectImpl implements MetaProperty { + + private static final long serialVersionUID = 839160118855669248L; + + protected final MetaClass metaClass; + protected final transient Range range; + protected final Class javaClass; + protected final Boolean mandatory; + protected final AnnotatedElement annotatedElement = new FakeAnnotatedElement(); + protected final CategoryAttribute attribute; + protected final Type type; + + public DynamicAttributesMetaProperty(MetaClass metaClass, CategoryAttribute attribute) { + this.attribute = attribute; + this.javaClass = DynamicAttributesUtils.getAttributeClass(attribute); + this.metaClass = metaClass; + this.name = DynamicAttributesUtils.encodeAttributeCode(attribute.getCode()); + this.mandatory = attribute.getRequired(); + + Metadata metadata = AppBeans.get(Metadata.NAME); + Session metadataSession = metadata.getSession(); + if (Entity.class.isAssignableFrom(javaClass)) { + range = new ClassRange(metadataSession.getClass(javaClass)); + this.type = Type.ASSOCIATION; + } else { + this.range = new DatatypeRange(Datatypes.getNN(javaClass)); + this.type = Type.DATATYPE; + } + } + + @Override + public MetaModel getModel() { + return metaClass.getModel(); + } + + @Override + public MetaClass getDomain() { + return metaClass; + } + + @Override + public Range getRange() { + return range; + } + + @Override + public Type getType() { + return type; + } + + @Override + public boolean isMandatory() { + return Boolean.TRUE.equals(mandatory); + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + public MetaProperty getInverse() { + return null; + } + + @Override + public AnnotatedElement getAnnotatedElement() { + return annotatedElement; + } + + @Override + public Class getJavaType() { + return javaClass; + } + + @Override + public Class getDeclaringClass() { + return null; + } + + protected static class FakeAnnotatedElement implements AnnotatedElement, Serializable { + + @Override + public boolean isAnnotationPresent(Class annotationClass) { + return false; + } + + @Override + public T getAnnotation(Class annotationClass) { + return null; + } + + @Override + public Annotation[] getAnnotations() { + return new Annotation[0]; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return new Annotation[0]; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DynamicAttributesMetaProperty)) return false; + + DynamicAttributesMetaProperty that = (DynamicAttributesMetaProperty) o; + + return metaClass.equals(that.metaClass) && name.equals(that.name); + + } + + @Override + public int hashCode() { + return 31 * metaClass.hashCode() + name.hashCode(); + } + + public CategoryAttribute getAttribute() { + return attribute; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesUtils.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesUtils.java index ff0ee80b32..19de2f54c4 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesUtils.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/DynamicAttributesUtils.java @@ -1,158 +1,158 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -import com.google.common.base.Joiner; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MetadataTools; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -public final class DynamicAttributesUtils { - private DynamicAttributesUtils() { - } - - /** - * Get special meta property path object for dynamic attribute - */ - public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, CategoryAttribute attribute) { - MetaProperty metaProperty = new DynamicAttributesMetaProperty(metaClass, attribute); - return new MetaPropertyPath(metaClass, metaProperty); - } - - /** - * Get special meta property path object for dynamic attribute by code - */ - @Nullable - public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, String attributeCode) { - attributeCode = decodeAttributeCode(attributeCode); - CategoryAttribute attribute = AppBeans.get(DynamicAttributes.NAME, DynamicAttributes.class) - .getAttributeForMetaClass(metaClass, attributeCode); - - if (attribute != null) { - return getMetaPropertyPath(metaClass, attribute); - } else { - return null; - } - } - - /** - * Get special meta property path object for dynamic attribute id - */ - @Nullable - public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, UUID attributeId) { - Collection attributes = AppBeans.get(DynamicAttributes.NAME, DynamicAttributes.class) - .getAttributesForMetaClass(metaClass); - CategoryAttribute attribute = null; - for (CategoryAttribute theAttribute : attributes) { - if (theAttribute.getId().equals(attributeId)) { - attribute = theAttribute; - break; - } - } - - if (attribute != null) { - return getMetaPropertyPath(metaClass, attribute); - } else { - return null; - } - } - - /** - * Remove dynamic attribute marker (+) from attribute code (if exists) - */ - public static String decodeAttributeCode(String attributeCode) { - return attributeCode.startsWith("+") ? attributeCode.substring(1) : attributeCode; - } - - /** - * Add dynamic attribute marker (+) to attribute code (if does not exist) - */ - public static String encodeAttributeCode(String attributeCode) { - return attributeCode.startsWith("+") ? attributeCode : "+" + attributeCode; - } - - /** - * Check if the name has dynamic attribute marker - */ - public static boolean isDynamicAttribute(String name) { - return name.startsWith("+"); - } - - /** - * Check if the meta property is dynamic attribute property - */ - public static boolean isDynamicAttribute(MetaProperty metaProperty) { - return metaProperty instanceof DynamicAttributesMetaProperty; - } - - public static CategoryAttribute getCategoryAttribute(MetaProperty metaProperty) { - return ((DynamicAttributesMetaProperty) metaProperty).getAttribute(); - } - - /** - * Resolve attribute value's Java class - */ - public static Class getAttributeClass(CategoryAttribute attribute) { - PropertyType propertyType = attribute.getDataType(); - switch (propertyType) { - case STRING: - return String.class; - case INTEGER: - return Integer.class; - case DOUBLE: - return Double.class; - case BOOLEAN: - return Boolean.class; - case DATE: - return Date.class; - case ENUMERATION: - return String.class; - case ENTITY: - return attribute.getJavaClassForEntity(); - } - return String.class; - } - - /** - * For collection dynamic attributes the method returns a list of formatted collection items joined with the comma, - * for non-collection dynamic attribute a formatted value is returned - */ - public static String getDynamicAttributeValueAsString(MetaProperty metaProperty, Object value) { - CategoryAttribute categoryAttribute = getCategoryAttribute(metaProperty); - MetadataTools metadataTools = AppBeans.get(MetadataTools.class); - if (categoryAttribute.getIsCollection()) { - if (value instanceof Collection) { - List valuesList = ((Collection) value).stream() - .map(item -> metadataTools.format(item, metaProperty)) - .collect(Collectors.toList()); - return Joiner.on(", ").join(valuesList); - } - } - return metadataTools.format(value, metaProperty); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +import com.google.common.base.Joiner; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MetadataTools; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public final class DynamicAttributesUtils { + private DynamicAttributesUtils() { + } + + /** + * Get special meta property path object for dynamic attribute + */ + public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, CategoryAttribute attribute) { + MetaProperty metaProperty = new DynamicAttributesMetaProperty(metaClass, attribute); + return new MetaPropertyPath(metaClass, metaProperty); + } + + /** + * Get special meta property path object for dynamic attribute by code + */ + @Nullable + public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, String attributeCode) { + attributeCode = decodeAttributeCode(attributeCode); + CategoryAttribute attribute = AppBeans.get(DynamicAttributes.NAME, DynamicAttributes.class) + .getAttributeForMetaClass(metaClass, attributeCode); + + if (attribute != null) { + return getMetaPropertyPath(metaClass, attribute); + } else { + return null; + } + } + + /** + * Get special meta property path object for dynamic attribute id + */ + @Nullable + public static MetaPropertyPath getMetaPropertyPath(MetaClass metaClass, UUID attributeId) { + Collection attributes = AppBeans.get(DynamicAttributes.NAME, DynamicAttributes.class) + .getAttributesForMetaClass(metaClass); + CategoryAttribute attribute = null; + for (CategoryAttribute theAttribute : attributes) { + if (theAttribute.getId().equals(attributeId)) { + attribute = theAttribute; + break; + } + } + + if (attribute != null) { + return getMetaPropertyPath(metaClass, attribute); + } else { + return null; + } + } + + /** + * Remove dynamic attribute marker (+) from attribute code (if exists) + */ + public static String decodeAttributeCode(String attributeCode) { + return attributeCode.startsWith("+") ? attributeCode.substring(1) : attributeCode; + } + + /** + * Add dynamic attribute marker (+) to attribute code (if does not exist) + */ + public static String encodeAttributeCode(String attributeCode) { + return attributeCode.startsWith("+") ? attributeCode : "+" + attributeCode; + } + + /** + * Check if the name has dynamic attribute marker + */ + public static boolean isDynamicAttribute(String name) { + return name.startsWith("+"); + } + + /** + * Check if the meta property is dynamic attribute property + */ + public static boolean isDynamicAttribute(MetaProperty metaProperty) { + return metaProperty instanceof DynamicAttributesMetaProperty; + } + + public static CategoryAttribute getCategoryAttribute(MetaProperty metaProperty) { + return ((DynamicAttributesMetaProperty) metaProperty).getAttribute(); + } + + /** + * Resolve attribute value's Java class + */ + public static Class getAttributeClass(CategoryAttribute attribute) { + PropertyType propertyType = attribute.getDataType(); + switch (propertyType) { + case STRING: + return String.class; + case INTEGER: + return Integer.class; + case DOUBLE: + return Double.class; + case BOOLEAN: + return Boolean.class; + case DATE: + return Date.class; + case ENUMERATION: + return String.class; + case ENTITY: + return attribute.getJavaClassForEntity(); + } + return String.class; + } + + /** + * For collection dynamic attributes the method returns a list of formatted collection items joined with the comma, + * for non-collection dynamic attribute a formatted value is returned + */ + public static String getDynamicAttributeValueAsString(MetaProperty metaProperty, Object value) { + CategoryAttribute categoryAttribute = getCategoryAttribute(metaProperty); + MetadataTools metadataTools = AppBeans.get(MetadataTools.class); + if (categoryAttribute.getIsCollection()) { + if (value instanceof Collection) { + List valuesList = ((Collection) value).stream() + .map(item -> metadataTools.format(item, metaProperty)) + .collect(Collectors.toList()); + return Joiner.on(", ").join(valuesList); + } + } + return metadataTools.format(value, metaProperty); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/PropertyType.java b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/PropertyType.java index 005c803d4e..d61b636d84 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/PropertyType.java +++ b/modules/global/src/com/haulmont/cuba/core/app/dynamicattributes/PropertyType.java @@ -1,22 +1,22 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.dynamicattributes; - -public enum PropertyType { - STRING, INTEGER, DOUBLE, DATE, BOOLEAN, ENTITY, ENUMERATION -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.dynamicattributes; + +public enum PropertyType { + STRING, INTEGER, DOUBLE, DATE, BOOLEAN, ENTITY, ENUMERATION +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportExportService.java b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportExportService.java index 4d544d67c9..f947d15623 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportExportService.java +++ b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportExportService.java @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import java.util.Collection; - -/** - * Service that is used for exporting a collection of entities and importing them. - */ -public interface EntityImportExportService { - - String NAME = "cuba_EntityImportExportService"; - - /** - *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI - * EntitySerializationAPI} and packs the JSON file into ZIP archive.

Serialization is described in the {@link - * com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) - * EntitySerializationAPI#toJson(Collection)} method documentation

- * - * @param entities a collection of entities to export - * @return a byte array of zipped JSON file - */ - byte[] exportEntitiesToZIP(Collection entities); - - /** - *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI - * EntitySerializationAPI} and packs the JSON file into ZIP archive. Before the serialization entities will be - * reloaded with the view passed as method parameter.

Serialization is described in the {@link - * com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) - * EntitySerializationAPI#toJson(Collection)} method documentation

- * - * @param entities a collection of entities to export - * @param view before serialization to JSON entities will be reloaded with this view - * @return a byte array of zipped JSON file - */ - byte[] exportEntitiesToZIP(Collection entities, View view); - - /** - *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI - * EntitySerializationAPI}.

Serialization is described in the {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) - * EntitySerializationAPI#toJson(Collection)} method documentation

- * - * @param entities a collection of entities to export - * @return a JSON string - */ - String exportEntitiesToJSON(Collection entities); - - /** - *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI - * EntitySerializationAPI}. Before the serialization entities will be reloaded with the view passed as method - * parameter.

Serialization is described in the {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) - * EntitySerializationAPI#toJson(Collection)} method documentation

- * - * @param entities a collection of entities to export - * @param view before serialization to JSON entities will be reloaded with this view - * @return a JSON string - */ - String exportEntitiesToJSON(Collection entities, View view); - - /** - * Deserializes the JSON and persists deserialized entities according to the rules, described by the {@code - * entityImportView} parameter. If the entity is not present in the database, it will be saved. Otherwise the fields - * of the existing entity that are in the {@code entityImportView} will be updated. - * - * @param json JSON file containing entities - * @param entityImportView {@code EntityImportView} with the rules that describes how entities should be persisted. - * @return a collection of entities that have been imported - * @see EntityImportView - */ - Collection importEntitiesFromJSON(String json, EntityImportView entityImportView); - - /** - * Reads a zip archive that contains a JSON file, deserializes the JSON and persists deserialized entities according - * to the rules, described by the {@code entityImportView} parameter. If the entity is not present in the database, - * it will be saved. Otherwise the fields of the existing entity that are in the {@code entityImportView} will be - * updated. - * - * @param zipBytes byte array of ZIP archive with JSON file - * @param entityImportView {@code EntityImportView} with the rules that describes how entities should be persisted. - * @return a collection of entities that have been imported - * @see EntityImportView - */ - Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView entityImportView); - - /** - * See {@link #importEntities(Collection, EntityImportView, boolean)}. The current method doesn't perform bean - * validation - */ - Collection importEntities(Collection entities, EntityImportView entityImportView); - - /** - * Persists entities according to the rules, described by the {@code entityImportView} parameter. If the entity is - * not present in the database, it will be saved. Otherwise the fields of the existing entity that are in the {@code - * entityImportView} will be updated. - *

- * If the view contains a property for composition attribute then all composition collection members that are absent - * in the passed entity will be removed. - * - * @param importView {@code EntityImportView} with the rules that describes how entities should be persisted. - * @param validate whether the passed entities should be validated by the {@link com.haulmont.cuba.core.global.BeanValidation} - * mechanism before entities are persisted - * @return a collection of entities that have been imported - */ - Collection importEntities(Collection entities, EntityImportView importView, boolean validate); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import java.util.Collection; + +/** + * Service that is used for exporting a collection of entities and importing them. + */ +public interface EntityImportExportService { + + String NAME = "cuba_EntityImportExportService"; + + /** + *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI + * EntitySerializationAPI} and packs the JSON file into ZIP archive.

Serialization is described in the {@link + * com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) + * EntitySerializationAPI#toJson(Collection)} method documentation

+ * + * @param entities a collection of entities to export + * @return a byte array of zipped JSON file + */ + byte[] exportEntitiesToZIP(Collection entities); + + /** + *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI + * EntitySerializationAPI} and packs the JSON file into ZIP archive. Before the serialization entities will be + * reloaded with the view passed as method parameter.

Serialization is described in the {@link + * com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) + * EntitySerializationAPI#toJson(Collection)} method documentation

+ * + * @param entities a collection of entities to export + * @param view before serialization to JSON entities will be reloaded with this view + * @return a byte array of zipped JSON file + */ + byte[] exportEntitiesToZIP(Collection entities, View view); + + /** + *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI + * EntitySerializationAPI}.

Serialization is described in the {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) + * EntitySerializationAPI#toJson(Collection)} method documentation

+ * + * @param entities a collection of entities to export + * @return a JSON string + */ + String exportEntitiesToJSON(Collection entities); + + /** + *

Serializes a collection of entities to JSON using {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI + * EntitySerializationAPI}. Before the serialization entities will be reloaded with the view passed as method + * parameter.

Serialization is described in the {@link com.haulmont.cuba.core.app.serialization.EntitySerializationAPI#toJson(Collection) + * EntitySerializationAPI#toJson(Collection)} method documentation

+ * + * @param entities a collection of entities to export + * @param view before serialization to JSON entities will be reloaded with this view + * @return a JSON string + */ + String exportEntitiesToJSON(Collection entities, View view); + + /** + * Deserializes the JSON and persists deserialized entities according to the rules, described by the {@code + * entityImportView} parameter. If the entity is not present in the database, it will be saved. Otherwise the fields + * of the existing entity that are in the {@code entityImportView} will be updated. + * + * @param json JSON file containing entities + * @param entityImportView {@code EntityImportView} with the rules that describes how entities should be persisted. + * @return a collection of entities that have been imported + * @see EntityImportView + */ + Collection importEntitiesFromJSON(String json, EntityImportView entityImportView); + + /** + * Reads a zip archive that contains a JSON file, deserializes the JSON and persists deserialized entities according + * to the rules, described by the {@code entityImportView} parameter. If the entity is not present in the database, + * it will be saved. Otherwise the fields of the existing entity that are in the {@code entityImportView} will be + * updated. + * + * @param zipBytes byte array of ZIP archive with JSON file + * @param entityImportView {@code EntityImportView} with the rules that describes how entities should be persisted. + * @return a collection of entities that have been imported + * @see EntityImportView + */ + Collection importEntitiesFromZIP(byte[] zipBytes, EntityImportView entityImportView); + + /** + * See {@link #importEntities(Collection, EntityImportView, boolean)}. The current method doesn't perform bean + * validation + */ + Collection importEntities(Collection entities, EntityImportView entityImportView); + + /** + * Persists entities according to the rules, described by the {@code entityImportView} parameter. If the entity is + * not present in the database, it will be saved. Otherwise the fields of the existing entity that are in the {@code + * entityImportView} will be updated. + *

+ * If the view contains a property for composition attribute then all composition collection members that are absent + * in the passed entity will be removed. + * + * @param importView {@code EntityImportView} with the rules that describes how entities should be persisted. + * @param validate whether the passed entities should be validated by the {@link com.haulmont.cuba.core.global.BeanValidation} + * mechanism before entities are persisted + * @return a collection of entities that have been imported + */ + Collection importEntities(Collection entities, EntityImportView importView, boolean validate); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportView.java b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportView.java index d6a53fe549..dfdf0d386b 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportView.java +++ b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportView.java @@ -1,181 +1,181 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.MetadataTools; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * Class describing how entity fields should be saved during the import performed by {@link EntityImportExportService - * EntityImportExportService}

Only fields that are added as properties to the {@code EntityImportView} will be - * saved.

For local entity property the rule is simple: if property name is added to the view, then the property - * will be saved. Use {@link #addLocalProperty(String)} method for adding local property to the view.

For - * many-to-one references there are two possible options:

  • Create or update the referenced entity. Use - * the {@link #addManyToOneProperty(String, EntityImportView)} method. The referenced entity will be saved according to - * the {@code EntityImportView} passed as parameter
  • Try to find the reference in the database and put it to the - * property value. {@link #addManyToOneProperty(String, ReferenceImportBehaviour)} must be used for this. {@link - * ReferenceImportBehaviour} parameter specifies the behaviour in case when referenced entity is missed in the database: - * missing entity can be ignored or import may fail with an error.
- *

- * For one-to-one references behavior is the same as for the many-to-one references. Just use the corresponding - * methods for adding properties to the view: {@link #addOneToOneProperty(String, EntityImportView)} or {@link - * #addOneToOneProperty(String, ReferenceImportBehaviour)}. - *

- * For one-to-many references you must specify the {@link EntityImportView} which defines how entities from the - * collection must be saved. The second parameter is the {@link CollectionImportPolicy} which specifies what to do with - * collection items that weren't passed to the import: they can be removed or remained. - *

- * For many-to-many references the following things must be defined:

  • Whether the passed collection - * members must be created/updated or just searched in the database
  • Whether the collection items not passed to - * the import must be removed or remain. Keep in mind that for many-to-many properties missing collection members will be - * removed from the collection only, not from the database
- *

- * You can invoke methods for adding view properties in fluent interface style. There are also useful methods like - * {@link #addLocalProperties()}, {@link #addSystemProperties()} or {@link #addProperties(String...)} - *

- * Example of creating the EntityImportView object: - *

- * EntityImportView importView = new EntityImportView(Group.class)
- *           .addLocalProperties()
- *           .addOneToManyProperty("constraints",
- *                  new EntityImportView(Constraint.class).addLocalProperties(),
- *                  CollectionImportPolicy.KEEP_ABSENT_ITEMS)
- *           .addManyToOneProperty("parent", ReferenceImportBehaviour.ERROR_ON_MISSING);
- * 
- */ -public class EntityImportView implements Serializable { - - private Map properties = new HashMap<>(); - - private Class entityClass; - - public EntityImportView(Class entityClass) { - this.entityClass = entityClass; - } - - public EntityImportView addLocalProperty(String name) { - EntityImportViewProperty property = new EntityImportViewProperty(name); - properties.put(name, property); - return this; - } - - public EntityImportView addManyToOneProperty(String name, EntityImportView view) { - EntityImportViewProperty property = new EntityImportViewProperty(name, view); - properties.put(name, property); - return this; - } - - public EntityImportView addManyToOneProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { - EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour); - properties.put(name, property); - return this; - } - - public EntityImportView addOneToOneProperty(String name, EntityImportView view) { - EntityImportViewProperty property = new EntityImportViewProperty(name, view); - properties.put(name, property); - return this; - } - - public EntityImportView addOneToOneProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { - EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour); - properties.put(name, property); - return this; - } - - public EntityImportView addOneToManyProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { - EntityImportViewProperty property = new EntityImportViewProperty(name, view, collectionImportPolicy); - properties.put(name, property); - return this; - } - - public EntityImportView addManyToManyProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { - EntityImportViewProperty property = new EntityImportViewProperty(name, view, collectionImportPolicy); - properties.put(name, property); - return this; - } - - public EntityImportView addManyToManyProperty(String name, ReferenceImportBehaviour referenceImportBehaviour, CollectionImportPolicy collectionImportPolicy) { - EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour, collectionImportPolicy); - properties.put(name, property); - return this; - } - - public EntityImportView addEmbeddedProperty(String name, EntityImportView view) { - EntityImportViewProperty property = new EntityImportViewProperty(name, view); - properties.put(name, property); - return this; - } - - public EntityImportView addProperty(EntityImportViewProperty property) { - properties.put(property.getName(), property); - return this; - } - - public EntityImportViewProperty getProperty(String name) { - return properties.get(name); - } - - public Collection getProperties() { - return properties.values(); - } - - public Class getEntityClass() { - return entityClass; - } - - public EntityImportView addLocalProperties() { - Metadata metadata = AppBeans.get(Metadata.class); - MetaClass metaClass = metadata.getClassNN(entityClass); - MetadataTools metadataTools = metadata.getTools(); - metaClass.getProperties().stream() - .filter(property -> !property.getRange().isClass() && !metadataTools.isSystem(property)) - .forEach(metaProperty -> addLocalProperty(metaProperty.getName())); - return this; - } - - public EntityImportView addSystemProperties() { - Metadata metadata = AppBeans.get(Metadata.class); - MetaClass metaClass = metadata.getClassNN(entityClass); - MetadataTools metadataTools = metadata.getTools(); - metaClass.getProperties().stream() - .filter(metadataTools::isSystem) - .forEach(metaProperty -> addLocalProperty(metaProperty.getName())); - return this; - } - - public EntityImportView addProperties(String... names) { - for (String name : names) { - addLocalProperty(name); - } - return this; - } - - public EntityImportView removeProperty(String name) { - properties.remove(name); - return this; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.MetadataTools; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Class describing how entity fields should be saved during the import performed by {@link EntityImportExportService + * EntityImportExportService}

Only fields that are added as properties to the {@code EntityImportView} will be + * saved.

For local entity property the rule is simple: if property name is added to the view, then the property + * will be saved. Use {@link #addLocalProperty(String)} method for adding local property to the view.

For + * many-to-one references there are two possible options:

  • Create or update the referenced entity. Use + * the {@link #addManyToOneProperty(String, EntityImportView)} method. The referenced entity will be saved according to + * the {@code EntityImportView} passed as parameter
  • Try to find the reference in the database and put it to the + * property value. {@link #addManyToOneProperty(String, ReferenceImportBehaviour)} must be used for this. {@link + * ReferenceImportBehaviour} parameter specifies the behaviour in case when referenced entity is missed in the database: + * missing entity can be ignored or import may fail with an error.
+ *

+ * For one-to-one references behavior is the same as for the many-to-one references. Just use the corresponding + * methods for adding properties to the view: {@link #addOneToOneProperty(String, EntityImportView)} or {@link + * #addOneToOneProperty(String, ReferenceImportBehaviour)}. + *

+ * For one-to-many references you must specify the {@link EntityImportView} which defines how entities from the + * collection must be saved. The second parameter is the {@link CollectionImportPolicy} which specifies what to do with + * collection items that weren't passed to the import: they can be removed or remained. + *

+ * For many-to-many references the following things must be defined:

  • Whether the passed collection + * members must be created/updated or just searched in the database
  • Whether the collection items not passed to + * the import must be removed or remain. Keep in mind that for many-to-many properties missing collection members will be + * removed from the collection only, not from the database
+ *

+ * You can invoke methods for adding view properties in fluent interface style. There are also useful methods like + * {@link #addLocalProperties()}, {@link #addSystemProperties()} or {@link #addProperties(String...)} + *

+ * Example of creating the EntityImportView object: + *

+ * EntityImportView importView = new EntityImportView(Group.class)
+ *           .addLocalProperties()
+ *           .addOneToManyProperty("constraints",
+ *                  new EntityImportView(Constraint.class).addLocalProperties(),
+ *                  CollectionImportPolicy.KEEP_ABSENT_ITEMS)
+ *           .addManyToOneProperty("parent", ReferenceImportBehaviour.ERROR_ON_MISSING);
+ * 
+ */ +public class EntityImportView implements Serializable { + + private Map properties = new HashMap<>(); + + private Class entityClass; + + public EntityImportView(Class entityClass) { + this.entityClass = entityClass; + } + + public EntityImportView addLocalProperty(String name) { + EntityImportViewProperty property = new EntityImportViewProperty(name); + properties.put(name, property); + return this; + } + + public EntityImportView addManyToOneProperty(String name, EntityImportView view) { + EntityImportViewProperty property = new EntityImportViewProperty(name, view); + properties.put(name, property); + return this; + } + + public EntityImportView addManyToOneProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { + EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour); + properties.put(name, property); + return this; + } + + public EntityImportView addOneToOneProperty(String name, EntityImportView view) { + EntityImportViewProperty property = new EntityImportViewProperty(name, view); + properties.put(name, property); + return this; + } + + public EntityImportView addOneToOneProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { + EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour); + properties.put(name, property); + return this; + } + + public EntityImportView addOneToManyProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { + EntityImportViewProperty property = new EntityImportViewProperty(name, view, collectionImportPolicy); + properties.put(name, property); + return this; + } + + public EntityImportView addManyToManyProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { + EntityImportViewProperty property = new EntityImportViewProperty(name, view, collectionImportPolicy); + properties.put(name, property); + return this; + } + + public EntityImportView addManyToManyProperty(String name, ReferenceImportBehaviour referenceImportBehaviour, CollectionImportPolicy collectionImportPolicy) { + EntityImportViewProperty property = new EntityImportViewProperty(name, referenceImportBehaviour, collectionImportPolicy); + properties.put(name, property); + return this; + } + + public EntityImportView addEmbeddedProperty(String name, EntityImportView view) { + EntityImportViewProperty property = new EntityImportViewProperty(name, view); + properties.put(name, property); + return this; + } + + public EntityImportView addProperty(EntityImportViewProperty property) { + properties.put(property.getName(), property); + return this; + } + + public EntityImportViewProperty getProperty(String name) { + return properties.get(name); + } + + public Collection getProperties() { + return properties.values(); + } + + public Class getEntityClass() { + return entityClass; + } + + public EntityImportView addLocalProperties() { + Metadata metadata = AppBeans.get(Metadata.class); + MetaClass metaClass = metadata.getClassNN(entityClass); + MetadataTools metadataTools = metadata.getTools(); + metaClass.getProperties().stream() + .filter(property -> !property.getRange().isClass() && !metadataTools.isSystem(property)) + .forEach(metaProperty -> addLocalProperty(metaProperty.getName())); + return this; + } + + public EntityImportView addSystemProperties() { + Metadata metadata = AppBeans.get(Metadata.class); + MetaClass metaClass = metadata.getClassNN(entityClass); + MetadataTools metadataTools = metadata.getTools(); + metaClass.getProperties().stream() + .filter(metadataTools::isSystem) + .forEach(metaProperty -> addLocalProperty(metaProperty.getName())); + return this; + } + + public EntityImportView addProperties(String... names) { + for (String name : names) { + addLocalProperty(name); + } + return this; + } + + public EntityImportView removeProperty(String name) { + properties.remove(name); + return this; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportViewProperty.java b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportViewProperty.java index a73c3bd2e6..8a4998c4e1 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportViewProperty.java +++ b/modules/global/src/com/haulmont/cuba/core/app/importexport/EntityImportViewProperty.java @@ -1,89 +1,89 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -import java.io.Serializable; - -public class EntityImportViewProperty implements Serializable { - - protected String name; - - protected EntityImportView view; - - protected ReferenceImportBehaviour referenceImportBehaviour; - - protected CollectionImportPolicy collectionImportPolicy; - - public EntityImportViewProperty(String name) { - this.name = name; - } - - public EntityImportViewProperty(String name, EntityImportView view) { - this.name = name; - this.view = view; - } - - public EntityImportViewProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { - this.name = name; - this.view = view; - this.collectionImportPolicy = collectionImportPolicy; - } - - public EntityImportViewProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { - this.name = name; - this.referenceImportBehaviour = referenceImportBehaviour; - } - - public EntityImportViewProperty(String name, ReferenceImportBehaviour referenceImportBehaviour, CollectionImportPolicy collectionImportPolicy) { - this.name = name; - this.referenceImportBehaviour = referenceImportBehaviour; - this.collectionImportPolicy = collectionImportPolicy; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public EntityImportView getView() { - return view; - } - - public void setView(EntityImportView view) { - this.view = view; - } - - public ReferenceImportBehaviour getReferenceImportBehaviour() { - return referenceImportBehaviour; - } - - public void setReferenceImportBehaviour(ReferenceImportBehaviour referenceImportBehaviour) { - this.referenceImportBehaviour = referenceImportBehaviour; - } - - public CollectionImportPolicy getCollectionImportPolicy() { - return collectionImportPolicy; - } - - public void setCollectionImportPolicy(CollectionImportPolicy collectionImportPolicy) { - this.collectionImportPolicy = collectionImportPolicy; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +import java.io.Serializable; + +public class EntityImportViewProperty implements Serializable { + + protected String name; + + protected EntityImportView view; + + protected ReferenceImportBehaviour referenceImportBehaviour; + + protected CollectionImportPolicy collectionImportPolicy; + + public EntityImportViewProperty(String name) { + this.name = name; + } + + public EntityImportViewProperty(String name, EntityImportView view) { + this.name = name; + this.view = view; + } + + public EntityImportViewProperty(String name, EntityImportView view, CollectionImportPolicy collectionImportPolicy) { + this.name = name; + this.view = view; + this.collectionImportPolicy = collectionImportPolicy; + } + + public EntityImportViewProperty(String name, ReferenceImportBehaviour referenceImportBehaviour) { + this.name = name; + this.referenceImportBehaviour = referenceImportBehaviour; + } + + public EntityImportViewProperty(String name, ReferenceImportBehaviour referenceImportBehaviour, CollectionImportPolicy collectionImportPolicy) { + this.name = name; + this.referenceImportBehaviour = referenceImportBehaviour; + this.collectionImportPolicy = collectionImportPolicy; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public EntityImportView getView() { + return view; + } + + public void setView(EntityImportView view) { + this.view = view; + } + + public ReferenceImportBehaviour getReferenceImportBehaviour() { + return referenceImportBehaviour; + } + + public void setReferenceImportBehaviour(ReferenceImportBehaviour referenceImportBehaviour) { + this.referenceImportBehaviour = referenceImportBehaviour; + } + + public CollectionImportPolicy getCollectionImportPolicy() { + return collectionImportPolicy; + } + + public void setCollectionImportPolicy(CollectionImportPolicy collectionImportPolicy) { + this.collectionImportPolicy = collectionImportPolicy; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/importexport/ReferenceImportBehaviour.java b/modules/global/src/com/haulmont/cuba/core/app/importexport/ReferenceImportBehaviour.java index 1efc1f3514..ad407053f6 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/importexport/ReferenceImportBehaviour.java +++ b/modules/global/src/com/haulmont/cuba/core/app/importexport/ReferenceImportBehaviour.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.importexport; - -/** - * Enum describes a behavior for references during entities import: missing reference can be ignored - * or an exception can be thrown. - * - */ -public enum ReferenceImportBehaviour { - IGNORE_MISSING, - ERROR_ON_MISSING -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.importexport; + +/** + * Enum describes a behavior for references during entities import: missing reference can be ignored + * or an exception can be thrown. + * + */ +public enum ReferenceImportBehaviour { + IGNORE_MISSING, + ERROR_ON_MISSING +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodInfo.java b/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodInfo.java index e892a28564..bba7607125 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodInfo.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.scheduled; - -import com.google.common.base.Preconditions; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -public class MethodInfo implements Serializable { - - private String name; - private List parameters = new ArrayList<>(); - - public MethodInfo(String name, List parameters) { - this.name = name; - this.parameters = parameters; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getParameters() { - return parameters; - } - - public void setParameters(List parameters) { - Preconditions.checkNotNull(parameters, "Parameters can not be null"); - this.parameters = parameters; - } - - public MethodParameterInfo getParameter(String paramName) { - for (MethodParameterInfo parameter : parameters) { - if (paramName.equals(parameter.getName())) - return parameter; - } - return null; - } - - public String getMethodSignature() { - StringBuilder sb = new StringBuilder(); - sb.append(name).append("("); - - int count = 0; - for (MethodParameterInfo param : parameters) { - sb.append(param.getType().getSimpleName()) - .append(" ") - .append(param.getName()); - - if (++count != parameters.size()) - sb.append(", "); - } - sb.append(")"); - return sb.toString(); - } - - @Override - public String toString() { - return getMethodSignature(); - } - - public boolean definitionEquals(MethodInfo methodInfo) { - if (!this.name.equals(methodInfo.getName())) - return false; - if (this.getParameters().size() != methodInfo.getParameters().size()) - return false; - - for (int i = 0; i < this.parameters.size(); i++) { - MethodParameterInfo param1 = this.parameters.get(i); - MethodParameterInfo param2 = methodInfo.getParameters().get(i); - if (!param1.getTypeName().equals(param2.getTypeName())) - return false; - } - - return true; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.scheduled; + +import com.google.common.base.Preconditions; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class MethodInfo implements Serializable { + + private String name; + private List parameters = new ArrayList<>(); + + public MethodInfo(String name, List parameters) { + this.name = name; + this.parameters = parameters; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + Preconditions.checkNotNull(parameters, "Parameters can not be null"); + this.parameters = parameters; + } + + public MethodParameterInfo getParameter(String paramName) { + for (MethodParameterInfo parameter : parameters) { + if (paramName.equals(parameter.getName())) + return parameter; + } + return null; + } + + public String getMethodSignature() { + StringBuilder sb = new StringBuilder(); + sb.append(name).append("("); + + int count = 0; + for (MethodParameterInfo param : parameters) { + sb.append(param.getType().getSimpleName()) + .append(" ") + .append(param.getName()); + + if (++count != parameters.size()) + sb.append(", "); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public String toString() { + return getMethodSignature(); + } + + public boolean definitionEquals(MethodInfo methodInfo) { + if (!this.name.equals(methodInfo.getName())) + return false; + if (this.getParameters().size() != methodInfo.getParameters().size()) + return false; + + for (int i = 0; i < this.parameters.size(); i++) { + MethodParameterInfo param1 = this.parameters.get(i); + MethodParameterInfo param2 = methodInfo.getParameters().get(i); + if (!param1.getTypeName().equals(param2.getTypeName())) + return false; + } + + return true; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodParameterInfo.java b/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodParameterInfo.java index f9f6d05d5b..20b3ae886e 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodParameterInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/app/scheduled/MethodParameterInfo.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.scheduled; - -import com.haulmont.bali.util.ReflectionHelper; - -import java.io.Serializable; - -public class MethodParameterInfo implements Serializable { - - private Class type; - private String name; - private String typeName; - private Object value; - - public MethodParameterInfo(String typeName, String name, Object value) { - this.typeName = typeName; - this.name = name; - this.value = value; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Class getType() { - return type == null ? ReflectionHelper.getClass(typeName) : type; - } - - public void setType(Class type) { - this.type = type; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(String typeName) { - this.typeName = typeName; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.scheduled; + +import com.haulmont.bali.util.ReflectionHelper; + +import java.io.Serializable; + +public class MethodParameterInfo implements Serializable { + + private Class type; + private String name; + private String typeName; + private Object value; + + public MethodParameterInfo(String typeName, String name, Object value) { + this.typeName = typeName; + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Class getType() { + return type == null ? ReflectionHelper.getClass(typeName) : type; + } + + public void setType(Class type) { + this.type = type; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationAPI.java b/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationAPI.java index 57ccac98ea..63302630c9 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationAPI.java +++ b/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationAPI.java @@ -1,138 +1,138 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.serialization; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.View; - -import javax.annotation.Nullable; -import java.util.Collection; - -/** - * Class that is used for serialization and deserialization of entities to JSON. - */ -public interface EntitySerializationAPI { - - String NAME = "cuba_EntitySerialization"; - - /** - * Serializes a single entity to the JSON object graph. - *

- * If the {@code view} parameter is null then all loaded entity properties will be presented in JSON, otherwise only - * loaded properties that are in the view will be in the JSON object. - *

- * The {@code options} parameter specify some additional options for the serialization process. For example, - * repeated entities may be replaced with the object with the only "id" property, making the result JSON more - * compact. See {@link EntitySerializationOption} for details. - *

- * Additionally, an "_entityName" property is added to the JSON objects that represent an entity. - * - * @param entity an entity to be serialized - * @param view a view that defines which entity properties should be added to the result JSON object - * @param options options specifying how an entity should be serialized - * @return a string that represents a JSON object - */ - String toJson(Entity entity, - @Nullable View view, - EntitySerializationOption... options); - - /** - * Serializes a collection of entities to the JSON array. Method works like the {@link #toJson(Entity, View, - * EntitySerializationOption...)}, but return a JSON array as a result. - * - * @param entities a list of entities to be serialized - * @param view a view that defines which entity properties should be added to the result JSON object - * @param options options specifying how an entity should be serialized - * @return a string that represents a JSON array of objects. - */ - String toJson(Collection entities, - @Nullable View view, - EntitySerializationOption... options); - - /** - * An overloaded version of the {@link #toJson(Entity, View, EntitySerializationOption...)} method with a null - * {@code view} parameter and with no serialization options. - * - * @param entity an entity to be serialized - * @return a string that represents a JSON object - */ - String toJson(Entity entity); - - /** - * An overloaded version of the {@link #toJson(Collection, View, EntitySerializationOption...)} method with a null - * {@code view} parameter and with no serialization options. - * - * @param entities a collection of entities to be serialized - * @return a string that represent a JSON array which contains entity objects - */ - String toJson(Collection entities); - - /** - * Serializes any custom POJO or collection of POJOs or JSON. If some field in POJO is an entity then this field - * will be serialized according to entity serialization rules. Date fields are serialized according to the format of - * the {@link com.haulmont.chile.core.datatypes.impl.DateTimeDatatype}. - * - * @param object any POJO or collection of POJOs - * @param options options specifying how a JSON object graph for fields with type 'Entity' will be serialized - * @return a string that represents a JSON object or JSON array - */ - String objectToJson(Object object, EntitySerializationOption... options); - - /** - * Deserializes a JSON object to the entity. - *

- * The {@code metaClass} parameter defines a result entity metaClass. It is optional. It must be defined if the JSON - * object doesn't contain an "_entityName" property. - *

- * An entity may be serialized to the JSON in slightly different formats. The format is defined by the {@code - * options} parameter. See {@link EntitySerializationOption} for details. - * - * @param json a string that represents a JSON object - * @param metaClass a metaClass of the entity that will be created - * @param options options specifying how a JSON object graph was serialized - * @return an entity - */ - T entityFromJson(String json, - @Nullable MetaClass metaClass, - EntitySerializationOption... options); - - /** - * Deserializes a JSON array of objects to entities collection - * - * @param json a string that represents a JSON array of objects - * @param metaClass a metaClass of the entities that will be created - * @param options options specifying how a JSON object graph was serialized - * @return an entities collection - */ - Collection entitiesCollectionFromJson(String json, - @Nullable MetaClass metaClass, - EntitySerializationOption... options); - - /** - * Deserializes an object of any class from JSON. Date fields are deserialized according to the {@link - * com.haulmont.chile.core.datatypes.impl.DateTimeDatatype} format, entities object and fields of Entity type are - * deserialized like in the {@link #entityFromJson(String, MetaClass, EntitySerializationOption...)} method - * - * @param json a string that represents an object - * @param clazz java class of the object - * @param options options specifying how a JSON object graph was serialized - * @return deserialized object - */ - T objectFromJson(String json, Class clazz, EntitySerializationOption... options); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.serialization; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.View; + +import javax.annotation.Nullable; +import java.util.Collection; + +/** + * Class that is used for serialization and deserialization of entities to JSON. + */ +public interface EntitySerializationAPI { + + String NAME = "cuba_EntitySerialization"; + + /** + * Serializes a single entity to the JSON object graph. + *

+ * If the {@code view} parameter is null then all loaded entity properties will be presented in JSON, otherwise only + * loaded properties that are in the view will be in the JSON object. + *

+ * The {@code options} parameter specify some additional options for the serialization process. For example, + * repeated entities may be replaced with the object with the only "id" property, making the result JSON more + * compact. See {@link EntitySerializationOption} for details. + *

+ * Additionally, an "_entityName" property is added to the JSON objects that represent an entity. + * + * @param entity an entity to be serialized + * @param view a view that defines which entity properties should be added to the result JSON object + * @param options options specifying how an entity should be serialized + * @return a string that represents a JSON object + */ + String toJson(Entity entity, + @Nullable View view, + EntitySerializationOption... options); + + /** + * Serializes a collection of entities to the JSON array. Method works like the {@link #toJson(Entity, View, + * EntitySerializationOption...)}, but return a JSON array as a result. + * + * @param entities a list of entities to be serialized + * @param view a view that defines which entity properties should be added to the result JSON object + * @param options options specifying how an entity should be serialized + * @return a string that represents a JSON array of objects. + */ + String toJson(Collection entities, + @Nullable View view, + EntitySerializationOption... options); + + /** + * An overloaded version of the {@link #toJson(Entity, View, EntitySerializationOption...)} method with a null + * {@code view} parameter and with no serialization options. + * + * @param entity an entity to be serialized + * @return a string that represents a JSON object + */ + String toJson(Entity entity); + + /** + * An overloaded version of the {@link #toJson(Collection, View, EntitySerializationOption...)} method with a null + * {@code view} parameter and with no serialization options. + * + * @param entities a collection of entities to be serialized + * @return a string that represent a JSON array which contains entity objects + */ + String toJson(Collection entities); + + /** + * Serializes any custom POJO or collection of POJOs or JSON. If some field in POJO is an entity then this field + * will be serialized according to entity serialization rules. Date fields are serialized according to the format of + * the {@link com.haulmont.chile.core.datatypes.impl.DateTimeDatatype}. + * + * @param object any POJO or collection of POJOs + * @param options options specifying how a JSON object graph for fields with type 'Entity' will be serialized + * @return a string that represents a JSON object or JSON array + */ + String objectToJson(Object object, EntitySerializationOption... options); + + /** + * Deserializes a JSON object to the entity. + *

+ * The {@code metaClass} parameter defines a result entity metaClass. It is optional. It must be defined if the JSON + * object doesn't contain an "_entityName" property. + *

+ * An entity may be serialized to the JSON in slightly different formats. The format is defined by the {@code + * options} parameter. See {@link EntitySerializationOption} for details. + * + * @param json a string that represents a JSON object + * @param metaClass a metaClass of the entity that will be created + * @param options options specifying how a JSON object graph was serialized + * @return an entity + */ + T entityFromJson(String json, + @Nullable MetaClass metaClass, + EntitySerializationOption... options); + + /** + * Deserializes a JSON array of objects to entities collection + * + * @param json a string that represents a JSON array of objects + * @param metaClass a metaClass of the entities that will be created + * @param options options specifying how a JSON object graph was serialized + * @return an entities collection + */ + Collection entitiesCollectionFromJson(String json, + @Nullable MetaClass metaClass, + EntitySerializationOption... options); + + /** + * Deserializes an object of any class from JSON. Date fields are deserialized according to the {@link + * com.haulmont.chile.core.datatypes.impl.DateTimeDatatype} format, entities object and fields of Entity type are + * deserialized like in the {@link #entityFromJson(String, MetaClass, EntitySerializationOption...)} method + * + * @param json a string that represents an object + * @param clazz java class of the object + * @param options options specifying how a JSON object graph was serialized + * @return deserialized object + */ + T objectFromJson(String json, Class clazz, EntitySerializationOption... options); +} diff --git a/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationException.java b/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationException.java index 1fc95c1ecf..a348e0f3a6 100644 --- a/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationException.java +++ b/modules/global/src/com/haulmont/cuba/core/app/serialization/EntitySerializationException.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.app.serialization; - -public class EntitySerializationException extends RuntimeException { - - public EntitySerializationException() { - } - - public EntitySerializationException(String message) { - super(message); - } - - public EntitySerializationException(String message, Throwable cause) { - super(message, cause); - } - - public EntitySerializationException(Throwable cause) { - super(cause); - } - - public EntitySerializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.app.serialization; + +public class EntitySerializationException extends RuntimeException { + + public EntitySerializationException() { + } + + public EntitySerializationException(String message) { + super(message); + } + + public EntitySerializationException(String message, Throwable cause) { + super(message, cause); + } + + public EntitySerializationException(Throwable cause) { + super(cause); + } + + public EntitySerializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/ConfigPersister.java b/modules/global/src/com/haulmont/cuba/core/config/ConfigPersister.java index 6d6fec6fbc..64a90cf631 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/ConfigPersister.java +++ b/modules/global/src/com/haulmont/cuba/core/config/ConfigPersister.java @@ -1,23 +1,23 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.config; - -public interface ConfigPersister { - String getProperty(SourceType sourceType, String name); - - void setProperty(SourceType sourceType, String name, String value); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.config; + +public interface ConfigPersister { + String getProperty(SourceType sourceType, String name); + + void setProperty(SourceType sourceType, String name, String value); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/ConfigStorageCommon.java b/modules/global/src/com/haulmont/cuba/core/config/ConfigStorageCommon.java index 3cbfba05bf..069e35eac6 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/ConfigStorageCommon.java +++ b/modules/global/src/com/haulmont/cuba/core/config/ConfigStorageCommon.java @@ -1,156 +1,156 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config; - -import com.google.common.base.Strings; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.auth.AuthenticationService; -import com.haulmont.cuba.security.auth.TrustedClientCredentials; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; - -@Component("cuba_ConfigStorageCommon") -public class ConfigStorageCommon { - - private final Logger log = LoggerFactory.getLogger(ConfigStorageCommon.class); - - @Inject - protected Configuration configuration; - @Inject - protected AuthenticationService authenticationService; - - public String printAppProperties(String prefix) { - List list = new ArrayList<>(); - for (String name : AppContext.getPropertyNames()) { - if (prefix == null || name.startsWith(prefix)) { - list.add(name + "=" + AppContext.getProperty(name)); - } - } - Collections.sort(list); - return new StrBuilder().appendWithSeparators(list, "\n").toString(); - } - - public String getAppProperty(String name) { - if (StringUtils.isBlank(name)) - return "Enter a property name"; - - return name + "=" + AppContext.getProperty(name); - } - - public String setAppProperty(String name, String value) { - if (StringUtils.isBlank(name)) - return "Enter a property name"; - if (StringUtils.isBlank(value)) - return "Enter a property value"; - - AppContext.setProperty(name, value); - return String.format("Property %s set to %s", name, value); - } - - /** - * Method returns a result of config method invocation - * @param classFQN fully qualified configuration interface name - * @param methodName config getter method name - * @param userLogin parameter is used for authentication if there is no security context bound to the current thread - * and configuration method source is DATABASE - * @param userPassword see userLogin parameter description - * @return configuration method invocation result - */ - public String getConfigValue(String classFQN, String methodName, String userLogin, String userPassword) { - Class aClass; - try { - aClass = Class.forName(classFQN); - } catch (ClassNotFoundException e) { - return String.format("Class %s not found.\nPlease ensure that you entered a fully qualified class name and " + - "that you class is in a proper application module (core, web or portal).", classFQN); - } - - if (Config.class.isAssignableFrom(aClass)) { - Config config = configuration.getConfig((Class)aClass); - Method method; - boolean logoutRequired = false; - try { - method = aClass.getMethod(methodName); - - //if there is no security context bound to the current thread and the source of the config method is - //DATABASE, then login attempt with 'userLogin' and 'userPassword' will be made - if (AppContext.getSecurityContext() == null) { - SourceType sourceType; - Source methodSourceAnnotation = method.getAnnotation(Source.class); - if (methodSourceAnnotation != null) { - sourceType = methodSourceAnnotation.type(); - } else { - Source classSourceAnnotation = aClass.getAnnotation(Source.class); - sourceType = classSourceAnnotation.type(); - } - - if (sourceType != null && sourceType == SourceType.DATABASE) { - if (Strings.isNullOrEmpty(userLogin)) { - return "No security context bound to the current thread. Please specify the user name."; - } else { - try { - Map availableLocales = configuration.getConfig(GlobalConfig.class).getAvailableLocales(); - Locale defaultLocale = availableLocales.values().iterator().next(); - - TrustedClientCredentials credentials = new TrustedClientCredentials(userLogin, userPassword, defaultLocale); - - UserSession session = authenticationService.login(credentials).getSession(); - AppContext.setSecurityContext(new SecurityContext(session)); - logoutRequired = true; - } catch (LoginException e) { - log.error(ExceptionUtils.getStackTrace(e)); - return "Login error: " + e.getMessage(); - } - } - } - } - - Object result = method.invoke(config); - return result == null ? null : result.toString(); - } catch (NoSuchMethodException e) { - return String.format("Method %s() not found in class %s", methodName, classFQN); - } catch (InvocationTargetException | IllegalAccessException e) { - return ExceptionUtils.getStackTrace(e); - } finally { - if (logoutRequired) { - try { - authenticationService.logout(); - } finally { - AppContext.setSecurityContext(null); - } - } - } - } else { - return String.format("Class %s is not an implementation of Config interface", classFQN); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config; + +import com.google.common.base.Strings; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.auth.AuthenticationService; +import com.haulmont.cuba.security.auth.TrustedClientCredentials; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + +@Component("cuba_ConfigStorageCommon") +public class ConfigStorageCommon { + + private final Logger log = LoggerFactory.getLogger(ConfigStorageCommon.class); + + @Inject + protected Configuration configuration; + @Inject + protected AuthenticationService authenticationService; + + public String printAppProperties(String prefix) { + List list = new ArrayList<>(); + for (String name : AppContext.getPropertyNames()) { + if (prefix == null || name.startsWith(prefix)) { + list.add(name + "=" + AppContext.getProperty(name)); + } + } + Collections.sort(list); + return new StrBuilder().appendWithSeparators(list, "\n").toString(); + } + + public String getAppProperty(String name) { + if (StringUtils.isBlank(name)) + return "Enter a property name"; + + return name + "=" + AppContext.getProperty(name); + } + + public String setAppProperty(String name, String value) { + if (StringUtils.isBlank(name)) + return "Enter a property name"; + if (StringUtils.isBlank(value)) + return "Enter a property value"; + + AppContext.setProperty(name, value); + return String.format("Property %s set to %s", name, value); + } + + /** + * Method returns a result of config method invocation + * @param classFQN fully qualified configuration interface name + * @param methodName config getter method name + * @param userLogin parameter is used for authentication if there is no security context bound to the current thread + * and configuration method source is DATABASE + * @param userPassword see userLogin parameter description + * @return configuration method invocation result + */ + public String getConfigValue(String classFQN, String methodName, String userLogin, String userPassword) { + Class aClass; + try { + aClass = Class.forName(classFQN); + } catch (ClassNotFoundException e) { + return String.format("Class %s not found.\nPlease ensure that you entered a fully qualified class name and " + + "that you class is in a proper application module (core, web or portal).", classFQN); + } + + if (Config.class.isAssignableFrom(aClass)) { + Config config = configuration.getConfig((Class)aClass); + Method method; + boolean logoutRequired = false; + try { + method = aClass.getMethod(methodName); + + //if there is no security context bound to the current thread and the source of the config method is + //DATABASE, then login attempt with 'userLogin' and 'userPassword' will be made + if (AppContext.getSecurityContext() == null) { + SourceType sourceType; + Source methodSourceAnnotation = method.getAnnotation(Source.class); + if (methodSourceAnnotation != null) { + sourceType = methodSourceAnnotation.type(); + } else { + Source classSourceAnnotation = aClass.getAnnotation(Source.class); + sourceType = classSourceAnnotation.type(); + } + + if (sourceType != null && sourceType == SourceType.DATABASE) { + if (Strings.isNullOrEmpty(userLogin)) { + return "No security context bound to the current thread. Please specify the user name."; + } else { + try { + Map availableLocales = configuration.getConfig(GlobalConfig.class).getAvailableLocales(); + Locale defaultLocale = availableLocales.values().iterator().next(); + + TrustedClientCredentials credentials = new TrustedClientCredentials(userLogin, userPassword, defaultLocale); + + UserSession session = authenticationService.login(credentials).getSession(); + AppContext.setSecurityContext(new SecurityContext(session)); + logoutRequired = true; + } catch (LoginException e) { + log.error(ExceptionUtils.getStackTrace(e)); + return "Login error: " + e.getMessage(); + } + } + } + } + + Object result = method.invoke(config); + return result == null ? null : result.toString(); + } catch (NoSuchMethodException e) { + return String.format("Method %s() not found in class %s", methodName, classFQN); + } catch (InvocationTargetException | IllegalAccessException e) { + return ExceptionUtils.getStackTrace(e); + } finally { + if (logoutRequired) { + try { + authenticationService.logout(); + } finally { + AppContext.setSecurityContext(null); + } + } + } + } else { + return String.format("Class %s is not an implementation of Config interface", classFQN); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/EnumStore.java b/modules/global/src/com/haulmont/cuba/core/config/EnumStore.java index eff208c6c3..c1e4bb73d2 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/EnumStore.java +++ b/modules/global/src/com/haulmont/cuba/core/config/EnumStore.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation for config properties, specifying the way to store enum values. - * - * @see EnumStoreMode - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface EnumStore { - - EnumStoreMode value(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for config properties, specifying the way to store enum values. + * + * @see EnumStoreMode + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface EnumStore { + + EnumStoreMode value(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/EnumStoreMode.java b/modules/global/src/com/haulmont/cuba/core/config/EnumStoreMode.java index 0e275ac0f5..96e5a5b45d 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/EnumStoreMode.java +++ b/modules/global/src/com/haulmont/cuba/core/config/EnumStoreMode.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config; - -/** - * Identifies the way to store enum class values in the config storage. - * - */ -public enum EnumStoreMode { - - /** - * Store enum IDs. - * Requires public static {@code fromId} class and work only with primitive ids - * for which stringify and type factory instances can be inferred from class definitions. - */ - ID, - - /** - * Store enum names. - */ - NAME +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config; + +/** + * Identifies the way to store enum class values in the config storage. + * + */ +public enum EnumStoreMode { + + /** + * Store enum IDs. + * Requires public static {@code fromId} class and work only with primitive ids + * for which stringify and type factory instances can be inferred from class definitions. + */ + ID, + + /** + * Store enum names. + */ + NAME } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/Source.java b/modules/global/src/com/haulmont/cuba/core/config/Source.java index 3f45439a16..6bc304bb10 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/Source.java +++ b/modules/global/src/com/haulmont/cuba/core/config/Source.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.config; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD}) -public @interface Source { - SourceType type(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.config; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface Source { + SourceType type(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/SourceType.java b/modules/global/src/com/haulmont/cuba/core/config/SourceType.java index 21d6b63fa4..9ed3d9b890 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/SourceType.java +++ b/modules/global/src/com/haulmont/cuba/core/config/SourceType.java @@ -1,23 +1,23 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.config; - -public enum SourceType { - SYSTEM, - APP, - DATABASE +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.config; + +public enum SourceType { + SYSTEM, + APP, + DATABASE } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/CommaSeparatedStringListTypeFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/CommaSeparatedStringListTypeFactory.java index 2291522ef0..760cb35777 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/CommaSeparatedStringListTypeFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/CommaSeparatedStringListTypeFactory.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import org.apache.commons.lang.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -public class CommaSeparatedStringListTypeFactory extends TypeFactory { - - @Override - public Object build(String string) { - List stringList = new ArrayList<>(); - if (StringUtils.isNotEmpty(string)) { - String[] elements = string.split(","); - for (String element : elements) { - if (StringUtils.isNotEmpty(element)) { - stringList.add(element.trim()); - } - } - } - return stringList; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import org.apache.commons.lang.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class CommaSeparatedStringListTypeFactory extends TypeFactory { + + @Override + public Object build(String string) { + List stringList = new ArrayList<>(); + if (StringUtils.isNotEmpty(string)) { + String[] elements = string.split(","); + for (String element : elements) { + if (StringUtils.isNotEmpty(element)) { + stringList.add(element.trim()); + } + } + } + return stringList; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/DateFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/DateFactory.java index ca53321b81..f53be24008 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/DateFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/DateFactory.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import java.text.SimpleDateFormat; -import java.text.DateFormat; -import java.text.ParseException; - -public class DateFactory extends TypeFactory { - @Override - public Object build(String string) { - if (string == null) - return null; - - DateFormat df = new SimpleDateFormat(DateStringify.DATE_FORMAT); - try { - return df.parse(string); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import java.text.SimpleDateFormat; +import java.text.DateFormat; +import java.text.ParseException; + +public class DateFactory extends TypeFactory { + @Override + public Object build(String string) { + if (string == null) + return null; + + DateFormat df = new SimpleDateFormat(DateStringify.DATE_FORMAT); + try { + return df.parse(string); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/DateStringify.java b/modules/global/src/com/haulmont/cuba/core/config/type/DateStringify.java index 9aa08149a2..223ec01295 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/DateStringify.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/DateStringify.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -public class DateStringify extends TypeStringify { - - public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; - - @Override - public String stringify(Object value) { - DateFormat df = new SimpleDateFormat(DATE_FORMAT); - return df.format(value); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +public class DateStringify extends TypeStringify { + + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; + + @Override + public String stringify(Object value) { + DateFormat df = new SimpleDateFormat(DATE_FORMAT); + return df.format(value); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/EntityStringify.java b/modules/global/src/com/haulmont/cuba/core/config/type/EntityStringify.java index fe40e15874..b31511fed1 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/EntityStringify.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/EntityStringify.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.OriginalEntityLoadInfo; - -public class EntityStringify extends TypeStringify { - - @Override - public String stringify(Object value) { - OriginalEntityLoadInfo entityLoadInfo = OriginalEntityLoadInfo.create((Entity) value); - return entityLoadInfo.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.OriginalEntityLoadInfo; + +public class EntityStringify extends TypeStringify { + + @Override + public String stringify(Object value) { + OriginalEntityLoadInfo entityLoadInfo = OriginalEntityLoadInfo.create((Entity) value); + return entityLoadInfo.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassFactory.java index fefdab2bce..03449ddf20 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassFactory.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class EnumClassFactory extends TypeFactory { - - private TypeFactory idFactory; - private Method fromIdMethod; - - public EnumClassFactory(TypeFactory idFactory, Method fromIdMethod) { - this.idFactory = idFactory; - this.fromIdMethod = fromIdMethod; - } - - @Override - public Object build(String string) { - try { - Object id = idFactory.build(string); - return fromIdMethod.invoke(null, id); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException("TypeFactory build error", e); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class EnumClassFactory extends TypeFactory { + + private TypeFactory idFactory; + private Method fromIdMethod; + + public EnumClassFactory(TypeFactory idFactory, Method fromIdMethod) { + this.idFactory = idFactory; + this.fromIdMethod = fromIdMethod; + } + + @Override + public Object build(String string) { + try { + Object id = idFactory.build(string); + return fromIdMethod.invoke(null, id); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("TypeFactory build error", e); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassStringify.java b/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassStringify.java index 3dfcad8da9..79fdd9df18 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassStringify.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/EnumClassStringify.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; - -public class EnumClassStringify extends TypeStringify { - - private TypeStringify idStringify; - - public EnumClassStringify(TypeStringify idStringify) { - this.idStringify = idStringify; - } - - @Override - public String stringify(Object value) { - EnumClass enumeration = (EnumClass) value; - return idStringify.stringify(enumeration.getId()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; + +public class EnumClassStringify extends TypeStringify { + + private TypeStringify idStringify; + + public EnumClassStringify(TypeStringify idStringify) { + this.idStringify = idStringify; + } + + @Override + public String stringify(Object value) { + EnumClass enumeration = (EnumClass) value; + return idStringify.stringify(enumeration.getId()); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/IntegerListTypeFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/IntegerListTypeFactory.java index cc4fd1d4d8..ce996c7726 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/IntegerListTypeFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/IntegerListTypeFactory.java @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class IntegerListTypeFactory extends TypeFactory { - - private Logger log = LoggerFactory.getLogger(IntegerListTypeFactory.class); - - @Override - public Object build(String string) { - List integerList = new ArrayList<>(); - if (StringUtils.isNotEmpty(string)) { - String[] elements = string.split(" "); - for (String element : elements) { - if (StringUtils.isNotEmpty(element)) { - try { - Integer value = Integer.parseInt(element); - integerList.add(value); - } catch (NumberFormatException e) { - log.debug("Invalid integer list property: " + string); - return Collections.emptyList(); - } - } - } - } - return integerList; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class IntegerListTypeFactory extends TypeFactory { + + private Logger log = LoggerFactory.getLogger(IntegerListTypeFactory.class); + + @Override + public Object build(String string) { + List integerList = new ArrayList<>(); + if (StringUtils.isNotEmpty(string)) { + String[] elements = string.split(" "); + for (String element : elements) { + if (StringUtils.isNotEmpty(element)) { + try { + Integer value = Integer.parseInt(element); + integerList.add(value); + } catch (NumberFormatException e) { + log.debug("Invalid integer list property: " + string); + return Collections.emptyList(); + } + } + } + } + return integerList; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/PrimitiveTypeStringify.java b/modules/global/src/com/haulmont/cuba/core/config/type/PrimitiveTypeStringify.java index 6292c4b68e..9e349d6869 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/PrimitiveTypeStringify.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/PrimitiveTypeStringify.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.config.type; - -public class PrimitiveTypeStringify extends TypeStringify { - @Override - public String stringify(Object value) { - return String.valueOf(value); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.config.type; + +public class PrimitiveTypeStringify extends TypeStringify { + @Override + public String stringify(Object value) { + return String.valueOf(value); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/StringListTypeFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/StringListTypeFactory.java index 2984e442f7..011e739e07 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/StringListTypeFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/StringListTypeFactory.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import org.apache.commons.lang.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -public class StringListTypeFactory extends TypeFactory { - @Override - public Object build(String string) { - List stringList = new ArrayList<>(); - if (StringUtils.isNotEmpty(string)) { - String[] elements = string.split("\\|"); - for (String element : elements) { - if (StringUtils.isNotEmpty(element)) { - stringList.add(element); - } - } - } - return stringList; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import org.apache.commons.lang.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class StringListTypeFactory extends TypeFactory { + @Override + public Object build(String string) { + List stringList = new ArrayList<>(); + if (StringUtils.isNotEmpty(string)) { + String[] elements = string.split("\\|"); + for (String element : elements) { + if (StringUtils.isNotEmpty(element)) { + stringList.add(element); + } + } + } + return stringList; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/config/type/UuidTypeFactory.java b/modules/global/src/com/haulmont/cuba/core/config/type/UuidTypeFactory.java index a2e1616422..78282d9de9 100644 --- a/modules/global/src/com/haulmont/cuba/core/config/type/UuidTypeFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/config/type/UuidTypeFactory.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.config.type; - -import com.haulmont.cuba.core.global.UuidProvider; - -public class UuidTypeFactory extends TypeFactory { - @Override - public Object build(String string) { - if (string == null) { - return null; - } - - return UuidProvider.fromString(string); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.config.type; + +import com.haulmont.cuba.core.global.UuidProvider; + +public class UuidTypeFactory extends TypeFactory { + @Override + public Object build(String string) { + if (string == null) { + return null; + } + + return UuidProvider.fromString(string); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/AbstractNotPersistentEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/AbstractNotPersistentEntity.java index 0a73bfc57f..e384ebaf70 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/AbstractNotPersistentEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/AbstractNotPersistentEntity.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.impl.AbstractInstance; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.UuidProvider; -import com.haulmont.cuba.core.sys.CubaEnhanced; -import com.haulmont.cuba.core.sys.CubaEnhancingDisabled; - -import java.util.UUID; - -/** - * Base class for not persistent entities. - * - * DEPRECATED! Use subclasses of BaseGenericIdEntity. - */ -@Deprecated -@com.haulmont.chile.core.annotations.MetaClass(name = "sys$AbstractNotPersistentEntity") -@SystemLevel(propagateToSubclasses = false) -public abstract class AbstractNotPersistentEntity - extends AbstractInstance - implements Entity, HasUuid, CubaEnhancingDisabled { - - private static final long serialVersionUID = -2846020822531467401L; - - protected UUID id; - - protected boolean __new = true; - - protected AbstractNotPersistentEntity() { - id = UuidProvider.createUuid(); - } - - @Override - public UUID getUuid() { - return id; - } - - @Override - public void setUuid(UUID uuid) { - id = uuid; - } - - @Override - public MetaClass getMetaClass() { - Metadata metadata = AppBeans.get(Metadata.NAME); - return metadata.getSession().getClassNN(getClass()); - } - - @MetaProperty - @Override - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - @Override - public void setValue(String property, Object obj, boolean checkEquals) { - Object oldValue = getValue(property); - if ((!checkEquals) || (!InstanceUtils.propertyValueEquals(oldValue, obj))) { - getMethodsCache().invokeSetter(this, property, obj); - if (!(this instanceof CubaEnhanced)) { - propertyChanged(property, oldValue, obj); - } - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - AbstractNotPersistentEntity that = (AbstractNotPersistentEntity) o; - - return !(getUuid() != null ? !getUuid().equals(that.getUuid()) : that.getUuid() != null); - } - - @Override - public int hashCode() { - return getUuid() != null ? getUuid().hashCode() : 0; - } - - @Override - public String toString() { - return getClass().getName() + "-" + getUuid(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.impl.AbstractInstance; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.UuidProvider; +import com.haulmont.cuba.core.sys.CubaEnhanced; +import com.haulmont.cuba.core.sys.CubaEnhancingDisabled; + +import java.util.UUID; + +/** + * Base class for not persistent entities. + * + * DEPRECATED! Use subclasses of BaseGenericIdEntity. + */ +@Deprecated +@com.haulmont.chile.core.annotations.MetaClass(name = "sys$AbstractNotPersistentEntity") +@SystemLevel(propagateToSubclasses = false) +public abstract class AbstractNotPersistentEntity + extends AbstractInstance + implements Entity, HasUuid, CubaEnhancingDisabled { + + private static final long serialVersionUID = -2846020822531467401L; + + protected UUID id; + + protected boolean __new = true; + + protected AbstractNotPersistentEntity() { + id = UuidProvider.createUuid(); + } + + @Override + public UUID getUuid() { + return id; + } + + @Override + public void setUuid(UUID uuid) { + id = uuid; + } + + @Override + public MetaClass getMetaClass() { + Metadata metadata = AppBeans.get(Metadata.NAME); + return metadata.getSession().getClassNN(getClass()); + } + + @MetaProperty + @Override + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + @Override + public void setValue(String property, Object obj, boolean checkEquals) { + Object oldValue = getValue(property); + if ((!checkEquals) || (!InstanceUtils.propertyValueEquals(oldValue, obj))) { + getMethodsCache().invokeSetter(this, property, obj); + if (!(this instanceof CubaEnhanced)) { + propertyChanged(property, oldValue, obj); + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + AbstractNotPersistentEntity that = (AbstractNotPersistentEntity) o; + + return !(getUuid() != null ? !getUuid().equals(that.getUuid()) : that.getUuid() != null); + } + + @Override + public int hashCode() { + return getUuid() != null ? getUuid().hashCode() : 0; + } + + @Override + public String toString() { + return getClass().getName() + "-" + getUuid(); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/AbstractSearchFolder.java b/modules/global/src/com/haulmont/cuba/core/entity/AbstractSearchFolder.java index 858558a0c6..1d7d706961 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/AbstractSearchFolder.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/AbstractSearchFolder.java @@ -1,89 +1,89 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; - -@MappedSuperclass -@SystemLevel -public abstract class AbstractSearchFolder extends Folder { - - private static final long serialVersionUID = -2234453892776090930L; - - @Column(name = "FILTER_COMPONENT") - protected String filterComponentId; - - @Column(name = "FILTER_XML") - protected String filterXml; - - @Column(name = "APPLY_DEFAULT") - protected Boolean applyDefault = true; - - public void copyFrom(AbstractSearchFolder srcFolder) { - setCreatedBy(srcFolder.getCreatedBy()); - setCreateTs(srcFolder.getCreateTs()); - setDeletedBy(srcFolder.getDeletedBy()); - setDeleteTs(srcFolder.getDeleteTs()); - setFilterComponentId(srcFolder.getFilterComponentId()); - setFilterXml(srcFolder.getFilterXml()); - setName(srcFolder.getCaption()); - setTabName(srcFolder.getTabName()); - setParent(srcFolder.getParent()); - setItemStyle(srcFolder.getItemStyle()); - setSortOrder(srcFolder.getSortOrder()); - } - - public String getFilterComponentId() { - return filterComponentId; - } - - public void setFilterComponentId(String filterComponentId) { - this.filterComponentId = filterComponentId; - } - - public String getFilterXml() { - return filterXml; - } - - public void setFilterXml(String filterXml) { - this.filterXml = filterXml; - } - - public Boolean getApplyDefault() { - return applyDefault; - } - - public void setApplyDefault(Boolean applyDefault) { - this.applyDefault = applyDefault; - } - - @MetaProperty - public String getLocName() { - if (StringUtils.isNotEmpty(name)) { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage(name); - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; + +@MappedSuperclass +@SystemLevel +public abstract class AbstractSearchFolder extends Folder { + + private static final long serialVersionUID = -2234453892776090930L; + + @Column(name = "FILTER_COMPONENT") + protected String filterComponentId; + + @Column(name = "FILTER_XML") + protected String filterXml; + + @Column(name = "APPLY_DEFAULT") + protected Boolean applyDefault = true; + + public void copyFrom(AbstractSearchFolder srcFolder) { + setCreatedBy(srcFolder.getCreatedBy()); + setCreateTs(srcFolder.getCreateTs()); + setDeletedBy(srcFolder.getDeletedBy()); + setDeleteTs(srcFolder.getDeleteTs()); + setFilterComponentId(srcFolder.getFilterComponentId()); + setFilterXml(srcFolder.getFilterXml()); + setName(srcFolder.getCaption()); + setTabName(srcFolder.getTabName()); + setParent(srcFolder.getParent()); + setItemStyle(srcFolder.getItemStyle()); + setSortOrder(srcFolder.getSortOrder()); + } + + public String getFilterComponentId() { + return filterComponentId; + } + + public void setFilterComponentId(String filterComponentId) { + this.filterComponentId = filterComponentId; + } + + public String getFilterXml() { + return filterXml; + } + + public void setFilterXml(String filterXml) { + this.filterXml = filterXml; + } + + public Boolean getApplyDefault() { + return applyDefault; + } + + public void setApplyDefault(Boolean applyDefault) { + this.applyDefault = applyDefault; + } + + @MetaProperty + public String getLocName() { + if (StringUtils.isNotEmpty(name)) { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage(name); + } + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/AppFolder.java b/modules/global/src/com/haulmont/cuba/core/entity/AppFolder.java index a758cf2b40..28d2ab4b97 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/AppFolder.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/AppFolder.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.annotation.EnableRestore; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import javax.persistence.Entity; - -@Entity(name = "sys$AppFolder") -@Table(name = "SYS_APP_FOLDER") -@PrimaryKeyJoinColumn(name = "FOLDER_ID", referencedColumnName = "ID") -@DiscriminatorValue("A") -@EnableRestore -public class AppFolder extends AbstractSearchFolder { - - private static final long serialVersionUID = -3587493035203986325L; - - @Column(name = "VISIBILITY_SCRIPT", length = 200) - protected String visibilityScript; - - @Column(name = "QUANTITY_SCRIPT", length = 200) - protected String quantityScript; - - @MetaProperty - @Transient - protected Integer quantity; - - @Override - public void copyFrom(AbstractSearchFolder srcFolder) { - super.copyFrom(srcFolder); - - setVisibilityScript(((AppFolder) srcFolder).getVisibilityScript()); - setQuantityScript(((AppFolder) srcFolder).getQuantityScript()); - } - - public String getVisibilityScript() { - return visibilityScript; - } - - public void setVisibilityScript(String visibilityScript) { - this.visibilityScript = visibilityScript; - } - - public String getQuantityScript() { - return quantityScript; - } - - public void setQuantityScript(String quantityScript) { - this.quantityScript = quantityScript; - } - - public Integer getQuantity() { - return quantity; - } - - public void setQuantity(Integer quantity) { - this.quantity = quantity; - } - - @Override - public String getCaption() { - String s = getLocName(); - if (quantity == null) { - return s; - } else { - return s + " (" + quantity + ")"; - } - } - - @Override - public String toString() { - return getName() + " (" + quantity + ")"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.annotation.EnableRestore; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import javax.persistence.Entity; + +@Entity(name = "sys$AppFolder") +@Table(name = "SYS_APP_FOLDER") +@PrimaryKeyJoinColumn(name = "FOLDER_ID", referencedColumnName = "ID") +@DiscriminatorValue("A") +@EnableRestore +public class AppFolder extends AbstractSearchFolder { + + private static final long serialVersionUID = -3587493035203986325L; + + @Column(name = "VISIBILITY_SCRIPT", length = 200) + protected String visibilityScript; + + @Column(name = "QUANTITY_SCRIPT", length = 200) + protected String quantityScript; + + @MetaProperty + @Transient + protected Integer quantity; + + @Override + public void copyFrom(AbstractSearchFolder srcFolder) { + super.copyFrom(srcFolder); + + setVisibilityScript(((AppFolder) srcFolder).getVisibilityScript()); + setQuantityScript(((AppFolder) srcFolder).getQuantityScript()); + } + + public String getVisibilityScript() { + return visibilityScript; + } + + public void setVisibilityScript(String visibilityScript) { + this.visibilityScript = visibilityScript; + } + + public String getQuantityScript() { + return quantityScript; + } + + public void setQuantityScript(String quantityScript) { + this.quantityScript = quantityScript; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + @Override + public String getCaption() { + String s = getLocName(); + if (quantity == null) { + return s; + } else { + return s + " (" + quantity + ")"; + } + } + + @Override + public String toString() { + return getName() + " (" + quantity + ")"; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/BaseEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/BaseEntity.java index ecfea1b125..ffc7b48637 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/BaseEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/BaseEntity.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -/** - * DEPRECATED. Use {@link Entity}. - */ -@Deprecated -public interface BaseEntity extends Entity { -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +/** + * DEPRECATED. Use {@link Entity}. + */ +@Deprecated +public interface BaseEntity extends Entity { +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/BaseGenericIdEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/BaseGenericIdEntity.java index e4ae6e8064..b352494106 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/BaseGenericIdEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/BaseGenericIdEntity.java @@ -1,184 +1,184 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.google.common.base.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.impl.AbstractInstance; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; -import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; -import com.haulmont.cuba.core.global.*; -import org.apache.commons.lang.ObjectUtils; - -import javax.annotation.Nullable; -import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Base class for persistent entities. - *
- * When choosing a base class for your entity, consider more specific base classes defining the primary key type: - *

    - *
  • {@link BaseUuidEntity}
  • - *
  • {@link BaseLongIdEntity}
  • - *
  • {@link BaseIntegerIdEntity}
  • - *
  • {@link BaseStringIdEntity}
  • - *
- * or most commonly used {@link StandardEntity}. - */ -@MappedSuperclass -@com.haulmont.chile.core.annotations.MetaClass(name = "sys$BaseGenericIdEntity") -@UnavailableInSecurityConstraints -public abstract class BaseGenericIdEntity extends AbstractInstance implements Entity { - - private static final long serialVersionUID = -8400641366148656528L; - - @Transient - protected boolean __new = true; - - @Transient - protected boolean __detached; - - protected transient boolean __managed; - - @Transient - protected boolean __removed; - - @Transient - protected SecurityState __securityState; - - @Transient - protected Map dynamicAttributes = null; - - public abstract void setId(T id); - - private void writeObject(java.io.ObjectOutputStream out) throws IOException { - if (__managed) - __detached = true; - out.defaultWriteObject(); - } - - @Override - public MetaClass getMetaClass() { - Metadata metadata = AppBeans.get(Metadata.NAME); - return metadata.getSession().getClassNN(getClass()); - } - - @Override - public void setValue(String property, Object newValue, boolean checkEquals) { - if (DynamicAttributesUtils.isDynamicAttribute(property)) { - Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly"); - String attributeCode = DynamicAttributesUtils.decodeAttributeCode(property); - CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(attributeCode); - Object oldValue = categoryAttributeValue != null ? categoryAttributeValue.getValue() : null; - - if (newValue == null) { - if (categoryAttributeValue != null) { - categoryAttributeValue.setValue(null); - categoryAttributeValue.setDeleteTs(AppBeans.get(TimeSource.class).currentTimestamp()); - propertyChanged(property, oldValue, null); - } - } else if (!ObjectUtils.equals(oldValue, newValue)) { - if (categoryAttributeValue != null) { - categoryAttributeValue.setValue(newValue); - categoryAttributeValue.setDeleteTs(null); - } else { - Metadata metadata = AppBeans.get(Metadata.NAME); - ReferenceToEntitySupport referenceToEntitySupport = AppBeans.get(ReferenceToEntitySupport.class); - - categoryAttributeValue = metadata.create(CategoryAttributeValue.class); - categoryAttributeValue.setValue(newValue); - categoryAttributeValue.setObjectEntityId(referenceToEntitySupport.getReferenceId(this)); - categoryAttributeValue.setCode(attributeCode); - DynamicAttributes dynamicAttributesBean = AppBeans.get(DynamicAttributes.NAME); - categoryAttributeValue.setCategoryAttribute( - dynamicAttributesBean.getAttributeForMetaClass(getMetaClass(), attributeCode)); - dynamicAttributes.put(attributeCode, categoryAttributeValue); - } - propertyChanged(property, oldValue, newValue); - } - } else { - super.setValue(property, newValue, checkEquals); - } - } - - @Override - @SuppressWarnings("unchecked") - public V getValue(String property) { - if (DynamicAttributesUtils.isDynamicAttribute(property)) { - if (PersistenceHelper.isNew(this) && dynamicAttributes == null) { - dynamicAttributes = new HashMap<>(); - } - - Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly"); - CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(DynamicAttributesUtils.decodeAttributeCode(property)); - if (categoryAttributeValue != null) { - return (V) categoryAttributeValue.getValue(); - } else { - return null; - } - } else { - return super.getValue(property); - } - } - - public void setDynamicAttributes(Map dynamicAttributes) { - this.dynamicAttributes = dynamicAttributes; - } - - @Nullable - public Map getDynamicAttributes() { - return dynamicAttributes; - } - - @Override - public boolean equals(Object other) { - if (this == other) - return true; - - if (other == null || getClass() != other.getClass()) - return false; - - return Objects.equals(getId(), ((BaseGenericIdEntity) other).getId()); - } - - @Override - public int hashCode() { - return getId() != null ? getId().hashCode() : 0; - } - - @Override - public String toString() { - String state = ""; - if (__new) - state += "new,"; - if (__managed) - state += "managed,"; - if (__detached) - state += "detached,"; - if (__removed) - state += "removed,"; - if (state.length() > 0) - state = state.substring(0, state.length() - 1); - return getClass().getName() + "-" + getId() + " [" + state + "]"; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.google.common.base.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.impl.AbstractInstance; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; +import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; +import com.haulmont.cuba.core.global.*; +import org.apache.commons.lang.ObjectUtils; + +import javax.annotation.Nullable; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Base class for persistent entities. + *
+ * When choosing a base class for your entity, consider more specific base classes defining the primary key type: + *
    + *
  • {@link BaseUuidEntity}
  • + *
  • {@link BaseLongIdEntity}
  • + *
  • {@link BaseIntegerIdEntity}
  • + *
  • {@link BaseStringIdEntity}
  • + *
+ * or most commonly used {@link StandardEntity}. + */ +@MappedSuperclass +@com.haulmont.chile.core.annotations.MetaClass(name = "sys$BaseGenericIdEntity") +@UnavailableInSecurityConstraints +public abstract class BaseGenericIdEntity extends AbstractInstance implements Entity { + + private static final long serialVersionUID = -8400641366148656528L; + + @Transient + protected boolean __new = true; + + @Transient + protected boolean __detached; + + protected transient boolean __managed; + + @Transient + protected boolean __removed; + + @Transient + protected SecurityState __securityState; + + @Transient + protected Map dynamicAttributes = null; + + public abstract void setId(T id); + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + if (__managed) + __detached = true; + out.defaultWriteObject(); + } + + @Override + public MetaClass getMetaClass() { + Metadata metadata = AppBeans.get(Metadata.NAME); + return metadata.getSession().getClassNN(getClass()); + } + + @Override + public void setValue(String property, Object newValue, boolean checkEquals) { + if (DynamicAttributesUtils.isDynamicAttribute(property)) { + Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly"); + String attributeCode = DynamicAttributesUtils.decodeAttributeCode(property); + CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(attributeCode); + Object oldValue = categoryAttributeValue != null ? categoryAttributeValue.getValue() : null; + + if (newValue == null) { + if (categoryAttributeValue != null) { + categoryAttributeValue.setValue(null); + categoryAttributeValue.setDeleteTs(AppBeans.get(TimeSource.class).currentTimestamp()); + propertyChanged(property, oldValue, null); + } + } else if (!ObjectUtils.equals(oldValue, newValue)) { + if (categoryAttributeValue != null) { + categoryAttributeValue.setValue(newValue); + categoryAttributeValue.setDeleteTs(null); + } else { + Metadata metadata = AppBeans.get(Metadata.NAME); + ReferenceToEntitySupport referenceToEntitySupport = AppBeans.get(ReferenceToEntitySupport.class); + + categoryAttributeValue = metadata.create(CategoryAttributeValue.class); + categoryAttributeValue.setValue(newValue); + categoryAttributeValue.setObjectEntityId(referenceToEntitySupport.getReferenceId(this)); + categoryAttributeValue.setCode(attributeCode); + DynamicAttributes dynamicAttributesBean = AppBeans.get(DynamicAttributes.NAME); + categoryAttributeValue.setCategoryAttribute( + dynamicAttributesBean.getAttributeForMetaClass(getMetaClass(), attributeCode)); + dynamicAttributes.put(attributeCode, categoryAttributeValue); + } + propertyChanged(property, oldValue, newValue); + } + } else { + super.setValue(property, newValue, checkEquals); + } + } + + @Override + @SuppressWarnings("unchecked") + public V getValue(String property) { + if (DynamicAttributesUtils.isDynamicAttribute(property)) { + if (PersistenceHelper.isNew(this) && dynamicAttributes == null) { + dynamicAttributes = new HashMap<>(); + } + + Preconditions.checkState(dynamicAttributes != null, "Dynamic attributes should be loaded explicitly"); + CategoryAttributeValue categoryAttributeValue = dynamicAttributes.get(DynamicAttributesUtils.decodeAttributeCode(property)); + if (categoryAttributeValue != null) { + return (V) categoryAttributeValue.getValue(); + } else { + return null; + } + } else { + return super.getValue(property); + } + } + + public void setDynamicAttributes(Map dynamicAttributes) { + this.dynamicAttributes = dynamicAttributes; + } + + @Nullable + public Map getDynamicAttributes() { + return dynamicAttributes; + } + + @Override + public boolean equals(Object other) { + if (this == other) + return true; + + if (other == null || getClass() != other.getClass()) + return false; + + return Objects.equals(getId(), ((BaseGenericIdEntity) other).getId()); + } + + @Override + public int hashCode() { + return getId() != null ? getId().hashCode() : 0; + } + + @Override + public String toString() { + String state = ""; + if (__new) + state += "new,"; + if (__managed) + state += "managed,"; + if (__detached) + state += "detached,"; + if (__removed) + state += "removed,"; + if (state.length() > 0) + state = state.substring(0, state.length() - 1); + return getClass().getName() + "-" + getId() + " [" + state + "]"; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/BaseIntegerIdEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/BaseIntegerIdEntity.java index 97c016b07f..a35875c941 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/BaseIntegerIdEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/BaseIntegerIdEntity.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; - -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; - -/** - * Base class for persistent entities with Integer identifier. - */ -@MappedSuperclass -@MetaClass(name = "sys$BaseIntegerIdEntity") -@UnavailableInSecurityConstraints -public abstract class BaseIntegerIdEntity extends BaseGenericIdEntity { - - private static final long serialVersionUID = 1748237513475338490L; - - @Id - @Column(name = "ID") - protected Integer id; - - @Override - public Integer getId() { - return id; - } - - @Override - public void setId(Integer id) { - this.id = id; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +/** + * Base class for persistent entities with Integer identifier. + */ +@MappedSuperclass +@MetaClass(name = "sys$BaseIntegerIdEntity") +@UnavailableInSecurityConstraints +public abstract class BaseIntegerIdEntity extends BaseGenericIdEntity { + + private static final long serialVersionUID = 1748237513475338490L; + + @Id + @Column(name = "ID") + protected Integer id; + + @Override + public Integer getId() { + return id; + } + + @Override + public void setId(Integer id) { + this.id = id; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/BaseLongIdEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/BaseLongIdEntity.java index 01b5800a9f..eb8a6c3b51 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/BaseLongIdEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/BaseLongIdEntity.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; - -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; - -/** - * Base class for persistent entities with Long identifier. - */ -@MappedSuperclass -@MetaClass(name = "sys$BaseLongIdEntity") -@UnavailableInSecurityConstraints -public abstract class BaseLongIdEntity extends BaseGenericIdEntity { - - private static final long serialVersionUID = 1748237513475338490L; - - @Id - @Column(name = "ID") - protected Long id; - - @Override - public Long getId() { - return id; - } - - @Override - public void setId(Long id) { - this.id = id; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +/** + * Base class for persistent entities with Long identifier. + */ +@MappedSuperclass +@MetaClass(name = "sys$BaseLongIdEntity") +@UnavailableInSecurityConstraints +public abstract class BaseLongIdEntity extends BaseGenericIdEntity { + + private static final long serialVersionUID = 1748237513475338490L; + + @Id + @Column(name = "ID") + protected Long id; + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/BaseUuidEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/BaseUuidEntity.java index 025f3ca24c..a7da624f36 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/BaseUuidEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/BaseUuidEntity.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; -import com.haulmont.cuba.core.global.UuidProvider; - -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import java.util.UUID; - -/** - * Base class for persistent entities with UUID identifier. - *

- * Inherit from it if you need an entity without optimistic locking, create, update and soft deletion info. - */ -@MappedSuperclass -@MetaClass(name = "sys$BaseUuidEntity") -@UnavailableInSecurityConstraints -public abstract class BaseUuidEntity extends BaseGenericIdEntity implements HasUuid { - - private static final long serialVersionUID = -2217624132287086972L; - - @Id - @Column(name = "ID") - protected UUID id; - - public BaseUuidEntity() { - id = UuidProvider.createUuid(); - } - - @Override - public UUID getId() { - return id; - } - - @Override - public void setId(UUID id) { - this.id = id; - } - - @Override - public UUID getUuid() { - return id; - } - - public void setUuid(UUID uuid) { - this.id = uuid; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; +import com.haulmont.cuba.core.global.UuidProvider; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import java.util.UUID; + +/** + * Base class for persistent entities with UUID identifier. + *

+ * Inherit from it if you need an entity without optimistic locking, create, update and soft deletion info. + */ +@MappedSuperclass +@MetaClass(name = "sys$BaseUuidEntity") +@UnavailableInSecurityConstraints +public abstract class BaseUuidEntity extends BaseGenericIdEntity implements HasUuid { + + private static final long serialVersionUID = -2217624132287086972L; + + @Id + @Column(name = "ID") + protected UUID id; + + public BaseUuidEntity() { + id = UuidProvider.createUuid(); + } + + @Override + public UUID getId() { + return id; + } + + @Override + public void setId(UUID id) { + this.id = id; + } + + @Override + public UUID getUuid() { + return id; + } + + public void setUuid(UUID uuid) { + this.id = uuid; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Categorized.java b/modules/global/src/com/haulmont/cuba/core/entity/Categorized.java index cd6f019a82..b6d39aa912 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Categorized.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Categorized.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -/** - * Interface to be implemented by entities which can be separated by categories and hence have several sets of - * dynamic attributes. - * Such entities can be displayed in RuntimePropertiesFrame. - * - */ -public interface Categorized { - - Category getCategory(); - - void setCategory(Category category); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +/** + * Interface to be implemented by entities which can be separated by categories and hence have several sets of + * dynamic attributes. + * Such entities can be displayed in RuntimePropertiesFrame. + * + */ +public interface Categorized { + + Category getCategory(); + + void setCategory(Category category); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/CategorizedEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/CategorizedEntity.java index 448c3e1723..3168b2c427 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/CategorizedEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/CategorizedEntity.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; -import com.haulmont.cuba.core.global.DeletePolicy; - -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.MappedSuperclass; - -/** - * Base class for entities which can be separated by categories and hence have several sets of dynamic attributes. - * Instead of using this base class, consider implementing {@link com.haulmont.cuba.core.entity.Categorized} interface. - * - */ -@MappedSuperclass -@MetaClass(name = "sys$CategorizedEntity") -public abstract class CategorizedEntity extends BaseUuidEntity implements Categorized { - - private static final long serialVersionUID = -4359158051274491070L; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "CATEGORY_ID") - @OnDeleteInverse(DeletePolicy.DENY) - protected Category category; - - @Override - public Category getCategory() { - return category; - } - - @Override - public void setCategory(Category category) { - this.category = category; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; +import com.haulmont.cuba.core.global.DeletePolicy; + +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; + +/** + * Base class for entities which can be separated by categories and hence have several sets of dynamic attributes. + * Instead of using this base class, consider implementing {@link com.haulmont.cuba.core.entity.Categorized} interface. + * + */ +@MappedSuperclass +@MetaClass(name = "sys$CategorizedEntity") +public abstract class CategorizedEntity extends BaseUuidEntity implements Categorized { + + private static final long serialVersionUID = -4359158051274491070L; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "CATEGORY_ID") + @OnDeleteInverse(DeletePolicy.DENY) + protected Category category; + + @Override + public Category getCategory() { + return category; + } + + @Override + public void setCategory(Category category) { + this.category = category; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Category.java b/modules/global/src/com/haulmont/cuba/core/entity/Category.java index fa4e25258c..1cbfeb1d0e 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Category.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Category.java @@ -1,120 +1,120 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.Composition; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.annotation.OnDelete; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import java.util.List; - -@javax.persistence.Entity(name = "sys$Category") -@Table(name = "SYS_CATEGORY") -@Inheritance(strategy = InheritanceType.JOINED) -@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.INTEGER) -@DiscriminatorValue("0") -@NamePattern("%s|localeName") -@SystemLevel -public class Category extends StandardEntity { - - private static final long serialVersionUID = 7160259865207148541L; - - @Column(name = "NAME", nullable = false) - protected String name; - - @Column(name = "ENTITY_TYPE", nullable = false) - protected String entityType; - - @Column(name = "IS_DEFAULT") - protected Boolean isDefault; - - @OneToMany(mappedBy = "category", targetEntity = CategoryAttribute.class) - @OnDelete(com.haulmont.cuba.core.global.DeletePolicy.CASCADE) - @OrderBy("orderNo") - @Composition - protected List categoryAttrs; - - @Column(name = "LOCALE_NAMES") - protected String localeNames; - - @Transient - @MetaProperty(related = "localeNames,name") - protected String localeName; - - @Column(name = "SPECIAL") - protected String special; - - public String getName() { - return name; - } - - public List getCategoryAttrs() { - return categoryAttrs; - } - - public void setName(String name) { - this.name = name; - } - - public void setCategoryAttrs(List categoryAttrs) { - this.categoryAttrs = categoryAttrs; - } - - public String getEntityType() { - return entityType; - } - - public void setEntityType(String entityType) { - this.entityType = entityType; - } - - public Boolean getIsDefault() { - return isDefault; - } - - public void setIsDefault(Boolean isDefault) { - this.isDefault = isDefault; - } - - public String getSpecial() { - return special; - } - - public void setSpecial(String special) { - this.special = special; - } - - public String getLocaleNames() { - return localeNames; - } - - public void setLocaleNames(String localeNames) { - this.localeNames = localeNames; - } - - public String getLocaleName() { - localeName = LocaleHelper.getLocalizedName(localeNames); - if (localeName == null) { - localeName = name; - } - return localeName; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.Composition; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.annotation.OnDelete; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import java.util.List; + +@javax.persistence.Entity(name = "sys$Category") +@Table(name = "SYS_CATEGORY") +@Inheritance(strategy = InheritanceType.JOINED) +@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.INTEGER) +@DiscriminatorValue("0") +@NamePattern("%s|localeName") +@SystemLevel +public class Category extends StandardEntity { + + private static final long serialVersionUID = 7160259865207148541L; + + @Column(name = "NAME", nullable = false) + protected String name; + + @Column(name = "ENTITY_TYPE", nullable = false) + protected String entityType; + + @Column(name = "IS_DEFAULT") + protected Boolean isDefault; + + @OneToMany(mappedBy = "category", targetEntity = CategoryAttribute.class) + @OnDelete(com.haulmont.cuba.core.global.DeletePolicy.CASCADE) + @OrderBy("orderNo") + @Composition + protected List categoryAttrs; + + @Column(name = "LOCALE_NAMES") + protected String localeNames; + + @Transient + @MetaProperty(related = "localeNames,name") + protected String localeName; + + @Column(name = "SPECIAL") + protected String special; + + public String getName() { + return name; + } + + public List getCategoryAttrs() { + return categoryAttrs; + } + + public void setName(String name) { + this.name = name; + } + + public void setCategoryAttrs(List categoryAttrs) { + this.categoryAttrs = categoryAttrs; + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public Boolean getIsDefault() { + return isDefault; + } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } + + public String getSpecial() { + return special; + } + + public void setSpecial(String special) { + this.special = special; + } + + public String getLocaleNames() { + return localeNames; + } + + public void setLocaleNames(String localeNames) { + this.localeNames = localeNames; + } + + public String getLocaleName() { + localeName = LocaleHelper.getLocalizedName(localeNames); + if (localeName == null) { + localeName = name; + } + return localeName; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttribute.java b/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttribute.java index 194b6406dc..401eca9337 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttribute.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttribute.java @@ -1,447 +1,447 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.google.common.base.Preconditions; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; -import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; -import com.haulmont.cuba.core.entity.annotation.Listeners; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.persistence.*; -import javax.persistence.Entity; -import java.util.*; - -@Entity(name = "sys$CategoryAttribute") -@Table(name = "SYS_CATEGORY_ATTR") -@NamePattern("%s|localeName") -@SystemLevel -@Listeners("report_CategoryAttributeListener") -public class CategoryAttribute extends StandardEntity { - - private static final long serialVersionUID = -6959392628534815752L; - - public static final int NAME_FIELD_LENGTH = 255; - public static final int CODE_FIELD_LENGTH = 50; - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "CATEGORY_ID") - private Category category; - - @Column(name = "CATEGORY_ENTITY_TYPE") - private String categoryEntityType; - - @Column(name = "NAME", length = NAME_FIELD_LENGTH, nullable = false) - private String name; - - @Column(name = "CODE", length = CODE_FIELD_LENGTH, nullable = false) - private String code; - - @Column(name = "ENUMERATION") - private String enumeration; - - @Column(name = "DATA_TYPE") - private String dataType; - - @Column(name = "ENTITY_CLASS") - private String entityClass; - - @Embedded - @AttributeOverrides({ - @AttributeOverride(name="entityId", column=@Column(name="DEFAULT_ENTITY_VALUE")), - @AttributeOverride(name="stringEntityId", column=@Column(name="DEFAULT_STR_ENTITY_VALUE")), - @AttributeOverride(name="intEntityId", column=@Column(name="DEFAULT_INT_ENTITY_VALUE")), - @AttributeOverride(name="longEntityId", column=@Column(name="DEFAULT_LONG_ENTITY_VALUE")) - }) - @EmbeddedParameters(nullAllowed = false) - private ReferenceToEntity defaultEntity; - - @Column(name = "ORDER_NO") - private Integer orderNo; - - @Column(name = "SCREEN") - private String screen; - - @Column(name = "REQUIRED") - private Boolean required = false; - - @Column(name = "LOOKUP") - private Boolean lookup = false; - - @Column(name = "TARGET_SCREENS") - private String targetScreens;//comma separated list of screenId#componentId pairs. componentId might be empty - - @Column(name = "DEFAULT_STRING") - private String defaultString; - - @Column(name = "DEFAULT_INT") - private Integer defaultInt; - - @Column(name = "DEFAULT_DOUBLE") - private Double defaultDouble; - - @Column(name = "DEFAULT_BOOLEAN") - private Boolean defaultBoolean; - - @Column(name = "DEFAULT_DATE") - private Date defaultDate; - - @Column(name = "DEFAULT_DATE_IS_CURRENT") - private Boolean defaultDateIsCurrent; - - @Column(name = "WIDTH", length = 20) - private String width; - - @Column(name = "ROWS_COUNT") - private Integer rowsCount; - - @Column(name = "IS_COLLECTION") - private Boolean isCollection = false; - - @Column(name = "WHERE_CLAUSE") - private String whereClause; - - @Column(name = "JOIN_CLAUSE") - private String joinClause; - - @Column(name = "FILTER_XML") - protected String filterXml; - - @Column(name = "LOCALE_NAMES") - protected String localeNames; - - @Column(name = "ENUMERATION_LOCALES") - protected String enumerationLocales; - - @Transient - @MetaProperty(related = {"localeNames", "name"}) - protected String localeName; - - @Transient - @MetaProperty(related = "enumerationLocales") - protected String enumerationLocale; - - @PostConstruct - public void init() { - Metadata metadata = AppBeans.get(Metadata.NAME); - defaultEntity = metadata.create(ReferenceToEntity.class); - } - - public void setCategory(Category entityType) { - this.category = entityType; - } - - public Category getCategory() { - return category; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEnumeration() { - return enumeration; - } - - public void setEnumeration(String e) { - this.enumeration = e; - } - - public PropertyType getDataType() { - if (dataType == null) return null; - - return PropertyType.valueOf(dataType); - } - - public void setDataType(PropertyType dataType) { - this.dataType = dataType != null ? dataType.name() : null; - } - - public Boolean getIsEntity() { - return getDataType() == PropertyType.ENTITY; - } - - public ReferenceToEntity getDefaultEntity() { - return defaultEntity; - } - - public void setDefaultEntity(ReferenceToEntity defaultEntity) { - this.defaultEntity = defaultEntity; - } - - public String getDefaultString() { - return defaultString; - } - - public void setDefaultString(String defaultString) { - this.defaultString = defaultString; - } - - public Integer getDefaultInt() { - return defaultInt; - } - - public void setDefaultInt(Integer defaultInt) { - this.defaultInt = defaultInt; - } - - public Double getDefaultDouble() { - return defaultDouble; - } - - public void setDefaultDouble(Double defaultDouble) { - this.defaultDouble = defaultDouble; - } - - public Boolean getDefaultBoolean() { - return defaultBoolean; - } - - public void setDefaultBoolean(Boolean defaultBoolean) { - this.defaultBoolean = defaultBoolean; - } - - public Date getDefaultDate() { - return defaultDate; - } - - public void setDefaultDate(Date defaultDate) { - this.defaultDate = defaultDate; - } - - public Object getDefaultValue() { - if (dataType != null) { - switch (PropertyType.valueOf(dataType)) { - case INTEGER: return defaultInt; - case DOUBLE: return defaultDouble; - case BOOLEAN: return defaultBoolean; - case DATE: return defaultDate; - case STRING: return defaultString; - case ENUMERATION: return defaultString; - case ENTITY: return getObjectDefaultEntityId(); - default: return null; - } - } - return null; - } - - public void setObjectDefaultEntityId(Object entity) { - defaultEntity.setObjectEntityId(entity); - } - - public Object getObjectDefaultEntityId() { - return defaultEntity.getObjectEntityId(); - } - - public Integer getOrderNo() { - return orderNo; - } - - public void setOrderNo(Integer orderNo) { - this.orderNo = orderNo; - } - - public String getScreen() { - return screen; - } - - public void setScreen(String screen) { - this.screen = screen; - } - - public Boolean getRequired() { - return required; - } - - public void setRequired(Boolean required) { - this.required = required; - } - - public Boolean getLookup() { - return lookup; - } - - public void setLookup(Boolean lookup) { - this.lookup = lookup; - } - - public Boolean getDefaultDateIsCurrent() { - return defaultDateIsCurrent; - } - - public void setDefaultDateIsCurrent(Boolean defaultDateIsCurrent) { - this.defaultDateIsCurrent = defaultDateIsCurrent; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - - public String getTargetScreens() { - return targetScreens; - } - - public void setTargetScreens(String targetScreens) { - this.targetScreens = targetScreens; - } - - public String getCategoryEntityType() { - return categoryEntityType; - } - - public void setCategoryEntityType(String categoryEntityType) { - this.categoryEntityType = categoryEntityType; - } - - public String getWidth() { - return width; - } - - public void setWidth(String width) { - this.width = width; - } - - public Integer getRowsCount() { - return rowsCount; - } - - public void setRowsCount(Integer rowsCount) { - this.rowsCount = rowsCount; - } - - public Boolean getIsCollection() { - return isCollection; - } - - public void setIsCollection(Boolean isCollection) { - this.isCollection = isCollection; - } - - public String getWhereClause() { - return whereClause; - } - - public void setWhereClause(String whereClause) { - this.whereClause = whereClause; - } - - public String getJoinClause() { - return joinClause; - } - - public void setJoinClause(String joinClause) { - this.joinClause = joinClause; - } - - public String getFilterXml() { - return filterXml; - } - - public void setFilterXml(String filterXml) { - this.filterXml = filterXml; - } - - public Set targetScreensSet() { - if (StringUtils.isNotBlank(targetScreens)) { - return new HashSet<>(Arrays.asList(targetScreens.split(","))); - } else { - return Collections.emptySet(); - } - } - - public List getEnumerationOptions() { - Preconditions.checkState(getDataType() == PropertyType.ENUMERATION, "Only enumeration attributes have options"); - String[] values = StringUtils.split(enumeration, ','); - return values != null ? Arrays.asList(values) : Collections.emptyList(); - } - - public String getEntityClass() { - return entityClass; - } - - public void setEntityClass(String entityClass) { - this.entityClass = entityClass; - } - - @Nullable - public Class getJavaClassForEntity(){ - if (StringUtils.isNotBlank(entityClass)) { - return ReflectionHelper.getClass(entityClass); - } else { - return null; - } - } - - public String getLocaleNames() { - return localeNames; - } - - public void setLocaleNames(String localeNames) { - this.localeNames = localeNames; - } - - public String getLocaleName() { - localeName = LocaleHelper.getLocalizedName(localeNames); - if (localeName == null) { - localeName = name; - } - return localeName; - } - - public void setEnumerationLocales(String enumerationLocales) { - this.enumerationLocales = enumerationLocales; - } - - public String getEnumerationLocales() { - return enumerationLocales; - } - - public String getEnumerationLocale() { - enumerationLocale = LocaleHelper.getLocalizedEnumeration(enumeration, enumerationLocales); - if (enumerationLocale == null) { - enumerationLocale = enumeration; - } - return enumerationLocale; - } - - public Map getLocalizedEnumerationMap() { - String enumeration = getEnumeration(); - String[] values = StringUtils.split(enumeration, ','); - Map map = new HashMap<>(); - for (String s : values) { - map.put(LocaleHelper.getEnumLocalizedValue(s, enumerationLocales), s); - } - return map; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.google.common.base.Preconditions; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; +import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; +import com.haulmont.cuba.core.entity.annotation.Listeners; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; +import javax.persistence.*; +import javax.persistence.Entity; +import java.util.*; + +@Entity(name = "sys$CategoryAttribute") +@Table(name = "SYS_CATEGORY_ATTR") +@NamePattern("%s|localeName") +@SystemLevel +@Listeners("report_CategoryAttributeListener") +public class CategoryAttribute extends StandardEntity { + + private static final long serialVersionUID = -6959392628534815752L; + + public static final int NAME_FIELD_LENGTH = 255; + public static final int CODE_FIELD_LENGTH = 50; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "CATEGORY_ID") + private Category category; + + @Column(name = "CATEGORY_ENTITY_TYPE") + private String categoryEntityType; + + @Column(name = "NAME", length = NAME_FIELD_LENGTH, nullable = false) + private String name; + + @Column(name = "CODE", length = CODE_FIELD_LENGTH, nullable = false) + private String code; + + @Column(name = "ENUMERATION") + private String enumeration; + + @Column(name = "DATA_TYPE") + private String dataType; + + @Column(name = "ENTITY_CLASS") + private String entityClass; + + @Embedded + @AttributeOverrides({ + @AttributeOverride(name="entityId", column=@Column(name="DEFAULT_ENTITY_VALUE")), + @AttributeOverride(name="stringEntityId", column=@Column(name="DEFAULT_STR_ENTITY_VALUE")), + @AttributeOverride(name="intEntityId", column=@Column(name="DEFAULT_INT_ENTITY_VALUE")), + @AttributeOverride(name="longEntityId", column=@Column(name="DEFAULT_LONG_ENTITY_VALUE")) + }) + @EmbeddedParameters(nullAllowed = false) + private ReferenceToEntity defaultEntity; + + @Column(name = "ORDER_NO") + private Integer orderNo; + + @Column(name = "SCREEN") + private String screen; + + @Column(name = "REQUIRED") + private Boolean required = false; + + @Column(name = "LOOKUP") + private Boolean lookup = false; + + @Column(name = "TARGET_SCREENS") + private String targetScreens;//comma separated list of screenId#componentId pairs. componentId might be empty + + @Column(name = "DEFAULT_STRING") + private String defaultString; + + @Column(name = "DEFAULT_INT") + private Integer defaultInt; + + @Column(name = "DEFAULT_DOUBLE") + private Double defaultDouble; + + @Column(name = "DEFAULT_BOOLEAN") + private Boolean defaultBoolean; + + @Column(name = "DEFAULT_DATE") + private Date defaultDate; + + @Column(name = "DEFAULT_DATE_IS_CURRENT") + private Boolean defaultDateIsCurrent; + + @Column(name = "WIDTH", length = 20) + private String width; + + @Column(name = "ROWS_COUNT") + private Integer rowsCount; + + @Column(name = "IS_COLLECTION") + private Boolean isCollection = false; + + @Column(name = "WHERE_CLAUSE") + private String whereClause; + + @Column(name = "JOIN_CLAUSE") + private String joinClause; + + @Column(name = "FILTER_XML") + protected String filterXml; + + @Column(name = "LOCALE_NAMES") + protected String localeNames; + + @Column(name = "ENUMERATION_LOCALES") + protected String enumerationLocales; + + @Transient + @MetaProperty(related = {"localeNames", "name"}) + protected String localeName; + + @Transient + @MetaProperty(related = "enumerationLocales") + protected String enumerationLocale; + + @PostConstruct + public void init() { + Metadata metadata = AppBeans.get(Metadata.NAME); + defaultEntity = metadata.create(ReferenceToEntity.class); + } + + public void setCategory(Category entityType) { + this.category = entityType; + } + + public Category getCategory() { + return category; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEnumeration() { + return enumeration; + } + + public void setEnumeration(String e) { + this.enumeration = e; + } + + public PropertyType getDataType() { + if (dataType == null) return null; + + return PropertyType.valueOf(dataType); + } + + public void setDataType(PropertyType dataType) { + this.dataType = dataType != null ? dataType.name() : null; + } + + public Boolean getIsEntity() { + return getDataType() == PropertyType.ENTITY; + } + + public ReferenceToEntity getDefaultEntity() { + return defaultEntity; + } + + public void setDefaultEntity(ReferenceToEntity defaultEntity) { + this.defaultEntity = defaultEntity; + } + + public String getDefaultString() { + return defaultString; + } + + public void setDefaultString(String defaultString) { + this.defaultString = defaultString; + } + + public Integer getDefaultInt() { + return defaultInt; + } + + public void setDefaultInt(Integer defaultInt) { + this.defaultInt = defaultInt; + } + + public Double getDefaultDouble() { + return defaultDouble; + } + + public void setDefaultDouble(Double defaultDouble) { + this.defaultDouble = defaultDouble; + } + + public Boolean getDefaultBoolean() { + return defaultBoolean; + } + + public void setDefaultBoolean(Boolean defaultBoolean) { + this.defaultBoolean = defaultBoolean; + } + + public Date getDefaultDate() { + return defaultDate; + } + + public void setDefaultDate(Date defaultDate) { + this.defaultDate = defaultDate; + } + + public Object getDefaultValue() { + if (dataType != null) { + switch (PropertyType.valueOf(dataType)) { + case INTEGER: return defaultInt; + case DOUBLE: return defaultDouble; + case BOOLEAN: return defaultBoolean; + case DATE: return defaultDate; + case STRING: return defaultString; + case ENUMERATION: return defaultString; + case ENTITY: return getObjectDefaultEntityId(); + default: return null; + } + } + return null; + } + + public void setObjectDefaultEntityId(Object entity) { + defaultEntity.setObjectEntityId(entity); + } + + public Object getObjectDefaultEntityId() { + return defaultEntity.getObjectEntityId(); + } + + public Integer getOrderNo() { + return orderNo; + } + + public void setOrderNo(Integer orderNo) { + this.orderNo = orderNo; + } + + public String getScreen() { + return screen; + } + + public void setScreen(String screen) { + this.screen = screen; + } + + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public Boolean getLookup() { + return lookup; + } + + public void setLookup(Boolean lookup) { + this.lookup = lookup; + } + + public Boolean getDefaultDateIsCurrent() { + return defaultDateIsCurrent; + } + + public void setDefaultDateIsCurrent(Boolean defaultDateIsCurrent) { + this.defaultDateIsCurrent = defaultDateIsCurrent; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getTargetScreens() { + return targetScreens; + } + + public void setTargetScreens(String targetScreens) { + this.targetScreens = targetScreens; + } + + public String getCategoryEntityType() { + return categoryEntityType; + } + + public void setCategoryEntityType(String categoryEntityType) { + this.categoryEntityType = categoryEntityType; + } + + public String getWidth() { + return width; + } + + public void setWidth(String width) { + this.width = width; + } + + public Integer getRowsCount() { + return rowsCount; + } + + public void setRowsCount(Integer rowsCount) { + this.rowsCount = rowsCount; + } + + public Boolean getIsCollection() { + return isCollection; + } + + public void setIsCollection(Boolean isCollection) { + this.isCollection = isCollection; + } + + public String getWhereClause() { + return whereClause; + } + + public void setWhereClause(String whereClause) { + this.whereClause = whereClause; + } + + public String getJoinClause() { + return joinClause; + } + + public void setJoinClause(String joinClause) { + this.joinClause = joinClause; + } + + public String getFilterXml() { + return filterXml; + } + + public void setFilterXml(String filterXml) { + this.filterXml = filterXml; + } + + public Set targetScreensSet() { + if (StringUtils.isNotBlank(targetScreens)) { + return new HashSet<>(Arrays.asList(targetScreens.split(","))); + } else { + return Collections.emptySet(); + } + } + + public List getEnumerationOptions() { + Preconditions.checkState(getDataType() == PropertyType.ENUMERATION, "Only enumeration attributes have options"); + String[] values = StringUtils.split(enumeration, ','); + return values != null ? Arrays.asList(values) : Collections.emptyList(); + } + + public String getEntityClass() { + return entityClass; + } + + public void setEntityClass(String entityClass) { + this.entityClass = entityClass; + } + + @Nullable + public Class getJavaClassForEntity(){ + if (StringUtils.isNotBlank(entityClass)) { + return ReflectionHelper.getClass(entityClass); + } else { + return null; + } + } + + public String getLocaleNames() { + return localeNames; + } + + public void setLocaleNames(String localeNames) { + this.localeNames = localeNames; + } + + public String getLocaleName() { + localeName = LocaleHelper.getLocalizedName(localeNames); + if (localeName == null) { + localeName = name; + } + return localeName; + } + + public void setEnumerationLocales(String enumerationLocales) { + this.enumerationLocales = enumerationLocales; + } + + public String getEnumerationLocales() { + return enumerationLocales; + } + + public String getEnumerationLocale() { + enumerationLocale = LocaleHelper.getLocalizedEnumeration(enumeration, enumerationLocales); + if (enumerationLocale == null) { + enumerationLocale = enumeration; + } + return enumerationLocale; + } + + public Map getLocalizedEnumerationMap() { + String enumeration = getEnumeration(); + String[] values = StringUtils.split(enumeration, ','); + Map map = new HashMap<>(); + for (String s : values) { + map.put(LocaleHelper.getEnumLocalizedValue(s, enumerationLocales), s); + } + return map; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttributeValue.java b/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttributeValue.java index 0ddec24739..2f1cc96f03 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttributeValue.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/CategoryAttributeValue.java @@ -1,267 +1,267 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; -import com.haulmont.cuba.core.entity.annotation.OnDelete; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.*; - -import javax.annotation.PostConstruct; -import javax.persistence.*; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -@javax.persistence.Entity(name = "sys$CategoryAttributeValue") -@Table(name = "SYS_ATTR_VALUE") -@SystemLevel -public class CategoryAttributeValue extends StandardEntity { - - private static final long serialVersionUID = -2861790889151226985L; - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "CATEGORY_ATTR_ID") - private CategoryAttribute categoryAttribute; - - @Column(name = "CODE") - private String code; - - @Column(name = "STRING_VALUE") - private String stringValue; - - @Column(name = "INTEGER_VALUE") - private Integer intValue; - - @Column(name = "DOUBLE_VALUE") - private Double doubleValue; - - @Column(name = "BOOLEAN_VALUE") - private Boolean booleanValue; - - @Column(name = "DATE_VALUE") - private Date dateValue; - - @Embedded - @EmbeddedParameters(nullAllowed = false) - private ReferenceToEntity entity; - - @Embedded - @AttributeOverrides({ - @AttributeOverride(name="entityId", column=@Column(name="ENTITY_VALUE")), - @AttributeOverride(name="stringEntityId", column=@Column(name="STRING_ENTITY_VALUE")), - @AttributeOverride(name="intEntityId", column=@Column(name="INT_ENTITY_VALUE")), - @AttributeOverride(name="longEntityId", column=@Column(name="LONG_ENTITY_VALUE")) - }) - @EmbeddedParameters(nullAllowed = false) - private ReferenceToEntity entityValue; - - @Transient - private BaseGenericIdEntity transientEntityValue; - - @OneToMany(mappedBy = "parent") - @OnDelete(DeletePolicy.CASCADE) - private List childValues; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "PARENT_ID") - private CategoryAttributeValue parent; - - @Transient - private List transientCollectionValue; - - @PostConstruct - public void init() { - Metadata metadata = AppBeans.get(Metadata.NAME); - entity = metadata.create(ReferenceToEntity.class); - entityValue = metadata.create(ReferenceToEntity.class); - } - - public void setCategoryAttribute(CategoryAttribute categoryAttribute) { - this.categoryAttribute = categoryAttribute; - } - - public CategoryAttribute getCategoryAttribute() { - return categoryAttribute; - } - - public ReferenceToEntity getEntity() { - return entity; - } - - public void setEntity(ReferenceToEntity entity) { - this.entity = entity; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public Integer getIntValue() { - return intValue; - } - - public void setIntValue(Integer intValue) { - this.intValue = intValue; - } - - public Double getDoubleValue() { - return doubleValue; - } - - public void setDoubleValue(Double doubleValue) { - this.doubleValue = doubleValue; - } - - public Boolean getBooleanValue() { - return booleanValue; - } - - public void setBooleanValue(Boolean booleanValue) { - this.booleanValue = booleanValue; - } - - public Date getDateValue() { - return dateValue; - } - - public void setDateValue(Date dateValue) { - this.dateValue = dateValue; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - - public ReferenceToEntity getEntityValue() { - return entityValue; - } - - public void setEntityValue(ReferenceToEntity entityValue) { - this.entityValue = entityValue; - } - - public BaseGenericIdEntity getTransientEntityValue() { - return transientEntityValue; - } - - public void setTransientEntityValue(BaseGenericIdEntity transientEntityValue) { - this.transientEntityValue = transientEntityValue; - } - - public List getChildValues() { - return childValues; - } - - public void setChildValues(List childValues) { - this.childValues = childValues; - } - - public CategoryAttributeValue getParent() { - return parent; - } - - public void setParent(CategoryAttributeValue parent) { - this.parent = parent; - } - - public List getTransientCollectionValue() { - return transientCollectionValue; - } - - public void setTransientCollectionValue(List transientCollectionValue) { - this.transientCollectionValue = transientCollectionValue; - } - - //todo eude support enumerations - public void setValue(Object value) { - if (value == null) { - stringValue = null; - intValue = null; - doubleValue = null; - booleanValue = null; - dateValue = null; - entityValue.setObjectEntityId(null); - transientEntityValue = null; - transientCollectionValue = null; - } else if (value instanceof Date) { - setDateValue((Date) value); - } else if (value instanceof Integer) { - setIntValue((Integer) value); - } else if (value instanceof Double) { - setDoubleValue((Double) value); - } else if (value instanceof Boolean) { - setBooleanValue((Boolean) value); - } else if (value instanceof BaseGenericIdEntity) { - ReferenceToEntitySupport referenceToEntitySupport = AppBeans.get(ReferenceToEntitySupport.class); - Object referenceId = referenceToEntitySupport.getReferenceId((BaseGenericIdEntity) value); - entityValue.setObjectEntityId(referenceId); - setTransientEntityValue((BaseGenericIdEntity) value); - } else if (value instanceof String) { - setStringValue((String) value); - } else if (value instanceof List) { - setTransientCollectionValue((List) value); - } else { - throw new IllegalArgumentException("Unsupported value type " + value.getClass()); - } - } - - public Object getValue() { - if (stringValue != null) { - return stringValue; - } else if (intValue != null) { - return intValue; - } else if (doubleValue != null) { - return doubleValue; - } else if (dateValue != null) { - return dateValue; - } else if (booleanValue != null) { - return booleanValue; - } else if (transientEntityValue != null) { - return transientEntityValue; - } if (transientCollectionValue != null) { - return transientCollectionValue; - } - - return null; - } - - public void setObjectEntityId(Object entityId) { - entity.setObjectEntityId(entityId); - } - - public Object getObjectEntityId() { - return entity.getObjectEntityId(); - } - - public void setObjectEntityValueId(Object entityId) { - entityValue.setObjectEntityId(entityId); - } - - public Object getObjectEntityValueId() { - return entityValue.getObjectEntityId(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; +import com.haulmont.cuba.core.entity.annotation.OnDelete; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.*; + +import javax.annotation.PostConstruct; +import javax.persistence.*; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@javax.persistence.Entity(name = "sys$CategoryAttributeValue") +@Table(name = "SYS_ATTR_VALUE") +@SystemLevel +public class CategoryAttributeValue extends StandardEntity { + + private static final long serialVersionUID = -2861790889151226985L; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "CATEGORY_ATTR_ID") + private CategoryAttribute categoryAttribute; + + @Column(name = "CODE") + private String code; + + @Column(name = "STRING_VALUE") + private String stringValue; + + @Column(name = "INTEGER_VALUE") + private Integer intValue; + + @Column(name = "DOUBLE_VALUE") + private Double doubleValue; + + @Column(name = "BOOLEAN_VALUE") + private Boolean booleanValue; + + @Column(name = "DATE_VALUE") + private Date dateValue; + + @Embedded + @EmbeddedParameters(nullAllowed = false) + private ReferenceToEntity entity; + + @Embedded + @AttributeOverrides({ + @AttributeOverride(name="entityId", column=@Column(name="ENTITY_VALUE")), + @AttributeOverride(name="stringEntityId", column=@Column(name="STRING_ENTITY_VALUE")), + @AttributeOverride(name="intEntityId", column=@Column(name="INT_ENTITY_VALUE")), + @AttributeOverride(name="longEntityId", column=@Column(name="LONG_ENTITY_VALUE")) + }) + @EmbeddedParameters(nullAllowed = false) + private ReferenceToEntity entityValue; + + @Transient + private BaseGenericIdEntity transientEntityValue; + + @OneToMany(mappedBy = "parent") + @OnDelete(DeletePolicy.CASCADE) + private List childValues; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "PARENT_ID") + private CategoryAttributeValue parent; + + @Transient + private List transientCollectionValue; + + @PostConstruct + public void init() { + Metadata metadata = AppBeans.get(Metadata.NAME); + entity = metadata.create(ReferenceToEntity.class); + entityValue = metadata.create(ReferenceToEntity.class); + } + + public void setCategoryAttribute(CategoryAttribute categoryAttribute) { + this.categoryAttribute = categoryAttribute; + } + + public CategoryAttribute getCategoryAttribute() { + return categoryAttribute; + } + + public ReferenceToEntity getEntity() { + return entity; + } + + public void setEntity(ReferenceToEntity entity) { + this.entity = entity; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public Integer getIntValue() { + return intValue; + } + + public void setIntValue(Integer intValue) { + this.intValue = intValue; + } + + public Double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(Double doubleValue) { + this.doubleValue = doubleValue; + } + + public Boolean getBooleanValue() { + return booleanValue; + } + + public void setBooleanValue(Boolean booleanValue) { + this.booleanValue = booleanValue; + } + + public Date getDateValue() { + return dateValue; + } + + public void setDateValue(Date dateValue) { + this.dateValue = dateValue; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public ReferenceToEntity getEntityValue() { + return entityValue; + } + + public void setEntityValue(ReferenceToEntity entityValue) { + this.entityValue = entityValue; + } + + public BaseGenericIdEntity getTransientEntityValue() { + return transientEntityValue; + } + + public void setTransientEntityValue(BaseGenericIdEntity transientEntityValue) { + this.transientEntityValue = transientEntityValue; + } + + public List getChildValues() { + return childValues; + } + + public void setChildValues(List childValues) { + this.childValues = childValues; + } + + public CategoryAttributeValue getParent() { + return parent; + } + + public void setParent(CategoryAttributeValue parent) { + this.parent = parent; + } + + public List getTransientCollectionValue() { + return transientCollectionValue; + } + + public void setTransientCollectionValue(List transientCollectionValue) { + this.transientCollectionValue = transientCollectionValue; + } + + //todo eude support enumerations + public void setValue(Object value) { + if (value == null) { + stringValue = null; + intValue = null; + doubleValue = null; + booleanValue = null; + dateValue = null; + entityValue.setObjectEntityId(null); + transientEntityValue = null; + transientCollectionValue = null; + } else if (value instanceof Date) { + setDateValue((Date) value); + } else if (value instanceof Integer) { + setIntValue((Integer) value); + } else if (value instanceof Double) { + setDoubleValue((Double) value); + } else if (value instanceof Boolean) { + setBooleanValue((Boolean) value); + } else if (value instanceof BaseGenericIdEntity) { + ReferenceToEntitySupport referenceToEntitySupport = AppBeans.get(ReferenceToEntitySupport.class); + Object referenceId = referenceToEntitySupport.getReferenceId((BaseGenericIdEntity) value); + entityValue.setObjectEntityId(referenceId); + setTransientEntityValue((BaseGenericIdEntity) value); + } else if (value instanceof String) { + setStringValue((String) value); + } else if (value instanceof List) { + setTransientCollectionValue((List) value); + } else { + throw new IllegalArgumentException("Unsupported value type " + value.getClass()); + } + } + + public Object getValue() { + if (stringValue != null) { + return stringValue; + } else if (intValue != null) { + return intValue; + } else if (doubleValue != null) { + return doubleValue; + } else if (dateValue != null) { + return dateValue; + } else if (booleanValue != null) { + return booleanValue; + } else if (transientEntityValue != null) { + return transientEntityValue; + } if (transientCollectionValue != null) { + return transientCollectionValue; + } + + return null; + } + + public void setObjectEntityId(Object entityId) { + entity.setObjectEntityId(entityId); + } + + public Object getObjectEntityId() { + return entity.getObjectEntityId(); + } + + public void setObjectEntityValueId(Object entityId) { + entityValue.setObjectEntityId(entityId); + } + + public Object getObjectEntityValueId() { + return entityValue.getObjectEntityId(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Config.java b/modules/global/src/com/haulmont/cuba/core/entity/Config.java index 551731f0b7..6fa1a6a1aa 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Config.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Config.java @@ -1,124 +1,124 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import javax.persistence.Version; -import java.util.Date; - -/** - * Entity for working with configuration parameters (see com.haulmont.cuba.core.config.Config).
- * Should not be used in application code. - */ -@Entity(name = "sys$Config") -@Table(name = "SYS_CONFIG") -@SystemLevel -public class Config extends BaseUuidEntity implements Versioned, Creatable, Updatable { - private static final long serialVersionUID = -2103060811330948816L; - - @Version - @Column(name = "VERSION") - private Integer version; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "UPDATE_TS") - private Date updateTs; - - @Column(name = "UPDATED_BY", length = 50) - private String updatedBy; - - @Column(name = "NAME") - private String name; - - @Column(name = "VALUE") - private String value; - - @Override - public Integer getVersion() { - return version; - } - - @Override - public void setVersion(Integer version) { - this.version = version; - } - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - @Override - public Date getUpdateTs() { - return updateTs; - } - - @Override - public void setUpdateTs(Date updateTs) { - this.updateTs = updateTs; - } - - @Override - public String getUpdatedBy() { - return updatedBy; - } - - @Override - public void setUpdatedBy(String updatedBy) { - this.updatedBy = updatedBy; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Version; +import java.util.Date; + +/** + * Entity for working with configuration parameters (see com.haulmont.cuba.core.config.Config).
+ * Should not be used in application code. + */ +@Entity(name = "sys$Config") +@Table(name = "SYS_CONFIG") +@SystemLevel +public class Config extends BaseUuidEntity implements Versioned, Creatable, Updatable { + private static final long serialVersionUID = -2103060811330948816L; + + @Version + @Column(name = "VERSION") + private Integer version; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "UPDATE_TS") + private Date updateTs; + + @Column(name = "UPDATED_BY", length = 50) + private String updatedBy; + + @Column(name = "NAME") + private String name; + + @Column(name = "VALUE") + private String value; + + @Override + public Integer getVersion() { + return version; + } + + @Override + public void setVersion(Integer version) { + this.version = version; + } + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + @Override + public Date getUpdateTs() { + return updateTs; + } + + @Override + public void setUpdateTs(Date updateTs) { + this.updateTs = updateTs; + } + + @Override + public String getUpdatedBy() { + return updatedBy; + } + + @Override + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/EmbeddableEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/EmbeddableEntity.java index 06927b1a9c..9311aefc13 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/EmbeddableEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/EmbeddableEntity.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.impl.AbstractInstance; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; - -import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; - -/** - * Base class for persistent embeddable entities. - * - */ -@MappedSuperclass -@com.haulmont.chile.core.annotations.MetaClass(name = "sys$EmbeddableEntity") -public abstract class EmbeddableEntity extends AbstractInstance implements Entity { - - private static final long serialVersionUID = 266201862280559076L; - - @Transient - protected SecurityState __securityState; - - @Override - public Object getId() { - return this; - } - - @Override - public MetaClass getMetaClass() { - Metadata metadata = AppBeans.get(Metadata.NAME); - return metadata.getSession().getClassNN(getClass()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.impl.AbstractInstance; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; + +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; + +/** + * Base class for persistent embeddable entities. + * + */ +@MappedSuperclass +@com.haulmont.chile.core.annotations.MetaClass(name = "sys$EmbeddableEntity") +public abstract class EmbeddableEntity extends AbstractInstance implements Entity { + + private static final long serialVersionUID = 266201862280559076L; + + @Transient + protected SecurityState __securityState; + + @Override + public Object getId() { + return this; + } + + @Override + public MetaClass getMetaClass() { + Metadata metadata = AppBeans.get(Metadata.NAME); + return metadata.getSession().getClassNN(getClass()); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Entity.java b/modules/global/src/com/haulmont/cuba/core/entity/Entity.java index 8bfd113c5d..e1e0be5553 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Entity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Entity.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.model.Instance; - -/** - * Interface to be implemented by domain model objects with identifiers. - * @param identifier type - * - */ -public interface Entity extends Instance { - T getId(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.model.Instance; + +/** + * Interface to be implemented by domain model objects with identifiers. + * @param identifier type + * + */ +public interface Entity extends Instance { + T getId(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/EntitySnapshot.java b/modules/global/src/com/haulmont/cuba/core/entity/EntitySnapshot.java index d1fc9261f6..5ffb88d795 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/EntitySnapshot.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/EntitySnapshot.java @@ -1,171 +1,171 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.PostConstruct; -import javax.persistence.*; -import javax.persistence.Entity; -import java.util.Date; - -/** - * Snapshot for entity. - */ -@Entity(name = "sys$EntitySnapshot") -@Table(name = "SYS_ENTITY_SNAPSHOT") -@SystemLevel -public class EntitySnapshot extends BaseUuidEntity implements Creatable { - - private static final long serialVersionUID = 4835363127711391591L; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "VIEW_XML") - private String viewXml; - - @Column(name = "SNAPSHOT_XML") - private String snapshotXml; - - @Column(name = "ENTITY_META_CLASS") - private String entityMetaClass; - - @Column(name = "SNAPSHOT_DATE", nullable = false) - private Date snapshotDate; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "AUTHOR_ID") - private User author; - - @Embedded - @EmbeddedParameters(nullAllowed = false) - private ReferenceToEntity entity; - - @PostConstruct - public void init() { - Metadata metadata = AppBeans.get(Metadata.NAME); - entity = metadata.create(ReferenceToEntity.class); - } - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - public String getViewXml() { - return viewXml; - } - - public void setViewXml(String viewXml) { - this.viewXml = viewXml; - } - - public String getSnapshotXml() { - return snapshotXml; - } - - public void setSnapshotXml(String snapshotXml) { - this.snapshotXml = snapshotXml; - } - - public String getEntityMetaClass() { - return entityMetaClass; - } - - public void setEntityMetaClass(String entityMetaClass) { - this.entityMetaClass = entityMetaClass; - } - - public void setAuthor(User author) { - this.author = author; - } - - public User getAuthor() { - return author; - } - - @MetaProperty(related = {"snapshotDate,author"}) - public String getLabel() { - String name = ""; - if (author != null && StringUtils.isNotEmpty(this.author.getCaption())) { - name += this.author.getCaption() + " "; - } - - Datatype datatype = Datatypes.getNN(Date.class); - - UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - if (userSessionSource != null && userSessionSource.checkCurrentUserSession()) { - name += datatype.format(snapshotDate, userSessionSource.getLocale()); - } - - return StringUtils.trim(name); - } - - @MetaProperty(related = "snapshotDate") - public Date getChangeDate() { - return this.snapshotDate; - } - - public Date getSnapshotDate() { - return snapshotDate; - } - - public void setSnapshotDate(Date snapshotDate) { - this.snapshotDate = snapshotDate; - } - - public ReferenceToEntity getEntity() { - return entity; - } - - public void setEntity(ReferenceToEntity entity) { - this.entity = entity; - } - - public void setObjectEntityId(Object entityId) { - entity.setObjectEntityId(entityId); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.PostConstruct; +import javax.persistence.*; +import javax.persistence.Entity; +import java.util.Date; + +/** + * Snapshot for entity. + */ +@Entity(name = "sys$EntitySnapshot") +@Table(name = "SYS_ENTITY_SNAPSHOT") +@SystemLevel +public class EntitySnapshot extends BaseUuidEntity implements Creatable { + + private static final long serialVersionUID = 4835363127711391591L; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "VIEW_XML") + private String viewXml; + + @Column(name = "SNAPSHOT_XML") + private String snapshotXml; + + @Column(name = "ENTITY_META_CLASS") + private String entityMetaClass; + + @Column(name = "SNAPSHOT_DATE", nullable = false) + private Date snapshotDate; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "AUTHOR_ID") + private User author; + + @Embedded + @EmbeddedParameters(nullAllowed = false) + private ReferenceToEntity entity; + + @PostConstruct + public void init() { + Metadata metadata = AppBeans.get(Metadata.NAME); + entity = metadata.create(ReferenceToEntity.class); + } + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public String getViewXml() { + return viewXml; + } + + public void setViewXml(String viewXml) { + this.viewXml = viewXml; + } + + public String getSnapshotXml() { + return snapshotXml; + } + + public void setSnapshotXml(String snapshotXml) { + this.snapshotXml = snapshotXml; + } + + public String getEntityMetaClass() { + return entityMetaClass; + } + + public void setEntityMetaClass(String entityMetaClass) { + this.entityMetaClass = entityMetaClass; + } + + public void setAuthor(User author) { + this.author = author; + } + + public User getAuthor() { + return author; + } + + @MetaProperty(related = {"snapshotDate,author"}) + public String getLabel() { + String name = ""; + if (author != null && StringUtils.isNotEmpty(this.author.getCaption())) { + name += this.author.getCaption() + " "; + } + + Datatype datatype = Datatypes.getNN(Date.class); + + UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + if (userSessionSource != null && userSessionSource.checkCurrentUserSession()) { + name += datatype.format(snapshotDate, userSessionSource.getLocale()); + } + + return StringUtils.trim(name); + } + + @MetaProperty(related = "snapshotDate") + public Date getChangeDate() { + return this.snapshotDate; + } + + public Date getSnapshotDate() { + return snapshotDate; + } + + public void setSnapshotDate(Date snapshotDate) { + this.snapshotDate = snapshotDate; + } + + public ReferenceToEntity getEntity() { + return entity; + } + + public void setEntity(ReferenceToEntity entity) { + this.entity = entity; + } + + public void setObjectEntityId(Object entityId) { + entity.setObjectEntityId(entityId); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/EntityStatistics.java b/modules/global/src/com/haulmont/cuba/core/entity/EntityStatistics.java index fa5357177e..b300d69ac5 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/EntityStatistics.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/EntityStatistics.java @@ -1,162 +1,162 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import java.util.Date; - -@Entity(name = "sys$EntityStatistics") -@Table(name = "SYS_ENTITY_STATISTICS") -@SystemLevel -public class EntityStatistics extends BaseUuidEntity implements Creatable, Updatable { - - private static final long serialVersionUID = -1734840995849860033L; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "UPDATE_TS") - private Date updateTs; - - @Column(name = "UPDATED_BY", length = 50) - private String updatedBy; - - @Column(name = "NAME", length = 50) - private String name; - - @Column(name = "INSTANCE_COUNT") - private Long instanceCount; - - @Column(name = "FETCH_UI") - private Integer fetchUI; - - @Column(name = "MAX_FETCH_UI") - private Integer maxFetchUI; - - @Column(name = "LAZY_COLLECTION_THRESHOLD") - private Integer lazyCollectionThreshold; - - @Column(name = "LOOKUP_SCREEN_THRESHOLD") - private Integer lookupScreenThreshold; - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - @Override - public String getUpdatedBy() { - return updatedBy; - } - - @Override - public void setUpdatedBy(String updatedBy) { - this.updatedBy = updatedBy; - } - - @Override - public Date getUpdateTs() { - return updateTs; - } - - @Override - public void setUpdateTs(Date updateTs) { - this.updateTs = updateTs; - } - - public Long getInstanceCount() { - return instanceCount; - } - - public void setInstanceCount(Long instanceCount) { - this.instanceCount = instanceCount; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getFetchUI() { - return fetchUI; - } - - public void setFetchUI(Integer fetchUI) { - this.fetchUI = fetchUI; - } - - public Integer getMaxFetchUI() { - return maxFetchUI; - } - - public void setMaxFetchUI(Integer maxFetchUI) { - this.maxFetchUI = maxFetchUI; - } - - public Integer getLazyCollectionThreshold() { - return lazyCollectionThreshold; - } - - public void setLazyCollectionThreshold(Integer lazyCollectionThreshold) { - this.lazyCollectionThreshold = lazyCollectionThreshold; - } - - public Integer getLookupScreenThreshold() { - return lookupScreenThreshold; - } - - public void setLookupScreenThreshold(Integer lookupScreenThreshold) { - this.lookupScreenThreshold = lookupScreenThreshold; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(StringUtils.trimToEmpty(name)); - sb.append(": instanceCount=").append(instanceCount != null ? instanceCount : 0); - if (lazyCollectionThreshold != null) - sb.append(", lazyCollectionThreshold=").append(lazyCollectionThreshold); - if (maxFetchUI != null) - sb.append(", maxFetchUI=").append(maxFetchUI); - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; + +@Entity(name = "sys$EntityStatistics") +@Table(name = "SYS_ENTITY_STATISTICS") +@SystemLevel +public class EntityStatistics extends BaseUuidEntity implements Creatable, Updatable { + + private static final long serialVersionUID = -1734840995849860033L; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "UPDATE_TS") + private Date updateTs; + + @Column(name = "UPDATED_BY", length = 50) + private String updatedBy; + + @Column(name = "NAME", length = 50) + private String name; + + @Column(name = "INSTANCE_COUNT") + private Long instanceCount; + + @Column(name = "FETCH_UI") + private Integer fetchUI; + + @Column(name = "MAX_FETCH_UI") + private Integer maxFetchUI; + + @Column(name = "LAZY_COLLECTION_THRESHOLD") + private Integer lazyCollectionThreshold; + + @Column(name = "LOOKUP_SCREEN_THRESHOLD") + private Integer lookupScreenThreshold; + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + @Override + public String getUpdatedBy() { + return updatedBy; + } + + @Override + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + @Override + public Date getUpdateTs() { + return updateTs; + } + + @Override + public void setUpdateTs(Date updateTs) { + this.updateTs = updateTs; + } + + public Long getInstanceCount() { + return instanceCount; + } + + public void setInstanceCount(Long instanceCount) { + this.instanceCount = instanceCount; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getFetchUI() { + return fetchUI; + } + + public void setFetchUI(Integer fetchUI) { + this.fetchUI = fetchUI; + } + + public Integer getMaxFetchUI() { + return maxFetchUI; + } + + public void setMaxFetchUI(Integer maxFetchUI) { + this.maxFetchUI = maxFetchUI; + } + + public Integer getLazyCollectionThreshold() { + return lazyCollectionThreshold; + } + + public void setLazyCollectionThreshold(Integer lazyCollectionThreshold) { + this.lazyCollectionThreshold = lazyCollectionThreshold; + } + + public Integer getLookupScreenThreshold() { + return lookupScreenThreshold; + } + + public void setLookupScreenThreshold(Integer lookupScreenThreshold) { + this.lookupScreenThreshold = lookupScreenThreshold; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(StringUtils.trimToEmpty(name)); + sb.append(": instanceCount=").append(instanceCount != null ? instanceCount : 0); + if (lazyCollectionThreshold != null) + sb.append(", lazyCollectionThreshold=").append(lazyCollectionThreshold); + if (maxFetchUI != null) + sb.append(", maxFetchUI=").append(maxFetchUI); + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/FileDescriptor.java b/modules/global/src/com/haulmont/cuba/core/entity/FileDescriptor.java index ec52b22d3a..3aa741466c 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/FileDescriptor.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/FileDescriptor.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.UuidProvider; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.Column; -import javax.persistence.Table; -import java.util.Date; - -@javax.persistence.Entity(name = "sys$FileDescriptor") -@Table(name = "SYS_FILE") -@NamePattern("%s (%s)|name,createDate,extension") -@SystemLevel -public class FileDescriptor extends StandardEntity { - - private static final long serialVersionUID = 564683944299730504L; - - @Column(name = "NAME", length = 500, nullable = false) - private String name; - - @Column(name = "EXT", length = 20) - private String extension; - - @Column(name = "FILE_SIZE") - private Long size; - - @Column(name = "CREATE_DATE") - private Date createDate; - - /** - * @return file uploading timestamp - */ - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - /** - * @return file name including extension - */ - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - /** - * @return file extension, i.e. the part of name after the last dot - */ - public String getExtension() { - return extension; - } - - public void setExtension(String extension) { - this.extension = StringUtils.substring(extension, 0, 20); - } - - /** - * @return file size in bytes - */ - public Long getSize() { - return size; - } - - public void setSize(Long size) { - this.size = size; - } - - /** - * Used by the framework to transfer file between application tiers. - */ - public String toUrlParam() { - StringBuilder strBuilder = new StringBuilder() - .append(id).append(",") - .append(extension).append(",") - .append(createDate.getTime()); - if (size != null) { - strBuilder.append(",").append(size); - } - return strBuilder.toString(); - } - - /** - * Used by the framework to transfer file between application tiers. - */ - public static FileDescriptor fromUrlParam(String urlParam) { - String[] parts = urlParam.split(","); - if (parts.length != 3 && parts.length != 4) { - throw new IllegalArgumentException("Invalid FileDescriptor format"); - } - Metadata metadata = AppBeans.get(Metadata.NAME); - FileDescriptor fd = metadata.create(FileDescriptor.class); - fd.setId(UuidProvider.fromString(parts[0])); - fd.setExtension(parts[1]); - fd.setCreateDate(new Date(Long.parseLong(parts[2]))); - if (parts.length == 4) { - fd.setSize(Long.parseLong(parts[3])); - } - return fd; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.UuidProvider; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.Column; +import javax.persistence.Table; +import java.util.Date; + +@javax.persistence.Entity(name = "sys$FileDescriptor") +@Table(name = "SYS_FILE") +@NamePattern("%s (%s)|name,createDate,extension") +@SystemLevel +public class FileDescriptor extends StandardEntity { + + private static final long serialVersionUID = 564683944299730504L; + + @Column(name = "NAME", length = 500, nullable = false) + private String name; + + @Column(name = "EXT", length = 20) + private String extension; + + @Column(name = "FILE_SIZE") + private Long size; + + @Column(name = "CREATE_DATE") + private Date createDate; + + /** + * @return file uploading timestamp + */ + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + /** + * @return file name including extension + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * @return file extension, i.e. the part of name after the last dot + */ + public String getExtension() { + return extension; + } + + public void setExtension(String extension) { + this.extension = StringUtils.substring(extension, 0, 20); + } + + /** + * @return file size in bytes + */ + public Long getSize() { + return size; + } + + public void setSize(Long size) { + this.size = size; + } + + /** + * Used by the framework to transfer file between application tiers. + */ + public String toUrlParam() { + StringBuilder strBuilder = new StringBuilder() + .append(id).append(",") + .append(extension).append(",") + .append(createDate.getTime()); + if (size != null) { + strBuilder.append(",").append(size); + } + return strBuilder.toString(); + } + + /** + * Used by the framework to transfer file between application tiers. + */ + public static FileDescriptor fromUrlParam(String urlParam) { + String[] parts = urlParam.split(","); + if (parts.length != 3 && parts.length != 4) { + throw new IllegalArgumentException("Invalid FileDescriptor format"); + } + Metadata metadata = AppBeans.get(Metadata.NAME); + FileDescriptor fd = metadata.create(FileDescriptor.class); + fd.setId(UuidProvider.fromString(parts[0])); + fd.setExtension(parts[1]); + fd.setCreateDate(new Date(Long.parseLong(parts[2]))); + if (parts.length == 4) { + fd.setSize(Long.parseLong(parts[3])); + } + return fd; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Folder.java b/modules/global/src/com/haulmont/cuba/core/entity/Folder.java index f4dc4ed404..600e839f69 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Folder.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Folder.java @@ -1,95 +1,95 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.EnableRestore; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import javax.persistence.Entity; - -@Entity(name = "sys$Folder") -@Table(name = "SYS_FOLDER") -@Inheritance(strategy = InheritanceType.JOINED) -@DiscriminatorColumn(name = "FOLDER_TYPE", discriminatorType = DiscriminatorType.STRING) -@DiscriminatorValue("F") -@SystemLevel -@EnableRestore(false) -public class Folder extends StandardEntity { - - private static final long serialVersionUID = -2038652558181851215L; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "PARENT_ID") - protected Folder parent; - - @Column(name = "NAME", length = 100) - protected String name; - - @Column(name = "SORT_ORDER") - protected Integer sortOrder; - - @Transient - protected String itemStyle = null; - - @Column(name = "TAB_NAME") - protected String tabName; - - public Folder getParent() { - return parent; - } - - public void setParent(Folder parent) { - this.parent = parent; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCaption() { - return name; - } - - public Integer getSortOrder() { - return sortOrder; - } - - public void setSortOrder(Integer sortOrder) { - this.sortOrder = sortOrder; - } - - public String getItemStyle() { - return itemStyle; - } - - public void setItemStyle(String itemStyle) { - this.itemStyle = itemStyle; - } - - public String getTabName() { - return tabName; - } - - public void setTabName(String tabName) { - this.tabName = tabName; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.EnableRestore; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import javax.persistence.Entity; + +@Entity(name = "sys$Folder") +@Table(name = "SYS_FOLDER") +@Inheritance(strategy = InheritanceType.JOINED) +@DiscriminatorColumn(name = "FOLDER_TYPE", discriminatorType = DiscriminatorType.STRING) +@DiscriminatorValue("F") +@SystemLevel +@EnableRestore(false) +public class Folder extends StandardEntity { + + private static final long serialVersionUID = -2038652558181851215L; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "PARENT_ID") + protected Folder parent; + + @Column(name = "NAME", length = 100) + protected String name; + + @Column(name = "SORT_ORDER") + protected Integer sortOrder; + + @Transient + protected String itemStyle = null; + + @Column(name = "TAB_NAME") + protected String tabName; + + public Folder getParent() { + return parent; + } + + public void setParent(Folder parent) { + this.parent = parent; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCaption() { + return name; + } + + public Integer getSortOrder() { + return sortOrder; + } + + public void setSortOrder(Integer sortOrder) { + this.sortOrder = sortOrder; + } + + public String getItemStyle() { + return itemStyle; + } + + public void setItemStyle(String itemStyle) { + this.itemStyle = itemStyle; + } + + public String getTabName() { + return tabName; + } + + public void setTabName(String tabName) { + this.tabName = tabName; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/FtsChangeType.java b/modules/global/src/com/haulmont/cuba/core/entity/FtsChangeType.java index 77c67be6b5..7a81ae72f2 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/FtsChangeType.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/FtsChangeType.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; - -public enum FtsChangeType implements EnumClass { - INSERT("I"), - UPDATE("U"), - DELETE("D"); - - private final String id; - - FtsChangeType(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - public static FtsChangeType fromId(String id) { - if ("I".equals(id)) - return INSERT; - else if ("U".equals(id)) - return UPDATE; - else if ("D".equals(id)) - return DELETE; - else - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; + +public enum FtsChangeType implements EnumClass { + INSERT("I"), + UPDATE("U"), + DELETE("D"); + + private final String id; + + FtsChangeType(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + public static FtsChangeType fromId(String id) { + if ("I".equals(id)) + return INSERT; + else if ("U".equals(id)) + return UPDATE; + else if ("D".equals(id)) + return DELETE; + else + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/FtsQueue.java b/modules/global/src/com/haulmont/cuba/core/entity/FtsQueue.java index 62eaf4544a..6810107b3f 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/FtsQueue.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/FtsQueue.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import java.util.Date; -import java.util.UUID; - -@Entity(name = "sys$FtsQueue") -@Table(name = "SYS_FTS_QUEUE") -@SystemLevel -public class FtsQueue extends BaseUuidEntity implements Creatable { - - private static final long serialVersionUID = 6488459370269702942L; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "ENTITY_ID") - protected UUID entityId; - - @Column(name = "STRING_ENTITY_ID", length = 255) - protected String stringEntityId; - - @Column(name = "INT_ENTITY_ID") - protected Integer intEntityId; - - @Column(name = "LONG_ENTITY_ID") - protected Long longEntityId; - - @Column(name = "ENTITY_NAME") - protected String entityName; - - @Column(name = "CHANGE_TYPE") - protected String changeType; - - @Column(name = "SOURCE_HOST") - protected String sourceHost; - - @Column(name = "INDEXING_HOST") - protected String indexingHost; - - @Column(name = "FAKE") - protected Boolean fake = false; - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - public UUID getEntityId() { - return entityId; - } - - public void setEntityId(UUID entityId) { - this.entityId = entityId; - } - - public String getStringEntityId() { - return stringEntityId; - } - - public void setStringEntityId(String stringEntityId) { - this.stringEntityId = stringEntityId; - } - - public Integer getIntEntityId() { - return intEntityId; - } - - public void setIntEntityId(Integer intEntityId) { - this.intEntityId = intEntityId; - } - - public Long getLongEntityId() { - return longEntityId; - } - - public void setLongEntityId(Long longEntityId) { - this.longEntityId = longEntityId; - } - - public Object getObjectEntityId() { - if (entityId != null) { - return entityId; - } else if (longEntityId != null) { - return longEntityId; - } else if (intEntityId != null) { - return intEntityId; - } else if (stringEntityId != null) { - return stringEntityId; - } else { - return null; - } - } - - public void setObjectEntityId(Object objectEntityId) { - if (objectEntityId instanceof UUID) { - setEntityId((UUID) objectEntityId); - } else if (objectEntityId instanceof Long) { - setLongEntityId((Long) objectEntityId); - } else if (objectEntityId instanceof Integer) { - setIntEntityId((Integer) objectEntityId); - } else if (objectEntityId instanceof String) { - setStringEntityId((String) objectEntityId); - } else if (objectEntityId instanceof IdProxy) { - Number realId = ((IdProxy) objectEntityId).getNN(); - if (realId instanceof Long) { - setLongEntityId((Long) realId); - } else { - setIntEntityId((Integer) realId); - } - } - else if (objectEntityId == null) { - setEntityId(null); - setLongEntityId(null); - setIntEntityId(null); - setLongEntityId(null); - } else { - throw new IllegalArgumentException( - String.format("Unsupported primary key type: %s", objectEntityId.getClass().getSimpleName())); - } - } - - public String getEntityName() { - return entityName; - } - - public void setEntityName(String entityName) { - this.entityName = entityName; - } - - public FtsChangeType getChangeType() { - return FtsChangeType.fromId(changeType); - } - - public void setChangeType(FtsChangeType changeType) { - this.changeType = changeType.getId(); - } - - public String getSourceHost() { - return sourceHost; - } - - public void setSourceHost(String sourceHost) { - this.sourceHost = sourceHost; - } - - public String getIndexingHost() { - return indexingHost; - } - - public void setIndexingHost(String indexingHost) { - this.indexingHost = indexingHost; - } - - public Boolean getFake() { - return fake; - } - - public void setFake(Boolean fake) { - this.fake = fake; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; +import java.util.UUID; + +@Entity(name = "sys$FtsQueue") +@Table(name = "SYS_FTS_QUEUE") +@SystemLevel +public class FtsQueue extends BaseUuidEntity implements Creatable { + + private static final long serialVersionUID = 6488459370269702942L; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "ENTITY_ID") + protected UUID entityId; + + @Column(name = "STRING_ENTITY_ID", length = 255) + protected String stringEntityId; + + @Column(name = "INT_ENTITY_ID") + protected Integer intEntityId; + + @Column(name = "LONG_ENTITY_ID") + protected Long longEntityId; + + @Column(name = "ENTITY_NAME") + protected String entityName; + + @Column(name = "CHANGE_TYPE") + protected String changeType; + + @Column(name = "SOURCE_HOST") + protected String sourceHost; + + @Column(name = "INDEXING_HOST") + protected String indexingHost; + + @Column(name = "FAKE") + protected Boolean fake = false; + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public UUID getEntityId() { + return entityId; + } + + public void setEntityId(UUID entityId) { + this.entityId = entityId; + } + + public String getStringEntityId() { + return stringEntityId; + } + + public void setStringEntityId(String stringEntityId) { + this.stringEntityId = stringEntityId; + } + + public Integer getIntEntityId() { + return intEntityId; + } + + public void setIntEntityId(Integer intEntityId) { + this.intEntityId = intEntityId; + } + + public Long getLongEntityId() { + return longEntityId; + } + + public void setLongEntityId(Long longEntityId) { + this.longEntityId = longEntityId; + } + + public Object getObjectEntityId() { + if (entityId != null) { + return entityId; + } else if (longEntityId != null) { + return longEntityId; + } else if (intEntityId != null) { + return intEntityId; + } else if (stringEntityId != null) { + return stringEntityId; + } else { + return null; + } + } + + public void setObjectEntityId(Object objectEntityId) { + if (objectEntityId instanceof UUID) { + setEntityId((UUID) objectEntityId); + } else if (objectEntityId instanceof Long) { + setLongEntityId((Long) objectEntityId); + } else if (objectEntityId instanceof Integer) { + setIntEntityId((Integer) objectEntityId); + } else if (objectEntityId instanceof String) { + setStringEntityId((String) objectEntityId); + } else if (objectEntityId instanceof IdProxy) { + Number realId = ((IdProxy) objectEntityId).getNN(); + if (realId instanceof Long) { + setLongEntityId((Long) realId); + } else { + setIntEntityId((Integer) realId); + } + } + else if (objectEntityId == null) { + setEntityId(null); + setLongEntityId(null); + setIntEntityId(null); + setLongEntityId(null); + } else { + throw new IllegalArgumentException( + String.format("Unsupported primary key type: %s", objectEntityId.getClass().getSimpleName())); + } + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public FtsChangeType getChangeType() { + return FtsChangeType.fromId(changeType); + } + + public void setChangeType(FtsChangeType changeType) { + this.changeType = changeType.getId(); + } + + public String getSourceHost() { + return sourceHost; + } + + public void setSourceHost(String sourceHost) { + this.sourceHost = sourceHost; + } + + public String getIndexingHost() { + return indexingHost; + } + + public void setIndexingHost(String indexingHost) { + this.indexingHost = indexingHost; + } + + public Boolean getFake() { + return fake; + } + + public void setFake(Boolean fake) { + this.fake = fake; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/JmxInstance.java b/modules/global/src/com/haulmont/cuba/core/entity/JmxInstance.java index 69628003a0..c19c7c827e 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/JmxInstance.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/JmxInstance.java @@ -1,95 +1,95 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; - -@Entity(name = "sys$JmxInstance") -@Table(name = "SYS_JMX_INSTANCE") -@NamePattern("#getCaption|nodeName,address") -@SystemLevel -public class JmxInstance extends StandardEntity { - - @Column(name = "NODE_NAME", length = 255) - protected String nodeName; - - @Column(name = "ADDRESS", length = 500, nullable = false) - protected String address; - - @Column(name = "LOGIN", length = 50, nullable = false) - protected String login; - - @Column(name = "PASSWORD", length = 255) - protected String password; - - public JmxInstance() { - } - - public JmxInstance(String nodeName) { - this.nodeName = nodeName; - } - - public String getNodeName() { - return nodeName; - } - - public void setNodeName(String nodeName) { - this.nodeName = nodeName; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getCaption() { - StringBuilder sb = new StringBuilder(); - if (StringUtils.isNotEmpty(nodeName)) - sb.append(nodeName); - - if (StringUtils.isNotEmpty(address)) - sb.append(" (").append(address).append(")"); - - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity(name = "sys$JmxInstance") +@Table(name = "SYS_JMX_INSTANCE") +@NamePattern("#getCaption|nodeName,address") +@SystemLevel +public class JmxInstance extends StandardEntity { + + @Column(name = "NODE_NAME", length = 255) + protected String nodeName; + + @Column(name = "ADDRESS", length = 500, nullable = false) + protected String address; + + @Column(name = "LOGIN", length = 50, nullable = false) + protected String login; + + @Column(name = "PASSWORD", length = 255) + protected String password; + + public JmxInstance() { + } + + public JmxInstance(String nodeName) { + this.nodeName = nodeName; + } + + public String getNodeName() { + return nodeName; + } + + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getCaption() { + StringBuilder sb = new StringBuilder(); + if (StringUtils.isNotEmpty(nodeName)) + sb.append(nodeName); + + if (StringUtils.isNotEmpty(address)) + sb.append(" (").append(address).append(")"); + + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/LockDescriptor.java b/modules/global/src/com/haulmont/cuba/core/entity/LockDescriptor.java index 5232f3b8d8..b34d41e2ef 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/LockDescriptor.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/LockDescriptor.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.Column; -import javax.persistence.Table; - -@javax.persistence.Entity(name = "sys$LockDescriptor") -@Table(name = "SYS_LOCK_CONFIG") -@SystemLevel -public class LockDescriptor extends BaseUuidEntity { - - private static final long serialVersionUID = -5798715368435824090L; - - @Column(name = "NAME", length = 100, nullable = false) - private String name; - - @Column(name = "TIMEOUT_SEC", nullable = false) - private Integer timeoutSec; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getTimeoutSec() { - return timeoutSec; - } - - public void setTimeoutSec(Integer timeoutSec) { - this.timeoutSec = timeoutSec; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.Column; +import javax.persistence.Table; + +@javax.persistence.Entity(name = "sys$LockDescriptor") +@Table(name = "SYS_LOCK_CONFIG") +@SystemLevel +public class LockDescriptor extends BaseUuidEntity { + + private static final long serialVersionUID = -5798715368435824090L; + + @Column(name = "NAME", length = 100, nullable = false) + private String name; + + @Column(name = "TIMEOUT_SEC", nullable = false) + private Integer timeoutSec; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getTimeoutSec() { + return timeoutSec; + } + + public void setTimeoutSec(Integer timeoutSec) { + this.timeoutSec = timeoutSec; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/ScheduledTaskDefinedBy.java b/modules/global/src/com/haulmont/cuba/core/entity/ScheduledTaskDefinedBy.java index bda6bd7fd9..bdb6fa4bb4 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/ScheduledTaskDefinedBy.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/ScheduledTaskDefinedBy.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; - -public enum ScheduledTaskDefinedBy implements EnumClass { - BEAN("B"), - CLASS("C"), - SCRIPT("S"); - - private final String id; - - ScheduledTaskDefinedBy(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - public static String getId(ScheduledTaskDefinedBy scheduledTask) { - return scheduledTask != null ? scheduledTask.getId() : null; - } - - public static ScheduledTaskDefinedBy fromId(String id) { - for (ScheduledTaskDefinedBy currentTask : values()) { - if (currentTask.getId().equals(id)) { - return currentTask; - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; + +public enum ScheduledTaskDefinedBy implements EnumClass { + BEAN("B"), + CLASS("C"), + SCRIPT("S"); + + private final String id; + + ScheduledTaskDefinedBy(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + public static String getId(ScheduledTaskDefinedBy scheduledTask) { + return scheduledTask != null ? scheduledTask.getId() : null; + } + + public static ScheduledTaskDefinedBy fromId(String id) { + for (ScheduledTaskDefinedBy currentTask : values()) { + if (currentTask.getId().equals(id)) { + return currentTask; + } + } + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/SchedulingType.java b/modules/global/src/com/haulmont/cuba/core/entity/SchedulingType.java index 33f16ed976..782844a5d2 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/SchedulingType.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/SchedulingType.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; - -public enum SchedulingType implements EnumClass { - CRON("C"), - PERIOD("P"), - FIXED_DELAY("D"); - - private final String id; - - SchedulingType(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - public static String getId(SchedulingType schedulingType) { - return schedulingType != null ? schedulingType.getId() : null; - } - - public static SchedulingType fromId(String id) { - for (SchedulingType schedulingType : values()) { - if (schedulingType.getId().equals(id)) { - return schedulingType; - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; + +public enum SchedulingType implements EnumClass { + CRON("C"), + PERIOD("P"), + FIXED_DELAY("D"); + + private final String id; + + SchedulingType(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + public static String getId(SchedulingType schedulingType) { + return schedulingType != null ? schedulingType.getId() : null; + } + + public static SchedulingType fromId(String id) { + for (SchedulingType schedulingType : values()) { + if (schedulingType.getId().equals(id)) { + return schedulingType; + } + } + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/SendingAttachment.java b/modules/global/src/com/haulmont/cuba/core/entity/SendingAttachment.java index 3454b96321..ee99e82fc6 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/SendingAttachment.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/SendingAttachment.java @@ -1,113 +1,113 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import javax.persistence.Entity; - -@Entity(name = "sys$SendingAttachment") -@Table(name = "SYS_SENDING_ATTACHMENT") -@SystemLevel -public class SendingAttachment extends StandardEntity { - private static final long serialVersionUID = -8253918579521701435L; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "MESSAGE_ID") - protected SendingMessage message; - - /** - * Attachment data is stored either in this field or in {@link #contentFile}. - */ - @Basic(fetch = FetchType.LAZY) - @Column(name = "CONTENT") - protected byte[] content; - - @JoinColumn(name = "CONTENT_FILE_ID") - @OneToOne(fetch = FetchType.LAZY) - protected FileDescriptor contentFile; - - @Column(name = "NAME", length = 500) - protected String name; - - @Column(name = "CONTENT_ID", length = 50) - protected String contentId; - - @Column(name = "DISPOSITION", length = 50) - protected String disposition; - - @Column(name = "TEXT_ENCODING", length = 50) - protected String encoding; - - public SendingMessage getMessage() { - return message; - } - - public void setMessage(SendingMessage message) { - this.message = message; - } - - public byte[] getContent() { - return content; - } - - public void setContent(byte[] content) { - this.content = content; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getContentId() { - return contentId; - } - - public void setContentId(String contentId) { - this.contentId = contentId; - } - - public String getDisposition() { - return disposition; - } - - public void setDisposition(String disposition) { - this.disposition = disposition; - } - - public String getEncoding() { - return encoding; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public FileDescriptor getContentFile() { - return contentFile; - } - - public void setContentFile(FileDescriptor contentFile) { - this.contentFile = contentFile; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import javax.persistence.Entity; + +@Entity(name = "sys$SendingAttachment") +@Table(name = "SYS_SENDING_ATTACHMENT") +@SystemLevel +public class SendingAttachment extends StandardEntity { + private static final long serialVersionUID = -8253918579521701435L; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "MESSAGE_ID") + protected SendingMessage message; + + /** + * Attachment data is stored either in this field or in {@link #contentFile}. + */ + @Basic(fetch = FetchType.LAZY) + @Column(name = "CONTENT") + protected byte[] content; + + @JoinColumn(name = "CONTENT_FILE_ID") + @OneToOne(fetch = FetchType.LAZY) + protected FileDescriptor contentFile; + + @Column(name = "NAME", length = 500) + protected String name; + + @Column(name = "CONTENT_ID", length = 50) + protected String contentId; + + @Column(name = "DISPOSITION", length = 50) + protected String disposition; + + @Column(name = "TEXT_ENCODING", length = 50) + protected String encoding; + + public SendingMessage getMessage() { + return message; + } + + public void setMessage(SendingMessage message) { + this.message = message; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getContentId() { + return contentId; + } + + public void setContentId(String contentId) { + this.contentId = contentId; + } + + public String getDisposition() { + return disposition; + } + + public void setDisposition(String disposition) { + this.disposition = disposition; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public FileDescriptor getContentFile() { + return contentFile; + } + + public void setContentFile(FileDescriptor contentFile) { + this.contentFile = contentFile; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/SendingMessage.java b/modules/global/src/com/haulmont/cuba/core/entity/SendingMessage.java index 8de99d028c..6d80f758ac 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/SendingMessage.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/SendingMessage.java @@ -1,189 +1,189 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.SendingStatus; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.*; -import javax.persistence.Entity; -import java.util.Date; -import java.util.List; - -/** - * Entity to store information about sending emails. - * - */ -@Entity(name = "sys$SendingMessage") -@Table(name = "SYS_SENDING_MESSAGE") -@SystemLevel -public class SendingMessage extends StandardEntity { - - private static final long serialVersionUID = -8156998515878702538L; - - public static final int CAPTION_LENGTH = 500; - public static final String HEADERS_SEPARATOR = "\n"; - - @Column(name = "ADDRESS_TO") - protected String address; - - @Column(name = "ADDRESS_FROM") - protected String from; - - @Column(name = "CAPTION", length = CAPTION_LENGTH) - protected String caption; - - /** - * Email body is stored either in this field or in {@link #contentTextFile}. - */ - @Column(name = "CONTENT_TEXT") - protected String contentText; - - @JoinColumn(name = "CONTENT_TEXT_FILE_ID") - @OneToOne(fetch = FetchType.LAZY) - protected FileDescriptor contentTextFile; - - @Column(name = "STATUS") - protected Integer status; - - @Column(name = "DATE_SENT") - protected Date dateSent; - - @Column(name = "ATTACHMENTS_NAME") - protected String attachmentsName; - - @Column(name = "DEADLINE") - protected Date deadline; - - @Column(name = "ATTEMPTS_COUNT") - protected Integer attemptsCount; - - @Column(name = "ATTEMPTS_MADE") - protected Integer attemptsMade; - - @OneToMany(mappedBy = "message", fetch = FetchType.LAZY) - protected List attachments; - - @Column(name = "EMAIL_HEADERS") - protected String headers; - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getContentText() { - return contentText; - } - - public void setContentText(String contentText) { - this.contentText = contentText; - } - - public Date getDeadline() { - return deadline; - } - - public void setDeadline(Date deadline) { - this.deadline = deadline; - } - - public SendingStatus getStatus() { - return status == null ? null : SendingStatus.fromId(status); - } - - public void setStatus(SendingStatus status) { - this.status = status == null ? null : status.getId(); - } - - public Date getDateSent() { - return dateSent; - } - - public void setDateSent(Date dateSent) { - this.dateSent = dateSent; - } - - public Integer getAttemptsCount() { - return attemptsCount; - } - - public void setAttemptsCount(Integer attemptsCount) { - this.attemptsCount = attemptsCount; - } - - public String getAttachmentsName() { - return attachmentsName; - } - - public void setAttachmentsName(String attachmentsName) { - this.attachmentsName = attachmentsName; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public void setCaption(String caption) { - this.caption = StringUtils.substring(caption, 0, SendingMessage.CAPTION_LENGTH); - } - - public String getCaption() { - return caption; - } - - public List getAttachments() { - return attachments; - } - - public void setAttachments(List attachments) { - this.attachments = attachments; - } - - public Integer getAttemptsMade() { - return attemptsMade; - } - - public void setAttemptsMade(Integer attemptsMade) { - this.attemptsMade = attemptsMade; - } - - public FileDescriptor getContentTextFile() { - return contentTextFile; - } - - public void setContentTextFile(FileDescriptor contentTextFile) { - this.contentTextFile = contentTextFile; - } - - public String getHeaders() { - return headers; - } - - public void setHeaders(String headers) { - this.headers = headers; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.SendingStatus; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.*; +import javax.persistence.Entity; +import java.util.Date; +import java.util.List; + +/** + * Entity to store information about sending emails. + * + */ +@Entity(name = "sys$SendingMessage") +@Table(name = "SYS_SENDING_MESSAGE") +@SystemLevel +public class SendingMessage extends StandardEntity { + + private static final long serialVersionUID = -8156998515878702538L; + + public static final int CAPTION_LENGTH = 500; + public static final String HEADERS_SEPARATOR = "\n"; + + @Column(name = "ADDRESS_TO") + protected String address; + + @Column(name = "ADDRESS_FROM") + protected String from; + + @Column(name = "CAPTION", length = CAPTION_LENGTH) + protected String caption; + + /** + * Email body is stored either in this field or in {@link #contentTextFile}. + */ + @Column(name = "CONTENT_TEXT") + protected String contentText; + + @JoinColumn(name = "CONTENT_TEXT_FILE_ID") + @OneToOne(fetch = FetchType.LAZY) + protected FileDescriptor contentTextFile; + + @Column(name = "STATUS") + protected Integer status; + + @Column(name = "DATE_SENT") + protected Date dateSent; + + @Column(name = "ATTACHMENTS_NAME") + protected String attachmentsName; + + @Column(name = "DEADLINE") + protected Date deadline; + + @Column(name = "ATTEMPTS_COUNT") + protected Integer attemptsCount; + + @Column(name = "ATTEMPTS_MADE") + protected Integer attemptsMade; + + @OneToMany(mappedBy = "message", fetch = FetchType.LAZY) + protected List attachments; + + @Column(name = "EMAIL_HEADERS") + protected String headers; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getContentText() { + return contentText; + } + + public void setContentText(String contentText) { + this.contentText = contentText; + } + + public Date getDeadline() { + return deadline; + } + + public void setDeadline(Date deadline) { + this.deadline = deadline; + } + + public SendingStatus getStatus() { + return status == null ? null : SendingStatus.fromId(status); + } + + public void setStatus(SendingStatus status) { + this.status = status == null ? null : status.getId(); + } + + public Date getDateSent() { + return dateSent; + } + + public void setDateSent(Date dateSent) { + this.dateSent = dateSent; + } + + public Integer getAttemptsCount() { + return attemptsCount; + } + + public void setAttemptsCount(Integer attemptsCount) { + this.attemptsCount = attemptsCount; + } + + public String getAttachmentsName() { + return attachmentsName; + } + + public void setAttachmentsName(String attachmentsName) { + this.attachmentsName = attachmentsName; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public void setCaption(String caption) { + this.caption = StringUtils.substring(caption, 0, SendingMessage.CAPTION_LENGTH); + } + + public String getCaption() { + return caption; + } + + public List getAttachments() { + return attachments; + } + + public void setAttachments(List attachments) { + this.attachments = attachments; + } + + public Integer getAttemptsMade() { + return attemptsMade; + } + + public void setAttemptsMade(Integer attemptsMade) { + this.attemptsMade = attemptsMade; + } + + public FileDescriptor getContentTextFile() { + return contentTextFile; + } + + public void setContentTextFile(FileDescriptor contentTextFile) { + this.contentTextFile = contentTextFile; + } + + public String getHeaders() { + return headers; + } + + public void setHeaders(String headers) { + this.headers = headers; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Server.java b/modules/global/src/com/haulmont/cuba/core/entity/Server.java index 6658b14136..688865cd15 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Server.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Server.java @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import java.util.Date; - -@Entity(name = "sys$Server") -@Table(name = "SYS_SERVER") -@NamePattern("%s|name") -@SystemLevel -public class Server extends BaseUuidEntity implements Creatable, Updatable { - - private static final long serialVersionUID = 1892335683693067357L; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "UPDATE_TS") - protected Date updateTs; - - @Column(name = "UPDATED_BY", length = 50) - protected String updatedBy; - - @Column(name = "NAME") - private String name; - - @Column(name = "IS_RUNNING") - private Boolean running; - - @Column(name = "DATA") - private String data; - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - @Override - public Date getUpdateTs() { - return updateTs; - } - - @Override - public void setUpdateTs(Date updateTs) { - this.updateTs = updateTs; - } - - @Override - public String getUpdatedBy() { - return updatedBy; - } - - @Override - public void setUpdatedBy(String updatedBy) { - this.updatedBy = updatedBy; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Boolean getRunning() { - return running; - } - - public void setRunning(Boolean running) { - this.running = running; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; + +@Entity(name = "sys$Server") +@Table(name = "SYS_SERVER") +@NamePattern("%s|name") +@SystemLevel +public class Server extends BaseUuidEntity implements Creatable, Updatable { + + private static final long serialVersionUID = 1892335683693067357L; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "UPDATE_TS") + protected Date updateTs; + + @Column(name = "UPDATED_BY", length = 50) + protected String updatedBy; + + @Column(name = "NAME") + private String name; + + @Column(name = "IS_RUNNING") + private Boolean running; + + @Column(name = "DATA") + private String data; + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + @Override + public Date getUpdateTs() { + return updateTs; + } + + @Override + public void setUpdateTs(Date updateTs) { + this.updateTs = updateTs; + } + + @Override + public String getUpdatedBy() { + return updatedBy; + } + + @Override + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean getRunning() { + return running; + } + + public void setRunning(Boolean running) { + this.running = running; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/SoftDelete.java b/modules/global/src/com/haulmont/cuba/core/entity/SoftDelete.java index ae8c643c2b..f58033b525 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/SoftDelete.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/SoftDelete.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import java.util.Date; - -/** - * Interface to be implemented by entities that support soft deletion. - * - */ -public interface SoftDelete { - - /** - * Returns true if the entity is deleted. - */ - Boolean isDeleted(); - - /** - * Returns deletion timestamp or null if not deleted. - */ - Date getDeleteTs(); - - /** - * Returns login name of the user who deleted the entity - * or null if not deleted. - */ - String getDeletedBy(); - - /** - * INTERNAL. Sets soft deletion timestamp. - */ - void setDeleteTs(Date deleteTs); - - /** - * INTERNAL. Sets login name of the user who deleted the entity. - */ - void setDeletedBy(String deletedBy); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import java.util.Date; + +/** + * Interface to be implemented by entities that support soft deletion. + * + */ +public interface SoftDelete { + + /** + * Returns true if the entity is deleted. + */ + Boolean isDeleted(); + + /** + * Returns deletion timestamp or null if not deleted. + */ + Date getDeleteTs(); + + /** + * Returns login name of the user who deleted the entity + * or null if not deleted. + */ + String getDeletedBy(); + + /** + * INTERNAL. Sets soft deletion timestamp. + */ + void setDeleteTs(Date deleteTs); + + /** + * INTERNAL. Sets login name of the user who deleted the entity. + */ + void setDeletedBy(String deletedBy); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/StandardEntity.java b/modules/global/src/com/haulmont/cuba/core/entity/StandardEntity.java index fee8519e91..6a44f8f547 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/StandardEntity.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/StandardEntity.java @@ -1,133 +1,133 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; - -import javax.persistence.MappedSuperclass; -import javax.persistence.Column; -import javax.persistence.Version; -import java.util.Date; - -/** - * The most widely used base class for persistent entities.
- * Optimistically locked, implements Updatable and SoftDelete. - */ -@MappedSuperclass -@MetaClass(name = "sys$StandardEntity") -@UnavailableInSecurityConstraints -public class StandardEntity extends BaseUuidEntity implements Versioned, Creatable, Updatable, SoftDelete { - private static final long serialVersionUID = 5642226839555253331L; - - @Version - @Column(name = "VERSION", nullable = false) - protected Integer version; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "UPDATE_TS") - protected Date updateTs; - - @Column(name = "UPDATED_BY", length = 50) - protected String updatedBy; - - @Column(name = "DELETE_TS") - protected Date deleteTs; - - @Column(name = "DELETED_BY", length = 50) - protected String deletedBy; - - @Override - public Integer getVersion() { - return version; - } - - @Override - public void setVersion(Integer version) { - this.version = version; - } - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - @Override - public Date getUpdateTs() { - return updateTs; - } - - @Override - public void setUpdateTs(Date updateTs) { - this.updateTs = updateTs; - } - - @Override - public String getUpdatedBy() { - return updatedBy; - } - - @Override - public void setUpdatedBy(String updatedBy) { - this.updatedBy = updatedBy; - } - - @Override - public Boolean isDeleted() { - return deleteTs != null; - } - - @Override - public Date getDeleteTs() { - return deleteTs; - } - - @Override - public void setDeleteTs(Date deleteTs) { - this.deleteTs = deleteTs; - } - - @Override - public String getDeletedBy() { - return deletedBy; - } - - @Override - public void setDeletedBy(String deletedBy) { - this.deletedBy = deletedBy; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.cuba.core.entity.annotation.UnavailableInSecurityConstraints; + +import javax.persistence.MappedSuperclass; +import javax.persistence.Column; +import javax.persistence.Version; +import java.util.Date; + +/** + * The most widely used base class for persistent entities.
+ * Optimistically locked, implements Updatable and SoftDelete. + */ +@MappedSuperclass +@MetaClass(name = "sys$StandardEntity") +@UnavailableInSecurityConstraints +public class StandardEntity extends BaseUuidEntity implements Versioned, Creatable, Updatable, SoftDelete { + private static final long serialVersionUID = 5642226839555253331L; + + @Version + @Column(name = "VERSION", nullable = false) + protected Integer version; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "UPDATE_TS") + protected Date updateTs; + + @Column(name = "UPDATED_BY", length = 50) + protected String updatedBy; + + @Column(name = "DELETE_TS") + protected Date deleteTs; + + @Column(name = "DELETED_BY", length = 50) + protected String deletedBy; + + @Override + public Integer getVersion() { + return version; + } + + @Override + public void setVersion(Integer version) { + this.version = version; + } + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + @Override + public Date getUpdateTs() { + return updateTs; + } + + @Override + public void setUpdateTs(Date updateTs) { + this.updateTs = updateTs; + } + + @Override + public String getUpdatedBy() { + return updatedBy; + } + + @Override + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + @Override + public Boolean isDeleted() { + return deleteTs != null; + } + + @Override + public Date getDeleteTs() { + return deleteTs; + } + + @Override + public void setDeleteTs(Date deleteTs) { + this.deleteTs = deleteTs; + } + + @Override + public String getDeletedBy() { + return deletedBy; + } + + @Override + public void setDeletedBy(String deletedBy) { + this.deletedBy = deletedBy; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Updatable.java b/modules/global/src/com/haulmont/cuba/core/entity/Updatable.java index 69a18fcd79..08b30efe8a 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Updatable.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Updatable.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -import java.util.Date; - -/** - * Interface to be implemented by entities that contain information about who updated them and when. - */ -public interface Updatable { - - Date getUpdateTs(); - - void setUpdateTs(Date updateTs); - - String getUpdatedBy(); - - void setUpdatedBy(String updatedBy); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +import java.util.Date; + +/** + * Interface to be implemented by entities that contain information about who updated them and when. + */ +public interface Updatable { + + Date getUpdateTs(); + + void setUpdateTs(Date updateTs); + + String getUpdatedBy(); + + void setUpdatedBy(String updatedBy); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/Versioned.java b/modules/global/src/com/haulmont/cuba/core/entity/Versioned.java index e5699bd4f8..eed8e039dd 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/Versioned.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/Versioned.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity; - -/** - * Interface to be implemented by optimistically locked entities. - * - */ -public interface Versioned { - - Integer getVersion(); - - /** - * Do not set version if you are not sure - it must be null for a new entity or loaded from the database - * for a persistent one. - */ - void setVersion(Integer version); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity; + +/** + * Interface to be implemented by optimistically locked entities. + * + */ +public interface Versioned { + + Integer getVersion(); + + /** + * Do not set version if you are not sure - it must be null for a new entity or loaded from the database + * for a persistent one. + */ + void setVersion(Integer version); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/annotation/EmbeddedParameters.java b/modules/global/src/com/haulmont/cuba/core/entity/annotation/EmbeddedParameters.java index a8e72a16bf..073d373c07 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/annotation/EmbeddedParameters.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/annotation/EmbeddedParameters.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Defines additional parameters for Embedded attributes. - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -public @interface EmbeddedParameters { - - /** - * If false, the embedded entity can not be null. This means you can always provide an instance when persisting - * the entity, even if all its attributes are null. - *

- * By default, the embedded entity can be null. In this case ORM does not create the instance on loading - * if all attributes are null. - */ - boolean nullAllowed() default true; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines additional parameters for Embedded attributes. + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface EmbeddedParameters { + + /** + * If false, the embedded entity can not be null. This means you can always provide an instance when persisting + * the entity, even if all its attributes are null. + *

+ * By default, the embedded entity can be null. In this case ORM does not create the instance on loading + * if all attributes are null. + */ + boolean nullAllowed() default true; +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/annotation/Listeners.java b/modules/global/src/com/haulmont/cuba/core/entity/annotation/Listeners.java index fa335d9df2..8dd3b1b6e0 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/annotation/Listeners.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/annotation/Listeners.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Defines classes of entity lifecycle listeners - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Listeners -{ - String[] value() default {}; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines classes of entity lifecycle listeners + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Listeners +{ + String[] value() default {}; +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/annotation/LocalizedValue.java b/modules/global/src/com/haulmont/cuba/core/entity/annotation/LocalizedValue.java index 2cf238d939..da0533aba8 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/annotation/LocalizedValue.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/annotation/LocalizedValue.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Explains how to get localized value of an attribute - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -@MetaAnnotation -public @interface LocalizedValue { - - /** - * Explicit definition of a messages pack, e.g. "com.haulmont.cuba.core.entity" - */ - String messagePack() default ""; - - /** - * Expression in terms of traversing object graph, returning messages pack name stored in an attribute, - * e.g. "proc.messagesPack" - */ - String messagePackExpr() default ""; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Explains how to get localized value of an attribute + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@MetaAnnotation +public @interface LocalizedValue { + + /** + * Explicit definition of a messages pack, e.g. "com.haulmont.cuba.core.entity" + */ + String messagePack() default ""; + + /** + * Expression in terms of traversing object graph, returning messages pack name stored in an attribute, + * e.g. "proc.messagesPack" + */ + String messagePackExpr() default ""; +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDelete.java b/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDelete.java index 64eede87a2..57bdd184cc 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDelete.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDelete.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity.annotation; - -import com.haulmont.cuba.core.global.DeletePolicy; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; - -/** - * Marks a link to other entity for specific soft deletion behaviour.
- * Taken into account by persistence when "this" entity is deleted.
- * See also {@link DeletePolicy} - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -public @interface OnDelete -{ - DeletePolicy value(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity.annotation; + +import com.haulmont.cuba.core.global.DeletePolicy; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; + +/** + * Marks a link to other entity for specific soft deletion behaviour.
+ * Taken into account by persistence when "this" entity is deleted.
+ * See also {@link DeletePolicy} + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface OnDelete +{ + DeletePolicy value(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDeleteInverse.java b/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDeleteInverse.java index a013adb649..41b019c15a 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDeleteInverse.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/annotation/OnDeleteInverse.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.entity.annotation; - -import com.haulmont.cuba.core.global.DeletePolicy; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.annotation.ElementType; - -/** - * Marks a link to other entity for specific soft deletion behaviour.
- * Taken into account by persistence when "linked" entity (which is referenced by the marked field) - * is deleted.
- * See also {@link DeletePolicy} - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -public @interface OnDeleteInverse -{ - DeletePolicy value(); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.entity.annotation; + +import com.haulmont.cuba.core.global.DeletePolicy; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Marks a link to other entity for specific soft deletion behaviour.
+ * Taken into account by persistence when "linked" entity (which is referenced by the marked field) + * is deleted.
+ * See also {@link DeletePolicy} + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface OnDeleteInverse +{ + DeletePolicy value(); +} diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityBasicPropertyDiff.java b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityBasicPropertyDiff.java index 827440c4cf..924bfaf0cb 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityBasicPropertyDiff.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityBasicPropertyDiff.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.diff; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.ViewProperty; - -@MetaClass(name = "sys$EntityBasicPropertyDiff") -@SystemLevel -public class EntityBasicPropertyDiff extends EntityPropertyDiff { - - private static final long serialVersionUID = -1532265990429557046L; - - private Object beforeValue; - - private Object afterValue; - - public EntityBasicPropertyDiff(ViewProperty viewProperty, MetaProperty metaProperty, - Object beforeValue, Object afterValue) { - super(viewProperty, metaProperty); - this.beforeValue = beforeValue; - this.afterValue = afterValue; - } - - @Override - public boolean hasStateValues() { - return true; - } - - @Override - public Object getBeforeValue() { - return beforeValue; - } - - @Override - public Object getAfterValue() { - return afterValue; - } - - @Override - public String getLabel() { - if (afterValue != null) - return afterValue.toString(); - else - return super.getLabel(); - } - - @Override - public String getBeforeString() { - if (beforeValue != null) { - if (beforeValue instanceof EnumClass) - return getEnumItemName(beforeValue); - return String.valueOf(beforeValue); - } - return super.getBeforeString(); - } - - @Override - public String getAfterString() { - if (afterValue != null) { - if (afterValue instanceof EnumClass) - return getEnumItemName(afterValue); - return String.valueOf(afterValue); - } - return super.getAfterString(); - } - - private String getEnumItemName(Object enumItem) { - String nameKey = enumItem.getClass().getSimpleName() + "." + enumItem.toString(); - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMessage(enumItem.getClass(), nameKey); - } - - @Override - public String getBeforeCaption() { - String value = getBeforeString(); - if (value.length() > CAPTION_CHAR_COUNT) - return value.substring(0, CAPTION_CHAR_COUNT) + "..."; - return super.getBeforeCaption(); - } - - @Override - public String getAfterCaption() { - String value = getAfterString(); - if (value.length() > CAPTION_CHAR_COUNT) - return value.substring(0, CAPTION_CHAR_COUNT) + "..."; - return super.getAfterCaption(); - } - - @Override - public ItemState getItemState() { - return ItemState.Modified; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.diff; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.ViewProperty; + +@MetaClass(name = "sys$EntityBasicPropertyDiff") +@SystemLevel +public class EntityBasicPropertyDiff extends EntityPropertyDiff { + + private static final long serialVersionUID = -1532265990429557046L; + + private Object beforeValue; + + private Object afterValue; + + public EntityBasicPropertyDiff(ViewProperty viewProperty, MetaProperty metaProperty, + Object beforeValue, Object afterValue) { + super(viewProperty, metaProperty); + this.beforeValue = beforeValue; + this.afterValue = afterValue; + } + + @Override + public boolean hasStateValues() { + return true; + } + + @Override + public Object getBeforeValue() { + return beforeValue; + } + + @Override + public Object getAfterValue() { + return afterValue; + } + + @Override + public String getLabel() { + if (afterValue != null) + return afterValue.toString(); + else + return super.getLabel(); + } + + @Override + public String getBeforeString() { + if (beforeValue != null) { + if (beforeValue instanceof EnumClass) + return getEnumItemName(beforeValue); + return String.valueOf(beforeValue); + } + return super.getBeforeString(); + } + + @Override + public String getAfterString() { + if (afterValue != null) { + if (afterValue instanceof EnumClass) + return getEnumItemName(afterValue); + return String.valueOf(afterValue); + } + return super.getAfterString(); + } + + private String getEnumItemName(Object enumItem) { + String nameKey = enumItem.getClass().getSimpleName() + "." + enumItem.toString(); + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMessage(enumItem.getClass(), nameKey); + } + + @Override + public String getBeforeCaption() { + String value = getBeforeString(); + if (value.length() > CAPTION_CHAR_COUNT) + return value.substring(0, CAPTION_CHAR_COUNT) + "..."; + return super.getBeforeCaption(); + } + + @Override + public String getAfterCaption() { + String value = getAfterString(); + if (value.length() > CAPTION_CHAR_COUNT) + return value.substring(0, CAPTION_CHAR_COUNT) + "..."; + return super.getAfterCaption(); + } + + @Override + public ItemState getItemState() { + return ItemState.Modified; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityClassPropertyDiff.java b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityClassPropertyDiff.java index 3237f615e0..90fd4708a7 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityClassPropertyDiff.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityClassPropertyDiff.java @@ -1,150 +1,150 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.diff; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.ViewProperty; - -import java.util.ArrayList; -import java.util.List; - -@MetaClass(name = "sys$EntityClassPropertyDiff") -@SystemLevel -public class EntityClassPropertyDiff extends EntityPropertyDiff { - private static final long serialVersionUID = -6783119655414015181L; - - private Object beforeValue; - - private Object afterValue; - - private ItemState itemState = ItemState.Normal; - - private boolean isLinkChange; - - private List propertyDiffs = new ArrayList<>(); - - private String beforeString = ""; - - private String afterString = ""; - - public EntityClassPropertyDiff(Object beforeValue, Object afterValue, - ViewProperty viewProperty, MetaProperty metaProperty, - boolean linkChange) { - super(viewProperty, metaProperty); - this.beforeValue = beforeValue; - this.afterValue = afterValue; - this.isLinkChange = linkChange; - - if ((afterValue != null) && isLinkChange) - label = InstanceUtils.getInstanceName((Instance) afterValue); - else - label = ""; - - if (afterValue != null) - afterString = InstanceUtils.getInstanceName((Instance) afterValue); - - if (beforeValue != null) - beforeString = InstanceUtils.getInstanceName((Instance) beforeValue); - } - - @Override - public boolean hasStateValues() { - return true; - } - - @Override - public Object getBeforeValue() { - return beforeValue; - } - - @Override - public Object getAfterValue() { - return afterValue; - } - - @Override - public ItemState getItemState() { - return itemState; - } - - @Override - public void setItemState(ItemState itemState) { - this.itemState = itemState; - } - - public List getPropertyDiffs() { - return propertyDiffs; - } - - public void setPropertyDiffs(List propertyDiffs) { - this.propertyDiffs = propertyDiffs; - } - - public boolean isLinkChange() { - return isLinkChange; - } - - @Override - public String getBeforeString() { - if (itemState != ItemState.Added && isLinkChange) - return beforeString; - else - return ""; - } - - @Override - public String getAfterString() { - if (itemState != ItemState.Removed && isLinkChange) - return afterString; - else - return ""; - } - - @Override - public String getBeforeCaption() { - String value = getBeforeString(); - if (value.length() > CAPTION_CHAR_COUNT) - return value.substring(0, CAPTION_CHAR_COUNT) + "..."; - return super.getBeforeCaption(); - } - - @Override - public String getAfterCaption() { - String value = getAfterString(); - if (value.length() > CAPTION_CHAR_COUNT) - return value.substring(0, CAPTION_CHAR_COUNT) + "..."; - return super.getAfterCaption(); - } - - @Override - public boolean itemStateVisible() { - return itemState != ItemState.Normal; - } - - @Override - public String getLabel() { - if (itemState == ItemState.Normal) - return super.getLabel(); - else - return ""; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.diff; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.ViewProperty; + +import java.util.ArrayList; +import java.util.List; + +@MetaClass(name = "sys$EntityClassPropertyDiff") +@SystemLevel +public class EntityClassPropertyDiff extends EntityPropertyDiff { + private static final long serialVersionUID = -6783119655414015181L; + + private Object beforeValue; + + private Object afterValue; + + private ItemState itemState = ItemState.Normal; + + private boolean isLinkChange; + + private List propertyDiffs = new ArrayList<>(); + + private String beforeString = ""; + + private String afterString = ""; + + public EntityClassPropertyDiff(Object beforeValue, Object afterValue, + ViewProperty viewProperty, MetaProperty metaProperty, + boolean linkChange) { + super(viewProperty, metaProperty); + this.beforeValue = beforeValue; + this.afterValue = afterValue; + this.isLinkChange = linkChange; + + if ((afterValue != null) && isLinkChange) + label = InstanceUtils.getInstanceName((Instance) afterValue); + else + label = ""; + + if (afterValue != null) + afterString = InstanceUtils.getInstanceName((Instance) afterValue); + + if (beforeValue != null) + beforeString = InstanceUtils.getInstanceName((Instance) beforeValue); + } + + @Override + public boolean hasStateValues() { + return true; + } + + @Override + public Object getBeforeValue() { + return beforeValue; + } + + @Override + public Object getAfterValue() { + return afterValue; + } + + @Override + public ItemState getItemState() { + return itemState; + } + + @Override + public void setItemState(ItemState itemState) { + this.itemState = itemState; + } + + public List getPropertyDiffs() { + return propertyDiffs; + } + + public void setPropertyDiffs(List propertyDiffs) { + this.propertyDiffs = propertyDiffs; + } + + public boolean isLinkChange() { + return isLinkChange; + } + + @Override + public String getBeforeString() { + if (itemState != ItemState.Added && isLinkChange) + return beforeString; + else + return ""; + } + + @Override + public String getAfterString() { + if (itemState != ItemState.Removed && isLinkChange) + return afterString; + else + return ""; + } + + @Override + public String getBeforeCaption() { + String value = getBeforeString(); + if (value.length() > CAPTION_CHAR_COUNT) + return value.substring(0, CAPTION_CHAR_COUNT) + "..."; + return super.getBeforeCaption(); + } + + @Override + public String getAfterCaption() { + String value = getAfterString(); + if (value.length() > CAPTION_CHAR_COUNT) + return value.substring(0, CAPTION_CHAR_COUNT) + "..."; + return super.getAfterCaption(); + } + + @Override + public boolean itemStateVisible() { + return itemState != ItemState.Normal; + } + + @Override + public String getLabel() { + if (itemState == ItemState.Normal) + return super.getLabel(); + else + return ""; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityCollectionPropertyDiff.java b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityCollectionPropertyDiff.java index 08d7b97eda..754f935af2 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityCollectionPropertyDiff.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityCollectionPropertyDiff.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.diff; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.ViewProperty; - -import java.util.ArrayList; -import java.util.List; - -@MetaClass(name = "sys$EntityCollectionPropertyDiff") -@SystemLevel -public class EntityCollectionPropertyDiff extends EntityPropertyDiff { - - private static final long serialVersionUID = -7472572229609999760L; - - private List addedEntities = new ArrayList<>(); - - private List removedEntities = new ArrayList<>(); - - private List modifiedEntities = new ArrayList<>(); - - public EntityCollectionPropertyDiff(ViewProperty viewProperty, - MetaProperty metaProperty) { - super(viewProperty, metaProperty); - } - - public List getAddedEntities() { - return addedEntities; - } - - public void setAddedEntities(List addedEntities) { - this.addedEntities = addedEntities; - } - - public List getRemovedEntities() { - return removedEntities; - } - - public void setRemovedEntities(List removedEntities) { - this.removedEntities = removedEntities; - } - - public List getModifiedEntities() { - return modifiedEntities; - } - - public void setModifiedEntities(List modifiedEntities) { - this.modifiedEntities = modifiedEntities; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.diff; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.ViewProperty; + +import java.util.ArrayList; +import java.util.List; + +@MetaClass(name = "sys$EntityCollectionPropertyDiff") +@SystemLevel +public class EntityCollectionPropertyDiff extends EntityPropertyDiff { + + private static final long serialVersionUID = -7472572229609999760L; + + private List addedEntities = new ArrayList<>(); + + private List removedEntities = new ArrayList<>(); + + private List modifiedEntities = new ArrayList<>(); + + public EntityCollectionPropertyDiff(ViewProperty viewProperty, + MetaProperty metaProperty) { + super(viewProperty, metaProperty); + } + + public List getAddedEntities() { + return addedEntities; + } + + public void setAddedEntities(List addedEntities) { + this.addedEntities = addedEntities; + } + + public List getRemovedEntities() { + return removedEntities; + } + + public void setRemovedEntities(List removedEntities) { + this.removedEntities = removedEntities; + } + + public List getModifiedEntities() { + return modifiedEntities; + } + + public void setModifiedEntities(List modifiedEntities) { + this.modifiedEntities = modifiedEntities; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityDiff.java b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityDiff.java index 913519f40e..a6566a922e 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityDiff.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityDiff.java @@ -1,117 +1,117 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.diff; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.View; - -import java.util.ArrayList; -import java.util.List; - -/** - * Diff object for Entity Snapshots - */ -@MetaClass(name = "sys$EntityDiff") -@SystemLevel -public class EntityDiff extends BaseUuidEntity { - - private static final long serialVersionUID = -3884249873393845439L; - - private View diffView; - - private EntitySnapshot beforeSnapshot; - - private EntitySnapshot afterSnapshot; - - private Entity beforeEntity; - - private Entity afterEntity; - - private List propertyDiffs = new ArrayList<>(); - - public EntityDiff(View diffView) { - this.diffView = diffView; - } - - public View getDiffView() { - return diffView; - } - - public void setDiffView(View diffView) { - this.diffView = diffView; - } - - public EntitySnapshot getBeforeSnapshot() { - return beforeSnapshot; - } - - public void setBeforeSnapshot(EntitySnapshot beforeSnapshot) { - this.beforeSnapshot = beforeSnapshot; - } - - public EntitySnapshot getAfterSnapshot() { - return afterSnapshot; - } - - public void setAfterSnapshot(EntitySnapshot afterSnapshot) { - this.afterSnapshot = afterSnapshot; - } - - public Entity getBeforeEntity() { - return beforeEntity; - } - - public void setBeforeEntity(Entity beforeEntity) { - this.beforeEntity = beforeEntity; - } - - public Entity getAfterEntity() { - return afterEntity; - } - - public void setAfterEntity(Entity afterEntity) { - this.afterEntity = afterEntity; - } - - public List getPropertyDiffs() { - return propertyDiffs; - } - - public void setPropertyDiffs(List propertyDiffs) { - this.propertyDiffs = propertyDiffs; - } - - @MetaProperty - public String getLabel(){ - String label = ""; - if (beforeSnapshot != null) - label += beforeSnapshot.getLabel() + " : "; - else - label += ""; - - if (afterSnapshot != null) - label += afterSnapshot.getLabel(); - - return label; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.diff; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.View; + +import java.util.ArrayList; +import java.util.List; + +/** + * Diff object for Entity Snapshots + */ +@MetaClass(name = "sys$EntityDiff") +@SystemLevel +public class EntityDiff extends BaseUuidEntity { + + private static final long serialVersionUID = -3884249873393845439L; + + private View diffView; + + private EntitySnapshot beforeSnapshot; + + private EntitySnapshot afterSnapshot; + + private Entity beforeEntity; + + private Entity afterEntity; + + private List propertyDiffs = new ArrayList<>(); + + public EntityDiff(View diffView) { + this.diffView = diffView; + } + + public View getDiffView() { + return diffView; + } + + public void setDiffView(View diffView) { + this.diffView = diffView; + } + + public EntitySnapshot getBeforeSnapshot() { + return beforeSnapshot; + } + + public void setBeforeSnapshot(EntitySnapshot beforeSnapshot) { + this.beforeSnapshot = beforeSnapshot; + } + + public EntitySnapshot getAfterSnapshot() { + return afterSnapshot; + } + + public void setAfterSnapshot(EntitySnapshot afterSnapshot) { + this.afterSnapshot = afterSnapshot; + } + + public Entity getBeforeEntity() { + return beforeEntity; + } + + public void setBeforeEntity(Entity beforeEntity) { + this.beforeEntity = beforeEntity; + } + + public Entity getAfterEntity() { + return afterEntity; + } + + public void setAfterEntity(Entity afterEntity) { + this.afterEntity = afterEntity; + } + + public List getPropertyDiffs() { + return propertyDiffs; + } + + public void setPropertyDiffs(List propertyDiffs) { + this.propertyDiffs = propertyDiffs; + } + + @MetaProperty + public String getLabel(){ + String label = ""; + if (beforeSnapshot != null) + label += beforeSnapshot.getLabel() + " : "; + else + label += ""; + + if (afterSnapshot != null) + label += afterSnapshot.getLabel(); + + return label; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityPropertyDiff.java b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityPropertyDiff.java index fd8e300d2c..bc6d02adca 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityPropertyDiff.java +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/EntityPropertyDiff.java @@ -1,132 +1,132 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity.diff; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MessageTools; -import com.haulmont.cuba.core.global.ViewProperty; - -/** - * Diff between properties in entity snapshots - * - */ -@MetaClass(name = "sys$EntityPropertyDiff") -@SystemLevel -public abstract class EntityPropertyDiff extends BaseUuidEntity { - - protected static final int CAPTION_CHAR_COUNT = 30; - - public enum ItemState { - Normal, - Modified, - Added, - Removed - } - - private static final long serialVersionUID = -6467322033937742101L; - - private ViewProperty viewProperty; - protected String propertyCaption; - protected String label = ""; - protected String metaClassName = ""; - - protected EntityPropertyDiff(ViewProperty viewProperty, com.haulmont.chile.core.model.MetaProperty metaProperty) { - this.viewProperty = viewProperty; - MessageTools messageTools = AppBeans.get(MessageTools.NAME); - this.propertyCaption = messageTools.getPropertyCaption(metaProperty.getDomain(), metaProperty.getName()); - this.metaClassName = metaProperty.getDomain().getName(); - } - - public ViewProperty getViewProperty() { - return viewProperty; - } - - public String getMetaClassName() { - return metaClassName; - } - - @MetaProperty - public String getName() { - return propertyCaption; - } - - @MetaProperty - public void setName(String name) { - propertyCaption = name; - } - - @MetaProperty - public String getLabel() { - return label; - } - - @MetaProperty - public void setLabel(String label) { - this.label = label; - } - - public boolean hasStateValues() { - return false; - } - - public Object getBeforeValue() { - return null; - } - - public Object getAfterValue() { - return null; - } - - @MetaProperty - public String getBeforeString() { - return ""; - } - - @MetaProperty - public String getAfterString() { - return ""; - } - - @MetaProperty - public String getBeforeCaption() { - return getBeforeString(); - } - - @MetaProperty - public String getAfterCaption() { - return getAfterString(); - } - - @MetaProperty - public ItemState getItemState() { - return ItemState.Normal; - } - - @MetaProperty - public void setItemState(ItemState itemState) { - - } - - public boolean itemStateVisible() { - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity.diff; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MessageTools; +import com.haulmont.cuba.core.global.ViewProperty; + +/** + * Diff between properties in entity snapshots + * + */ +@MetaClass(name = "sys$EntityPropertyDiff") +@SystemLevel +public abstract class EntityPropertyDiff extends BaseUuidEntity { + + protected static final int CAPTION_CHAR_COUNT = 30; + + public enum ItemState { + Normal, + Modified, + Added, + Removed + } + + private static final long serialVersionUID = -6467322033937742101L; + + private ViewProperty viewProperty; + protected String propertyCaption; + protected String label = ""; + protected String metaClassName = ""; + + protected EntityPropertyDiff(ViewProperty viewProperty, com.haulmont.chile.core.model.MetaProperty metaProperty) { + this.viewProperty = viewProperty; + MessageTools messageTools = AppBeans.get(MessageTools.NAME); + this.propertyCaption = messageTools.getPropertyCaption(metaProperty.getDomain(), metaProperty.getName()); + this.metaClassName = metaProperty.getDomain().getName(); + } + + public ViewProperty getViewProperty() { + return viewProperty; + } + + public String getMetaClassName() { + return metaClassName; + } + + @MetaProperty + public String getName() { + return propertyCaption; + } + + @MetaProperty + public void setName(String name) { + propertyCaption = name; + } + + @MetaProperty + public String getLabel() { + return label; + } + + @MetaProperty + public void setLabel(String label) { + this.label = label; + } + + public boolean hasStateValues() { + return false; + } + + public Object getBeforeValue() { + return null; + } + + public Object getAfterValue() { + return null; + } + + @MetaProperty + public String getBeforeString() { + return ""; + } + + @MetaProperty + public String getAfterString() { + return ""; + } + + @MetaProperty + public String getBeforeCaption() { + return getBeforeString(); + } + + @MetaProperty + public String getAfterCaption() { + return getAfterString(); + } + + @MetaProperty + public ItemState getItemState() { + return ItemState.Normal; + } + + @MetaProperty + public void setItemState(ItemState itemState) { + + } + + public boolean itemStateVisible() { + return false; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/messages.properties b/modules/global/src/com/haulmont/cuba/core/entity/diff/messages.properties index bcde2442c3..cac378302e 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/messages.properties +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/messages.properties @@ -1,24 +1,24 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -EntityPropertyDiff.name = Field -EntityPropertyDiff.label = Change -EntityPropertyDiff.beforeString = Previous value -EntityPropertyDiff.afterString = New value -EntityPropertyDiff.itemState = State -EntityPropertyDiff.beforeCaption = Previous value -EntityPropertyDiff.afterCaption = New value +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +EntityPropertyDiff.name = Field +EntityPropertyDiff.label = Change +EntityPropertyDiff.beforeString = Previous value +EntityPropertyDiff.afterString = New value +EntityPropertyDiff.itemState = State +EntityPropertyDiff.beforeCaption = Previous value +EntityPropertyDiff.afterCaption = New value diff --git a/modules/global/src/com/haulmont/cuba/core/entity/diff/messages_ru.properties b/modules/global/src/com/haulmont/cuba/core/entity/diff/messages_ru.properties index 6321c42c19..02379ff593 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/diff/messages_ru.properties +++ b/modules/global/src/com/haulmont/cuba/core/entity/diff/messages_ru.properties @@ -1,24 +1,24 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -EntityPropertyDiff.name=Поле -EntityPropertyDiff.label=Изменения -EntityPropertyDiff.beforeString=Предыдущее значение -EntityPropertyDiff.afterString=Новое значение -EntityPropertyDiff.itemState=Состояние -EntityPropertyDiff.beforeCaption=Предыдущее значение -EntityPropertyDiff.afterCaption=Новое значение +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +EntityPropertyDiff.name=Поле +EntityPropertyDiff.label=Изменения +EntityPropertyDiff.beforeString=Предыдущее значение +EntityPropertyDiff.afterString=Новое значение +EntityPropertyDiff.itemState=Состояние +EntityPropertyDiff.beforeCaption=Предыдущее значение +EntityPropertyDiff.afterCaption=Новое значение diff --git a/modules/global/src/com/haulmont/cuba/core/entity/messages.properties b/modules/global/src/com/haulmont/cuba/core/entity/messages.properties index e71ef06e3a..9a55d8c0f6 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/messages.properties +++ b/modules/global/src/com/haulmont/cuba/core/entity/messages.properties @@ -1,233 +1,233 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -AbstractNotPersistentEntity.id=ID - -BaseUuidEntity.id=ID -BaseIntegerIdEntity.id=ID -BaseLongIdEntity.id=ID -BaseIdentityIdEntity.id=ID - -StandardEntity.version=Version -StandardEntity.createTs=Created At -StandardEntity.createdBy=Created By -StandardEntity.updateTs=Updated At -StandardEntity.updatedBy=Updated By -StandardEntity.deleteTs=Deleted At -StandardEntity.deletedBy=Deleted By - -FileDescriptor=File -FileDescriptor.name=Name -FileDescriptor.createDate=Created At -FileDescriptor.extension=Extension -FileDescriptor.size=Size - -SendingMessage = Message -SendingMessage.version = Version -SendingMessage.updateTs = Last Attempt Time -SendingMessage.updatedBy = Updated By -SendingMessage.deleteTs = Deleted At -SendingMessage.deletedBy = Deleted By -SendingMessage.address = Address -SendingMessage.from = From -SendingMessage.contentText = Content -SendingMessage.deadline = Deadline -SendingMessage.status = Status -SendingMessage.dateSent = Sending Date -SendingMessage.attemptsCount = Attempt Limit -SendingMessage.attemptsMade = Attempts Made -SendingMessage.attachmentsName = Attachment Names -SendingMessage.caption = Caption - -Server=Server -Server.name=Name -Server.address=Address -Server.running=Running - -EntitySnapshot=Entity Snapshot -EntitySnapshot.author=Author -EntitySnapshot.changeDate=Change Date -EntitySnapshot.viewXml=View XML -EntitySnapshot.snapshotXml=Snapshot XML -EntitySnapshot.snapshotDate=Snapshot Date -EntitySnapshot.entityId=Entity Id -EntitySnapshot.label=Label - -EntityStatistics = Entity Statistics -EntityStatistics.lookupScreenThreshold = Lookup Screen Threshold -EntityStatistics.maxFetchUI = Max Fetch UI -EntityStatistics.instanceCount = Instance Count -EntityStatistics.name = Name -EntityStatistics.fetchUI = Fetch UI -EntityStatistics.lazyCollectionThreshold = Lazy Collection Threshold - -CategorizedEntity.category=Category - -Category=Category -Category.name=Name -Category.localeName=Localized name -Category.entityType=Entity type - -CategoryAttribute=Category Attribute -CategoryAttribute.name=Name -CategoryAttribute.code=Code -CategoryAttribute.dataType=Type -CategoryAttribute.defaultString=Default value -CategoryAttribute.defaultInt=Default value -CategoryAttribute.defaultDouble=Default value -CategoryAttribute.defaultBoolean=Default value -CategoryAttribute.defaultDate=Default value -CategoryAttribute.defaultEntityId=Default value -CategoryAttribute.required=Required attribute -CategoryAttribute.isCollection=Is collection -CategoryAttribute.screen=Entity selection screen -CategoryAttribute.category = Category -CategoryAttribute.categoryEntityType = Category entity type -CategoryAttribute.enumeration = Enumeration -CategoryAttribute.isEntity = Is entity -CategoryAttribute.orderNo = Order No -CategoryAttribute.lookup = Select with lookup field -CategoryAttribute.targetScreens = Target screens -CategoryAttribute.defaultDateIsCurrent = Default date is current -CategoryAttribute.width=Width -CategoryAttribute.rowsCount=Rows count -CategoryAttribute.joinClause=Join clause -CategoryAttribute.whereClause=Where clause -CategoryAttribute.localeName=Localized name -CategoryAttribute.localeNames=Localized name values -CategoryAttribute.enumerationLocale=Localized enumeration values -CategoryAttribute.enumerationLocales=All localized enumeration values - -ScheduledTask=Scheduled Task -ScheduledTask.beanName=Bean Name -ScheduledTask.methodName=Method Name -ScheduledTask.userName=User Name -ScheduledTask.userPassword=User Password -ScheduledTask.singleton=Singleton -ScheduledTask.active=Active -ScheduledTask.period=Period, sec -ScheduledTask.timeout=Timeout, sec -ScheduledTask.startDate = Start Date -ScheduledTask.timeFrame = Time Frame, sec -ScheduledTask.startDelay = Start Delay, sec -ScheduledTask.permittedServers = Permitted Servers -ScheduledTask.logStart = Log start -ScheduledTask.logFinish = Log finish -ScheduledTask.definedBy = Defined by -ScheduledTask.className = Class Name -ScheduledTask.scriptName = Script Name -ScheduledTask.description = Description -ScheduledTask.methodParametersString = Method Parameters -ScheduledTask.cron = Cron Expression -ScheduledTask.schedulingType=Scheduling Type -ScheduledTask.updatedBy = Updated By -ScheduledTask.lastStartTime = Last Start Time -ScheduledTask.deletedBy = Deleted By -ScheduledTask.updateTs = Updated At -ScheduledTask.lastStartServer = Server Last Start Time -ScheduledTask.deleteTs = Deleted At -ScheduledTask.methodParamsXml = XML - -SchedulingType.CRON=Cron -SchedulingType.PERIOD=Period -SchedulingType.FIXED_DELAY=Fixed Delay - -ScheduledExecution = Scheduled Execution -ScheduledExecution.task = Task -ScheduledExecution.server = Server -ScheduledExecution.startTime = Start Time -ScheduledExecution.finishTime = Finish Time -ScheduledExecution.durationSec = Duration, sec -ScheduledExecution.result = Result - -ScheduledTaskDefinedBy.BEAN=Bean -ScheduledTaskDefinedBy.CLASS=Class -ScheduledTaskDefinedBy.SCRIPT=Script - -JmxInstance = Jmx Instance -JmxInstance.nodeName=Node Name -JmxInstance.address=JMX host:port -JmxInstance.login=Login -JmxInstance.password=Password - -LockDescriptor = Lock Descriptor -LockDescriptor.name = Name -LockDescriptor.timeout = Timeout, sec -LockDescriptor.timeoutSec = Timeout, sec - -Category.isDefault=Is Default -Category.special=Special -Category.categoryAttrs=Category Attributes -Category.localeNames = Localized values - -SendingAttachment = Sending Attachment -SendingAttachment.contentFile=Content of File -SendingAttachment.contentId=Identificator of Content -SendingAttachment.message=Message -SendingAttachment.content=Content -SendingAttachment.name=Name -SendingAttachment.encoding=Encoding -SendingAttachment.disposition=Disposition - -SendingMessage.contentTextFile=Content of File -SendingMessage.attachments=Attachments -SendingMessage.headers = Headers - -CategoryAttributeValue = Category Attribute Value -CategoryAttributeValue.date = Date -CategoryAttributeValue.code = Code -CategoryAttributeValue.entityId = Entity Id -CategoryAttributeValue.categoryAttribute = Category Attribute -CategoryAttributeValue.entityValue = Entity Value -CategoryAttributeValue.intValue = Int Value -CategoryAttributeValue.doubleValue = Double Value -CategoryAttributeValue.stringValue = String Value -CategoryAttributeValue.booleanValue = Boolean Value - -Config = Config -Config.name = Name -Config.value = Value - -Folder = Folder -Folder.name = Name -Folder.parent = Parent -Folder.tabName = Tab Name -Folder.sortOrder = Sort Order - -FtsQueue = Fts Queue -FtsQueue.entityName = Entity Name -FtsQueue.changeType = Change Type -FtsQueue.indexingHost = Indexing Host -FtsQueue.sourceHost = Source Host -FtsQueue.entityId = Entity Id -FtsQueue.fake = Fake - -LockDescriptorNameType.ENTITY = Entity -LockDescriptorNameType.CUSTOM = Custom - -ScreenProfilerEvent = Screen Profiler Event -ScreenProfilerEvent.eventTs = Event Time -ScreenProfilerEvent.screen = Screen -ScreenProfilerEvent.user = User -ScreenProfilerEvent.clientTime = Client Time, ms -ScreenProfilerEvent.clientTimeSec = Client Time, s -ScreenProfilerEvent.serverTime = Server Time, ms -ScreenProfilerEvent.serverTimeSec = Server Time, s -ScreenProfilerEvent.networkTime = Network Time, ms -ScreenProfilerEvent.networkTimeSec = Network Time, s -ScreenProfilerEvent.totalTime = Total Time, ms +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +AbstractNotPersistentEntity.id=ID + +BaseUuidEntity.id=ID +BaseIntegerIdEntity.id=ID +BaseLongIdEntity.id=ID +BaseIdentityIdEntity.id=ID + +StandardEntity.version=Version +StandardEntity.createTs=Created At +StandardEntity.createdBy=Created By +StandardEntity.updateTs=Updated At +StandardEntity.updatedBy=Updated By +StandardEntity.deleteTs=Deleted At +StandardEntity.deletedBy=Deleted By + +FileDescriptor=File +FileDescriptor.name=Name +FileDescriptor.createDate=Created At +FileDescriptor.extension=Extension +FileDescriptor.size=Size + +SendingMessage = Message +SendingMessage.version = Version +SendingMessage.updateTs = Last Attempt Time +SendingMessage.updatedBy = Updated By +SendingMessage.deleteTs = Deleted At +SendingMessage.deletedBy = Deleted By +SendingMessage.address = Address +SendingMessage.from = From +SendingMessage.contentText = Content +SendingMessage.deadline = Deadline +SendingMessage.status = Status +SendingMessage.dateSent = Sending Date +SendingMessage.attemptsCount = Attempt Limit +SendingMessage.attemptsMade = Attempts Made +SendingMessage.attachmentsName = Attachment Names +SendingMessage.caption = Caption + +Server=Server +Server.name=Name +Server.address=Address +Server.running=Running + +EntitySnapshot=Entity Snapshot +EntitySnapshot.author=Author +EntitySnapshot.changeDate=Change Date +EntitySnapshot.viewXml=View XML +EntitySnapshot.snapshotXml=Snapshot XML +EntitySnapshot.snapshotDate=Snapshot Date +EntitySnapshot.entityId=Entity Id +EntitySnapshot.label=Label + +EntityStatistics = Entity Statistics +EntityStatistics.lookupScreenThreshold = Lookup Screen Threshold +EntityStatistics.maxFetchUI = Max Fetch UI +EntityStatistics.instanceCount = Instance Count +EntityStatistics.name = Name +EntityStatistics.fetchUI = Fetch UI +EntityStatistics.lazyCollectionThreshold = Lazy Collection Threshold + +CategorizedEntity.category=Category + +Category=Category +Category.name=Name +Category.localeName=Localized name +Category.entityType=Entity type + +CategoryAttribute=Category Attribute +CategoryAttribute.name=Name +CategoryAttribute.code=Code +CategoryAttribute.dataType=Type +CategoryAttribute.defaultString=Default value +CategoryAttribute.defaultInt=Default value +CategoryAttribute.defaultDouble=Default value +CategoryAttribute.defaultBoolean=Default value +CategoryAttribute.defaultDate=Default value +CategoryAttribute.defaultEntityId=Default value +CategoryAttribute.required=Required attribute +CategoryAttribute.isCollection=Is collection +CategoryAttribute.screen=Entity selection screen +CategoryAttribute.category = Category +CategoryAttribute.categoryEntityType = Category entity type +CategoryAttribute.enumeration = Enumeration +CategoryAttribute.isEntity = Is entity +CategoryAttribute.orderNo = Order No +CategoryAttribute.lookup = Select with lookup field +CategoryAttribute.targetScreens = Target screens +CategoryAttribute.defaultDateIsCurrent = Default date is current +CategoryAttribute.width=Width +CategoryAttribute.rowsCount=Rows count +CategoryAttribute.joinClause=Join clause +CategoryAttribute.whereClause=Where clause +CategoryAttribute.localeName=Localized name +CategoryAttribute.localeNames=Localized name values +CategoryAttribute.enumerationLocale=Localized enumeration values +CategoryAttribute.enumerationLocales=All localized enumeration values + +ScheduledTask=Scheduled Task +ScheduledTask.beanName=Bean Name +ScheduledTask.methodName=Method Name +ScheduledTask.userName=User Name +ScheduledTask.userPassword=User Password +ScheduledTask.singleton=Singleton +ScheduledTask.active=Active +ScheduledTask.period=Period, sec +ScheduledTask.timeout=Timeout, sec +ScheduledTask.startDate = Start Date +ScheduledTask.timeFrame = Time Frame, sec +ScheduledTask.startDelay = Start Delay, sec +ScheduledTask.permittedServers = Permitted Servers +ScheduledTask.logStart = Log start +ScheduledTask.logFinish = Log finish +ScheduledTask.definedBy = Defined by +ScheduledTask.className = Class Name +ScheduledTask.scriptName = Script Name +ScheduledTask.description = Description +ScheduledTask.methodParametersString = Method Parameters +ScheduledTask.cron = Cron Expression +ScheduledTask.schedulingType=Scheduling Type +ScheduledTask.updatedBy = Updated By +ScheduledTask.lastStartTime = Last Start Time +ScheduledTask.deletedBy = Deleted By +ScheduledTask.updateTs = Updated At +ScheduledTask.lastStartServer = Server Last Start Time +ScheduledTask.deleteTs = Deleted At +ScheduledTask.methodParamsXml = XML + +SchedulingType.CRON=Cron +SchedulingType.PERIOD=Period +SchedulingType.FIXED_DELAY=Fixed Delay + +ScheduledExecution = Scheduled Execution +ScheduledExecution.task = Task +ScheduledExecution.server = Server +ScheduledExecution.startTime = Start Time +ScheduledExecution.finishTime = Finish Time +ScheduledExecution.durationSec = Duration, sec +ScheduledExecution.result = Result + +ScheduledTaskDefinedBy.BEAN=Bean +ScheduledTaskDefinedBy.CLASS=Class +ScheduledTaskDefinedBy.SCRIPT=Script + +JmxInstance = Jmx Instance +JmxInstance.nodeName=Node Name +JmxInstance.address=JMX host:port +JmxInstance.login=Login +JmxInstance.password=Password + +LockDescriptor = Lock Descriptor +LockDescriptor.name = Name +LockDescriptor.timeout = Timeout, sec +LockDescriptor.timeoutSec = Timeout, sec + +Category.isDefault=Is Default +Category.special=Special +Category.categoryAttrs=Category Attributes +Category.localeNames = Localized values + +SendingAttachment = Sending Attachment +SendingAttachment.contentFile=Content of File +SendingAttachment.contentId=Identificator of Content +SendingAttachment.message=Message +SendingAttachment.content=Content +SendingAttachment.name=Name +SendingAttachment.encoding=Encoding +SendingAttachment.disposition=Disposition + +SendingMessage.contentTextFile=Content of File +SendingMessage.attachments=Attachments +SendingMessage.headers = Headers + +CategoryAttributeValue = Category Attribute Value +CategoryAttributeValue.date = Date +CategoryAttributeValue.code = Code +CategoryAttributeValue.entityId = Entity Id +CategoryAttributeValue.categoryAttribute = Category Attribute +CategoryAttributeValue.entityValue = Entity Value +CategoryAttributeValue.intValue = Int Value +CategoryAttributeValue.doubleValue = Double Value +CategoryAttributeValue.stringValue = String Value +CategoryAttributeValue.booleanValue = Boolean Value + +Config = Config +Config.name = Name +Config.value = Value + +Folder = Folder +Folder.name = Name +Folder.parent = Parent +Folder.tabName = Tab Name +Folder.sortOrder = Sort Order + +FtsQueue = Fts Queue +FtsQueue.entityName = Entity Name +FtsQueue.changeType = Change Type +FtsQueue.indexingHost = Indexing Host +FtsQueue.sourceHost = Source Host +FtsQueue.entityId = Entity Id +FtsQueue.fake = Fake + +LockDescriptorNameType.ENTITY = Entity +LockDescriptorNameType.CUSTOM = Custom + +ScreenProfilerEvent = Screen Profiler Event +ScreenProfilerEvent.eventTs = Event Time +ScreenProfilerEvent.screen = Screen +ScreenProfilerEvent.user = User +ScreenProfilerEvent.clientTime = Client Time, ms +ScreenProfilerEvent.clientTimeSec = Client Time, s +ScreenProfilerEvent.serverTime = Server Time, ms +ScreenProfilerEvent.serverTimeSec = Server Time, s +ScreenProfilerEvent.networkTime = Network Time, ms +ScreenProfilerEvent.networkTimeSec = Network Time, s +ScreenProfilerEvent.totalTime = Total Time, ms ScreenProfilerEvent.totalTimeSec = Total Time, s \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/entity/messages_ru.properties b/modules/global/src/com/haulmont/cuba/core/entity/messages_ru.properties index 9b602cca07..44db03af63 100644 --- a/modules/global/src/com/haulmont/cuba/core/entity/messages_ru.properties +++ b/modules/global/src/com/haulmont/cuba/core/entity/messages_ru.properties @@ -1,231 +1,231 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -AbstractNotPersistentEntity.id=ID - -BaseUuidEntity.id=ID -BaseIntegerIdEntity.id=ID -BaseLongIdEntity.id=ID -BaseIdentityIdEntity.id=ID - -StandardEntity.version=Версия -StandardEntity.createTs=Дата создания -StandardEntity.createdBy=Создана кем -StandardEntity.updateTs=Дата изменения -StandardEntity.updatedBy=Изменена кем -StandardEntity.deleteTs=Дата удаления -StandardEntity.deletedBy=Удалена кем - -FileDescriptor=Файл -FileDescriptor.name=Имя -FileDescriptor.createDate=Дата создания -FileDescriptor.extension=Тип файла -FileDescriptor.size=Размер файла - -SendingMessage = Сообщение -SendingMessage.version = Версия -SendingMessage.updateTs = Время последней попытки -SendingMessage.updatedBy = Изменена кем -SendingMessage.deleteTs = Дата удаления -SendingMessage.deletedBy = Удалена кем -SendingMessage.address = Получатель -SendingMessage.from = Отправитель -SendingMessage.contentText = Тело сообщения -SendingMessage.deadline = Отправлять до -SendingMessage.status = Статус -SendingMessage.dateSent = Время отправки -SendingMessage.attemptsCount = Лимит попыток -SendingMessage.attemptsMade = Число попыток -SendingMessage.attachmentsName = Наименования вложений -SendingMessage.caption = Тема - -Server=Сервер -Server.name=Имя -Server.address=Адрес -Server.running=Работает - -EntitySnapshot=Снимок сущности -EntitySnapshot.author=Автор -EntitySnapshot.changeDate=Дата изменений -EntitySnapshot.viewXml=View XML -EntitySnapshot.snapshotXml=XML снимка -EntitySnapshot.snapshotDate=Дата создания снимка -EntitySnapshot.entityId=Id сущности -EntitySnapshot.label=Метка - -EntityStatistics =Статистика сущности -EntityStatistics.lookupScreenThreshold = Lookup Screen Threshold -EntityStatistics.maxFetchUI = Max Fetch UI -EntityStatistics.instanceCount = Instance Count -EntityStatistics.name = Name -EntityStatistics.fetchUI = Fetch UI -EntityStatistics.lazyCollectionThreshold = Lazy Collection Threshold - -CategorizedEntity.category=Категория - -Category=Категория -Category.name=Название -Category.localeName=Локализованное название -Category.entityType=Тип сущности - -CategoryAttribute=Атрибут категории -CategoryAttribute.name=Название -CategoryAttribute.code=Код -CategoryAttribute.dataType=Тип -CategoryAttribute.defaultString=Значение по умолчанию -CategoryAttribute.defaultInt=Значение по умолчанию -CategoryAttribute.defaultDouble=Значение по умолчанию -CategoryAttribute.defaultBoolean=Значение по умолчанию -CategoryAttribute.defaultDate=Значение по умолчанию -CategoryAttribute.defaultEntityId=Значение по умолчанию -CategoryAttribute.required=Обязательный атрибут -CategoryAttribute.isCollection=Коллекция -CategoryAttribute.screen=Экран выбора сущности -CategoryAttribute.category=Категория -CategoryAttribute.categoryEntityType = Тип категории -CategoryAttribute.enumeration=Перечисление -CategoryAttribute.isEntity=Сущность -CategoryAttribute.orderNo=Порядковый номер -CategoryAttribute.lookup=Выбирать в выпадающем списке -CategoryAttribute.targetScreens = Экраны -CategoryAttribute.defaultDateIsCurrent=Дата по умолчанию равна текущей -CategoryAttribute.width=Ширина -CategoryAttribute.rowsCount=Количество строк -CategoryAttribute.localeName=Локализованное название -CategoryAttribute.localeNames=Локализованные значения названия -CategoryAttribute.enumerationLocale=Локализованные значения перечисления -CategoryAttribute.enumerationLocales=Все локализованные значения перечисления - -ScheduledTask=Назначенное задание -ScheduledTask.beanName=Bean Name -ScheduledTask.methodName=Method Name -ScheduledTask.userName=User Name -ScheduledTask.userPassword=User Password -ScheduledTask.singleton=Singleton -ScheduledTask.active=Active -ScheduledTask.period=Period, sec -ScheduledTask.timeout=Timeout, sec -ScheduledTask.startDate = Start Date -ScheduledTask.timeFrame = Time Frame, sec -ScheduledTask.startDelay = Start Delay, sec -ScheduledTask.permittedServers = Permitted Servers -ScheduledTask.logStart = Log Start -ScheduledTask.logFinish = Log Finish -ScheduledTask.definedBy = Defined By -ScheduledTask.className = Class Name -ScheduledTask.scriptName = Script Name -ScheduledTask.description = Description -ScheduledTask.methodParametersString = Method Parameters -ScheduledTask.cron = Cron Expression -ScheduledTask.schedulingType=Scheduling Type -ScheduledTask.updatedBy = Изменено кем -ScheduledTask.lastStartTime = Дата последнего запуска -ScheduledTask.deletedBy = Удалено кем -ScheduledTask.updateTs = Дата изменения -ScheduledTask.lastStartServer = Дата последнего запуска сервера -ScheduledTask.deleteTs = Дата удаления -ScheduledTask.methodParamsXml = XML - -SchedulingType.CRON=Cron -SchedulingType.PERIOD=Period -SchedulingType.FIXED_DELAY=Fixed Delay - -ScheduledExecution = Выполнение задания -ScheduledExecution.task = Task -ScheduledExecution.server = Server -ScheduledExecution.startTime = Start time -ScheduledExecution.finishTime = Finish time -ScheduledExecution.durationSec = Duration, sec -ScheduledExecution.result = Result - -ScheduledTaskDefinedBy.BEAN=Bean -ScheduledTaskDefinedBy.CLASS=Class -ScheduledTaskDefinedBy.SCRIPT=Script - -JmxInstance = Экземпляр Jmx -JmxInstance.nodeName=Имя узла -JmxInstance.address=JMX хост:порт -JmxInstance.login=Логин -JmxInstance.password=Пароль - -LockDescriptor = Дескриптор блокировки -LockDescriptor.name = Наименование -LockDescriptor.timeout = Таймаут, сек -LockDescriptor.timeoutSec = Таймаут, сек - -Category.isDefault=По умолчанию -Category.special=Специальный -Category.categoryAttrs=Категория атрибутов -Category.localeNames = Локализованные значения - -SendingAttachment = Вложение -SendingAttachment.contentFile=Содержание файла -SendingAttachment.contentId=Идентификатор содержания -SendingAttachment.message=Сообщение -SendingAttachment.content=Содержание -SendingAttachment.name=Имя -SendingAttachment.encoding=Кодировка -SendingAttachment.disposition=Расположение - -SendingMessage.contentTextFile=Содержание файла -SendingMessage.attachments=Вложения -SendingMessage.headers = Заголовки - -CategoryAttributeValue = Значение атрибута категории -CategoryAttributeValue.date = Дата -CategoryAttributeValue.code = Код -CategoryAttributeValue.entityId = Id сущности -CategoryAttributeValue.categoryAttribute = Атрибут категории -CategoryAttributeValue.entityValue = Значение сущности -CategoryAttributeValue.intValue = Целочисленное значение -CategoryAttributeValue.doubleValue = Вещественное значение -CategoryAttributeValue.stringValue = Строковое значение -CategoryAttributeValue.booleanValue = Логическое значение - -Config = Конфигурация -Config.name = Название -Config.value = Значение - -Folder = Папка -Folder.name = Наименование -Folder.parent = Родительская папка -Folder.tabName = Заголовок окна -Folder.sortOrder = Порядковый номер - -FtsQueue = Очередь поиска -FtsQueue.entityName = Имя сущности -FtsQueue.changeType = Тип изменения -FtsQueue.indexingHost = Хост индексации -FtsQueue.sourceHost = Хост-источник -FtsQueue.entityId = Id сущности -FtsQueue.fake = Не настоящие - -LockDescriptorNameType.ENTITY = Сущности -LockDescriptorNameType.CUSTOM = Произвольная - -ScreenProfilerEvent = События профилировщика экранов -ScreenProfilerEvent.eventTs = Время события -ScreenProfilerEvent.screen = Экран -ScreenProfilerEvent.user = Пользователь -ScreenProfilerEvent.clientTime = Время на клиенте, мс -ScreenProfilerEvent.clientTimeSec = Время на клиенте, с -ScreenProfilerEvent.serverTime = Время на сервере, мс -ScreenProfilerEvent.serverTimeSec = Время на сервере, с -ScreenProfilerEvent.networkTime = Сетевое время, мс -ScreenProfilerEvent.networkTimeSec = Сетевое время, с -ScreenProfilerEvent.totalTime = Общее время, мс +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +AbstractNotPersistentEntity.id=ID + +BaseUuidEntity.id=ID +BaseIntegerIdEntity.id=ID +BaseLongIdEntity.id=ID +BaseIdentityIdEntity.id=ID + +StandardEntity.version=Версия +StandardEntity.createTs=Дата создания +StandardEntity.createdBy=Создана кем +StandardEntity.updateTs=Дата изменения +StandardEntity.updatedBy=Изменена кем +StandardEntity.deleteTs=Дата удаления +StandardEntity.deletedBy=Удалена кем + +FileDescriptor=Файл +FileDescriptor.name=Имя +FileDescriptor.createDate=Дата создания +FileDescriptor.extension=Тип файла +FileDescriptor.size=Размер файла + +SendingMessage = Сообщение +SendingMessage.version = Версия +SendingMessage.updateTs = Время последней попытки +SendingMessage.updatedBy = Изменена кем +SendingMessage.deleteTs = Дата удаления +SendingMessage.deletedBy = Удалена кем +SendingMessage.address = Получатель +SendingMessage.from = Отправитель +SendingMessage.contentText = Тело сообщения +SendingMessage.deadline = Отправлять до +SendingMessage.status = Статус +SendingMessage.dateSent = Время отправки +SendingMessage.attemptsCount = Лимит попыток +SendingMessage.attemptsMade = Число попыток +SendingMessage.attachmentsName = Наименования вложений +SendingMessage.caption = Тема + +Server=Сервер +Server.name=Имя +Server.address=Адрес +Server.running=Работает + +EntitySnapshot=Снимок сущности +EntitySnapshot.author=Автор +EntitySnapshot.changeDate=Дата изменений +EntitySnapshot.viewXml=View XML +EntitySnapshot.snapshotXml=XML снимка +EntitySnapshot.snapshotDate=Дата создания снимка +EntitySnapshot.entityId=Id сущности +EntitySnapshot.label=Метка + +EntityStatistics =Статистика сущности +EntityStatistics.lookupScreenThreshold = Lookup Screen Threshold +EntityStatistics.maxFetchUI = Max Fetch UI +EntityStatistics.instanceCount = Instance Count +EntityStatistics.name = Name +EntityStatistics.fetchUI = Fetch UI +EntityStatistics.lazyCollectionThreshold = Lazy Collection Threshold + +CategorizedEntity.category=Категория + +Category=Категория +Category.name=Название +Category.localeName=Локализованное название +Category.entityType=Тип сущности + +CategoryAttribute=Атрибут категории +CategoryAttribute.name=Название +CategoryAttribute.code=Код +CategoryAttribute.dataType=Тип +CategoryAttribute.defaultString=Значение по умолчанию +CategoryAttribute.defaultInt=Значение по умолчанию +CategoryAttribute.defaultDouble=Значение по умолчанию +CategoryAttribute.defaultBoolean=Значение по умолчанию +CategoryAttribute.defaultDate=Значение по умолчанию +CategoryAttribute.defaultEntityId=Значение по умолчанию +CategoryAttribute.required=Обязательный атрибут +CategoryAttribute.isCollection=Коллекция +CategoryAttribute.screen=Экран выбора сущности +CategoryAttribute.category=Категория +CategoryAttribute.categoryEntityType = Тип категории +CategoryAttribute.enumeration=Перечисление +CategoryAttribute.isEntity=Сущность +CategoryAttribute.orderNo=Порядковый номер +CategoryAttribute.lookup=Выбирать в выпадающем списке +CategoryAttribute.targetScreens = Экраны +CategoryAttribute.defaultDateIsCurrent=Дата по умолчанию равна текущей +CategoryAttribute.width=Ширина +CategoryAttribute.rowsCount=Количество строк +CategoryAttribute.localeName=Локализованное название +CategoryAttribute.localeNames=Локализованные значения названия +CategoryAttribute.enumerationLocale=Локализованные значения перечисления +CategoryAttribute.enumerationLocales=Все локализованные значения перечисления + +ScheduledTask=Назначенное задание +ScheduledTask.beanName=Bean Name +ScheduledTask.methodName=Method Name +ScheduledTask.userName=User Name +ScheduledTask.userPassword=User Password +ScheduledTask.singleton=Singleton +ScheduledTask.active=Active +ScheduledTask.period=Period, sec +ScheduledTask.timeout=Timeout, sec +ScheduledTask.startDate = Start Date +ScheduledTask.timeFrame = Time Frame, sec +ScheduledTask.startDelay = Start Delay, sec +ScheduledTask.permittedServers = Permitted Servers +ScheduledTask.logStart = Log Start +ScheduledTask.logFinish = Log Finish +ScheduledTask.definedBy = Defined By +ScheduledTask.className = Class Name +ScheduledTask.scriptName = Script Name +ScheduledTask.description = Description +ScheduledTask.methodParametersString = Method Parameters +ScheduledTask.cron = Cron Expression +ScheduledTask.schedulingType=Scheduling Type +ScheduledTask.updatedBy = Изменено кем +ScheduledTask.lastStartTime = Дата последнего запуска +ScheduledTask.deletedBy = Удалено кем +ScheduledTask.updateTs = Дата изменения +ScheduledTask.lastStartServer = Дата последнего запуска сервера +ScheduledTask.deleteTs = Дата удаления +ScheduledTask.methodParamsXml = XML + +SchedulingType.CRON=Cron +SchedulingType.PERIOD=Period +SchedulingType.FIXED_DELAY=Fixed Delay + +ScheduledExecution = Выполнение задания +ScheduledExecution.task = Task +ScheduledExecution.server = Server +ScheduledExecution.startTime = Start time +ScheduledExecution.finishTime = Finish time +ScheduledExecution.durationSec = Duration, sec +ScheduledExecution.result = Result + +ScheduledTaskDefinedBy.BEAN=Bean +ScheduledTaskDefinedBy.CLASS=Class +ScheduledTaskDefinedBy.SCRIPT=Script + +JmxInstance = Экземпляр Jmx +JmxInstance.nodeName=Имя узла +JmxInstance.address=JMX хост:порт +JmxInstance.login=Логин +JmxInstance.password=Пароль + +LockDescriptor = Дескриптор блокировки +LockDescriptor.name = Наименование +LockDescriptor.timeout = Таймаут, сек +LockDescriptor.timeoutSec = Таймаут, сек + +Category.isDefault=По умолчанию +Category.special=Специальный +Category.categoryAttrs=Категория атрибутов +Category.localeNames = Локализованные значения + +SendingAttachment = Вложение +SendingAttachment.contentFile=Содержание файла +SendingAttachment.contentId=Идентификатор содержания +SendingAttachment.message=Сообщение +SendingAttachment.content=Содержание +SendingAttachment.name=Имя +SendingAttachment.encoding=Кодировка +SendingAttachment.disposition=Расположение + +SendingMessage.contentTextFile=Содержание файла +SendingMessage.attachments=Вложения +SendingMessage.headers = Заголовки + +CategoryAttributeValue = Значение атрибута категории +CategoryAttributeValue.date = Дата +CategoryAttributeValue.code = Код +CategoryAttributeValue.entityId = Id сущности +CategoryAttributeValue.categoryAttribute = Атрибут категории +CategoryAttributeValue.entityValue = Значение сущности +CategoryAttributeValue.intValue = Целочисленное значение +CategoryAttributeValue.doubleValue = Вещественное значение +CategoryAttributeValue.stringValue = Строковое значение +CategoryAttributeValue.booleanValue = Логическое значение + +Config = Конфигурация +Config.name = Название +Config.value = Значение + +Folder = Папка +Folder.name = Наименование +Folder.parent = Родительская папка +Folder.tabName = Заголовок окна +Folder.sortOrder = Порядковый номер + +FtsQueue = Очередь поиска +FtsQueue.entityName = Имя сущности +FtsQueue.changeType = Тип изменения +FtsQueue.indexingHost = Хост индексации +FtsQueue.sourceHost = Хост-источник +FtsQueue.entityId = Id сущности +FtsQueue.fake = Не настоящие + +LockDescriptorNameType.ENTITY = Сущности +LockDescriptorNameType.CUSTOM = Произвольная + +ScreenProfilerEvent = События профилировщика экранов +ScreenProfilerEvent.eventTs = Время события +ScreenProfilerEvent.screen = Экран +ScreenProfilerEvent.user = Пользователь +ScreenProfilerEvent.clientTime = Время на клиенте, мс +ScreenProfilerEvent.clientTimeSec = Время на клиенте, с +ScreenProfilerEvent.serverTime = Время на сервере, мс +ScreenProfilerEvent.serverTimeSec = Время на сервере, с +ScreenProfilerEvent.networkTime = Сетевое время, мс +ScreenProfilerEvent.networkTimeSec = Сетевое время, с +ScreenProfilerEvent.totalTime = Общее время, мс ScreenProfilerEvent.totalTimeSec = Общее время, с \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/AccessDeniedException.java b/modules/global/src/com/haulmont/cuba/core/global/AccessDeniedException.java index 99ddb98a1a..1923e5e04b 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/AccessDeniedException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/AccessDeniedException.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.security.entity.PermissionType; - -/** - * Exception that is raised on attempt to violate a security constraint. - * - * - */ -@SupportedByClient -@Logging(Logging.Type.BRIEF) -public class AccessDeniedException extends RuntimeException -{ - private static final long serialVersionUID = -3097861878301424338L; - - private PermissionType type; - - private String target; - - public AccessDeniedException(PermissionType type, String target) { - super(type.toString() + " " + target); - this.type = type; - this.target = target; - } - - public PermissionType getType() { - return type; - } - - public String getTarget() { - return target; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.security.entity.PermissionType; + +/** + * Exception that is raised on attempt to violate a security constraint. + * + * + */ +@SupportedByClient +@Logging(Logging.Type.BRIEF) +public class AccessDeniedException extends RuntimeException +{ + private static final long serialVersionUID = -3097861878301424338L; + + private PermissionType type; + + private String target; + + public AccessDeniedException(PermissionType type, String target) { + super(type.toString() + " " + target); + this.type = type; + this.target = target; + } + + public PermissionType getType() { + return type; + } + + public String getTarget() { + return target; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/ClientType.java b/modules/global/src/com/haulmont/cuba/core/global/ClientType.java index 3d04e21a18..b65f299e0b 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/ClientType.java +++ b/modules/global/src/com/haulmont/cuba/core/global/ClientType.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -public enum ClientType { - WEB("W", "web"), - PORTAL("P", "portal"), - DESKTOP("D", "desktop"), - REST_API("R", "rest"); - - private String id; - private String configPath; - - ClientType(String id, String configPath) { - this.id = id; - this.configPath = configPath; - } - - public String getId() { - return id; - } - - public String getConfigPath() { - return configPath; - } - - public static ClientType fromId(String id) { - if ("W".equals(id)) { - return WEB; - } else if ("D".equals(id)) { - return DESKTOP; - } else if ("P".equals(id)) { - return PORTAL; - } else { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +public enum ClientType { + WEB("W", "web"), + PORTAL("P", "portal"), + DESKTOP("D", "desktop"), + REST_API("R", "rest"); + + private String id; + private String configPath; + + ClientType(String id, String configPath) { + this.id = id; + this.configPath = configPath; + } + + public String getId() { + return id; + } + + public String getConfigPath() { + return configPath; + } + + public static ClientType fromId(String id) { + if ("W".equals(id)) { + return WEB; + } else if ("D".equals(id)) { + return DESKTOP; + } else if ("P".equals(id)) { + return PORTAL; + } else { + return null; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/CommitContext.java b/modules/global/src/com/haulmont/cuba/core/global/CommitContext.java index d559c540ca..8178ca3fe3 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/CommitContext.java +++ b/modules/global/src/com/haulmont/cuba/core/global/CommitContext.java @@ -1,196 +1,196 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.entity.Entity; - -import javax.annotation.Nullable; -import java.io.Serializable; -import java.util.*; - -/** - * DTO that contains information about currently committed entities. - *
Used by {@link com.haulmont.cuba.core.app.DataService} - */ -@SuppressWarnings("unchecked") -public class CommitContext implements Serializable { - - private static final long serialVersionUID = 2510011302544968537L; - - protected Collection commitInstances = new LinkedHashSet<>(); - protected Collection removeInstances = new LinkedHashSet<>(); - - protected Map views = new HashMap<>(); - - protected boolean softDeletion = true; - protected boolean discardCommitted; - protected Map dbHints = new HashMap<>(); - - /** - * @param commitInstances changed entities to be committed to the database - */ - public CommitContext(Entity... commitInstances) { - this.commitInstances.addAll(Arrays.asList(commitInstances)); - } - - /** - * @param commitInstances collection of changed entities to be committed to the database - */ - public CommitContext(Collection commitInstances) { - this.commitInstances.addAll(commitInstances); - } - - /** - * @param commitInstances collection of changed entities to be committed to the database - * @param removeInstances collection of entities to be removed from the database - */ - public CommitContext(Collection commitInstances, Collection removeInstances) { - this.commitInstances.addAll(commitInstances); - this.removeInstances.addAll(removeInstances); - } - - /** - * Adds an entity to be committed to the database. - * - * @param entity entity instance - * @return this instance for chaining - */ - public CommitContext addInstanceToCommit(Entity entity) { - commitInstances.add(entity); - return this; - } - - /** - * Adds an entity to be committed to the database. - * - * @param entity entity instance - * @param view view which is used in merge operation to ensure all required attributes are loaded in the returned instance - * @return this instance for chaining - */ - public CommitContext addInstanceToCommit(Entity entity, @Nullable View view) { - commitInstances.add(entity); - if (view != null) - views.put(entity, view); - return this; - } - - /** - * Adds an entity to be committed to the database. - * - * @param entity entity instance - * @param viewName view which is used in merge operation to ensure all required attributes are loaded in the returned instance - * @return this instance for chaining - */ - public CommitContext addInstanceToCommit(Entity entity, @Nullable String viewName) { - commitInstances.add(entity); - if (viewName != null) { - views.put(entity, getViewFromRepository(entity, viewName)); - } - return this; - } - - /** - * Adds an entity to be removed from the database. - * - * @param entity entity instance - * @return this instance for chaining - */ - public CommitContext addInstanceToRemove(Entity entity) { - removeInstances.add(entity); - return this; - } - - /** - * @return direct reference to collection of changed entities that will be committed to the database. - * The collection is modifiable. - */ - public Collection getCommitInstances() { - return commitInstances; - } - - /** - * @param commitInstances collection of changed entities that will be committed to the database - */ - public void setCommitInstances(Collection commitInstances) { - this.commitInstances = commitInstances; - } - - /** - * @return direct reference to collection of entities that will be removed from the database. - * The collection is modifiable. - */ - public Collection getRemoveInstances() { - return removeInstances; - } - - /** - * @param removeInstances collection of entities to be removed from the database - */ - public void setRemoveInstances(Collection removeInstances) { - this.removeInstances = removeInstances; - } - - /** - * Enables defining a view for each committed entity. These views are used in merge operation to ensure all - * required attributes are loaded in returned instances. - * - * @return editable map of entities to their views - */ - public Map getViews() { - return views; - } - - /** - * @return custom hints which can be used later during query construction - */ - public Map getDbHints() { - return dbHints; - } - - /** - * @return whether to use soft deletion for this commit - */ - public boolean isSoftDeletion() { - return softDeletion; - } - - /** - * @param softDeletion whether to use soft deletion for this commit - */ - public void setSoftDeletion(boolean softDeletion) { - this.softDeletion = softDeletion; - } - - /** - * @return true if calling code does not need committed instances, which allows for performance optimization - */ - public boolean isDiscardCommitted() { - return discardCommitted; - } - - /** - * Set to true if calling code does not need committed instances, which allows for performance optimization. - */ - public void setDiscardCommitted(boolean discardCommitted) { - this.discardCommitted = discardCommitted; - } - - private View getViewFromRepository(Entity entity, String viewName) { - Metadata metadata = AppBeans.get(Metadata.NAME); - return metadata.getViewRepository().getView(metadata.getClass(entity.getClass()), viewName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.entity.Entity; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.*; + +/** + * DTO that contains information about currently committed entities. + *
Used by {@link com.haulmont.cuba.core.app.DataService} + */ +@SuppressWarnings("unchecked") +public class CommitContext implements Serializable { + + private static final long serialVersionUID = 2510011302544968537L; + + protected Collection commitInstances = new LinkedHashSet<>(); + protected Collection removeInstances = new LinkedHashSet<>(); + + protected Map views = new HashMap<>(); + + protected boolean softDeletion = true; + protected boolean discardCommitted; + protected Map dbHints = new HashMap<>(); + + /** + * @param commitInstances changed entities to be committed to the database + */ + public CommitContext(Entity... commitInstances) { + this.commitInstances.addAll(Arrays.asList(commitInstances)); + } + + /** + * @param commitInstances collection of changed entities to be committed to the database + */ + public CommitContext(Collection commitInstances) { + this.commitInstances.addAll(commitInstances); + } + + /** + * @param commitInstances collection of changed entities to be committed to the database + * @param removeInstances collection of entities to be removed from the database + */ + public CommitContext(Collection commitInstances, Collection removeInstances) { + this.commitInstances.addAll(commitInstances); + this.removeInstances.addAll(removeInstances); + } + + /** + * Adds an entity to be committed to the database. + * + * @param entity entity instance + * @return this instance for chaining + */ + public CommitContext addInstanceToCommit(Entity entity) { + commitInstances.add(entity); + return this; + } + + /** + * Adds an entity to be committed to the database. + * + * @param entity entity instance + * @param view view which is used in merge operation to ensure all required attributes are loaded in the returned instance + * @return this instance for chaining + */ + public CommitContext addInstanceToCommit(Entity entity, @Nullable View view) { + commitInstances.add(entity); + if (view != null) + views.put(entity, view); + return this; + } + + /** + * Adds an entity to be committed to the database. + * + * @param entity entity instance + * @param viewName view which is used in merge operation to ensure all required attributes are loaded in the returned instance + * @return this instance for chaining + */ + public CommitContext addInstanceToCommit(Entity entity, @Nullable String viewName) { + commitInstances.add(entity); + if (viewName != null) { + views.put(entity, getViewFromRepository(entity, viewName)); + } + return this; + } + + /** + * Adds an entity to be removed from the database. + * + * @param entity entity instance + * @return this instance for chaining + */ + public CommitContext addInstanceToRemove(Entity entity) { + removeInstances.add(entity); + return this; + } + + /** + * @return direct reference to collection of changed entities that will be committed to the database. + * The collection is modifiable. + */ + public Collection getCommitInstances() { + return commitInstances; + } + + /** + * @param commitInstances collection of changed entities that will be committed to the database + */ + public void setCommitInstances(Collection commitInstances) { + this.commitInstances = commitInstances; + } + + /** + * @return direct reference to collection of entities that will be removed from the database. + * The collection is modifiable. + */ + public Collection getRemoveInstances() { + return removeInstances; + } + + /** + * @param removeInstances collection of entities to be removed from the database + */ + public void setRemoveInstances(Collection removeInstances) { + this.removeInstances = removeInstances; + } + + /** + * Enables defining a view for each committed entity. These views are used in merge operation to ensure all + * required attributes are loaded in returned instances. + * + * @return editable map of entities to their views + */ + public Map getViews() { + return views; + } + + /** + * @return custom hints which can be used later during query construction + */ + public Map getDbHints() { + return dbHints; + } + + /** + * @return whether to use soft deletion for this commit + */ + public boolean isSoftDeletion() { + return softDeletion; + } + + /** + * @param softDeletion whether to use soft deletion for this commit + */ + public void setSoftDeletion(boolean softDeletion) { + this.softDeletion = softDeletion; + } + + /** + * @return true if calling code does not need committed instances, which allows for performance optimization + */ + public boolean isDiscardCommitted() { + return discardCommitted; + } + + /** + * Set to true if calling code does not need committed instances, which allows for performance optimization. + */ + public void setDiscardCommitted(boolean discardCommitted) { + this.discardCommitted = discardCommitted; + } + + private View getViewFromRepository(Entity entity, String viewName) { + Metadata metadata = AppBeans.get(Metadata.NAME); + return metadata.getViewRepository().getView(metadata.getClass(entity.getClass()), viewName); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/DeletePolicy.java b/modules/global/src/com/haulmont/cuba/core/global/DeletePolicy.java index ec8e65f5d5..911e9e225e 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/DeletePolicy.java +++ b/modules/global/src/com/haulmont/cuba/core/global/DeletePolicy.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -/** - * This enum defines a behaviour to deal with linked objects in case of soft delete
- *

    - *
  • DENY - throw {@link DeletePolicyException} when linked object exists - *
  • CASCADE - soft delete the linked object - *
  • UNLINK - remove link - *
- * - */ -public enum DeletePolicy { - DENY, - CASCADE, - UNLINK +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +/** + * This enum defines a behaviour to deal with linked objects in case of soft delete
+ *
    + *
  • DENY - throw {@link DeletePolicyException} when linked object exists + *
  • CASCADE - soft delete the linked object + *
  • UNLINK - remove link + *
+ * + */ +public enum DeletePolicy { + DENY, + CASCADE, + UNLINK } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/DeletePolicyException.java b/modules/global/src/com/haulmont/cuba/core/global/DeletePolicyException.java index c57a4a9cc6..8be68c8949 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/DeletePolicyException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/DeletePolicyException.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -/** - * Exception that is raised on attempt to soft delete an object, - * which has linked objects marked with {@link com.haulmont.cuba.core.entity.annotation.OnDelete} annotation - * with {@link com.haulmont.cuba.core.global.DeletePolicy#DENY} value. - * - */ -public class DeletePolicyException extends RuntimeException { - - private static final long serialVersionUID = -1359432367630173077L; - - private String entity; - private String refEntity; - - public static final String ERR_MESSAGE = "Unable to delete %s because there are references from %s"; - - public DeletePolicyException(String entity, String refEntity) { - super(String.format(ERR_MESSAGE, entity, refEntity)); - this.entity = entity; - this.refEntity = refEntity; - } - - public String getEntity() { - return entity; - } - - public String getRefEntity() { - return refEntity; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +/** + * Exception that is raised on attempt to soft delete an object, + * which has linked objects marked with {@link com.haulmont.cuba.core.entity.annotation.OnDelete} annotation + * with {@link com.haulmont.cuba.core.global.DeletePolicy#DENY} value. + * + */ +public class DeletePolicyException extends RuntimeException { + + private static final long serialVersionUID = -1359432367630173077L; + + private String entity; + private String refEntity; + + public static final String ERR_MESSAGE = "Unable to delete %s because there are references from %s"; + + public DeletePolicyException(String entity, String refEntity) { + super(String.format(ERR_MESSAGE, entity, refEntity)); + this.entity = entity; + this.refEntity = refEntity; + } + + public String getEntity() { + return entity; + } + + public String getRefEntity() { + return refEntity; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/DesignSupport.java b/modules/global/src/com/haulmont/cuba/core/global/DesignSupport.java index 16a0b49ca4..07936a026e 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/DesignSupport.java +++ b/modules/global/src/com/haulmont/cuba/core/global/DesignSupport.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotates code containing additional information for external tools - * - */ -@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, - ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.TYPE_PARAMETER}) -@Retention(RetentionPolicy.SOURCE) -public @interface DesignSupport { - - /** - * @return additional information - */ - String value() default ""; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates code containing additional information for external tools + * + */ +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, + ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.TYPE_PARAMETER}) +@Retention(RetentionPolicy.SOURCE) +public @interface DesignSupport { + + /** + * @return additional information + */ + String value() default ""; +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EmailAttachment.java b/modules/global/src/com/haulmont/cuba/core/global/EmailAttachment.java index 5bb171faf0..f633eb1089 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EmailAttachment.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EmailAttachment.java @@ -1,99 +1,99 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import javax.annotation.Nullable; -import javax.mail.Part; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; - -/** - * @see EmailInfo - * @see com.haulmont.cuba.core.app.EmailService - */ -public class EmailAttachment implements Serializable { - private static final long serialVersionUID = 8201729520638588939L; - - private final byte[] data; - private final String name; - - private final String contentId; - - /** - * @see Part#INLINE - * @see Part#ATTACHMENT - */ - private final String disposition; - - /** - * UTF-8 is the default if not specified. - */ - private final String encoding; - - /** - * Create file attachment. - */ - public EmailAttachment(byte[] data, String name) { - this(data, name, null, Part.ATTACHMENT, null); - } - - /** - * Create inline attachment (e.g. image embedded into html). - */ - public EmailAttachment(byte[] data, String name, String contentId) { - this(data, name, contentId, Part.INLINE, null); - } - - public EmailAttachment(byte[] data, String name, @Nullable String contentId, String disposition, - @Nullable String encoding) { - this.data = data; - this.name = name; - this.contentId = contentId; - this.disposition = disposition; - this.encoding = encoding; - } - - public byte[] getData() { - return data; - } - - public String getName() { - return name; - } - - public String getContentId() { - return contentId; - } - - public String getDisposition() { - return disposition; - } - - public String getEncoding() { - return encoding; - } - - public static EmailAttachment createTextAttachment(String text, String encoding, String name) { - byte[] data; - try { - data = text.getBytes(encoding); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - return new EmailAttachment(data, name, null, Part.ATTACHMENT, encoding); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import javax.annotation.Nullable; +import javax.mail.Part; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; + +/** + * @see EmailInfo + * @see com.haulmont.cuba.core.app.EmailService + */ +public class EmailAttachment implements Serializable { + private static final long serialVersionUID = 8201729520638588939L; + + private final byte[] data; + private final String name; + + private final String contentId; + + /** + * @see Part#INLINE + * @see Part#ATTACHMENT + */ + private final String disposition; + + /** + * UTF-8 is the default if not specified. + */ + private final String encoding; + + /** + * Create file attachment. + */ + public EmailAttachment(byte[] data, String name) { + this(data, name, null, Part.ATTACHMENT, null); + } + + /** + * Create inline attachment (e.g. image embedded into html). + */ + public EmailAttachment(byte[] data, String name, String contentId) { + this(data, name, contentId, Part.INLINE, null); + } + + public EmailAttachment(byte[] data, String name, @Nullable String contentId, String disposition, + @Nullable String encoding) { + this.data = data; + this.name = name; + this.contentId = contentId; + this.disposition = disposition; + this.encoding = encoding; + } + + public byte[] getData() { + return data; + } + + public String getName() { + return name; + } + + public String getContentId() { + return contentId; + } + + public String getDisposition() { + return disposition; + } + + public String getEncoding() { + return encoding; + } + + public static EmailAttachment createTextAttachment(String text, String encoding, String name) { + byte[] data; + try { + data = text.getBytes(encoding); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + return new EmailAttachment(data, name, null, Part.ATTACHMENT, encoding); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EmailException.java b/modules/global/src/com/haulmont/cuba/core/global/EmailException.java index b5acb9b48f..855d549e10 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EmailException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EmailException.java @@ -1,58 +1,58 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import java.util.List; - -/** - * Email sending error.
- * Contains failed addresses and corresponding error messages. - */ -@SupportedByClient -public class EmailException extends Exception { - - private static final long serialVersionUID = -9129158384759856382L; - private final List failedAddresses; - /** - * List of error messages which prevented email to be sent. - */ - private final List messages; - - public EmailException(List failedAddresses, List messages) { - if (failedAddresses == null || messages == null || failedAddresses.size() != messages.size()) - throw new IllegalArgumentException(); - - this.failedAddresses = failedAddresses; - this.messages = messages; - } - - public List getFailedAddresses() { - return failedAddresses; - } - - public List getMessages() { - return messages; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < failedAddresses.size(); i++) { - sb.append(failedAddresses.get(i)).append(" : ").append(messages.get(i)).append("\n"); - } - return sb.toString(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import java.util.List; + +/** + * Email sending error.
+ * Contains failed addresses and corresponding error messages. + */ +@SupportedByClient +public class EmailException extends Exception { + + private static final long serialVersionUID = -9129158384759856382L; + private final List failedAddresses; + /** + * List of error messages which prevented email to be sent. + */ + private final List messages; + + public EmailException(List failedAddresses, List messages) { + if (failedAddresses == null || messages == null || failedAddresses.size() != messages.size()) + throw new IllegalArgumentException(); + + this.failedAddresses = failedAddresses; + this.messages = messages; + } + + public List getFailedAddresses() { + return failedAddresses; + } + + public List getMessages() { + return messages; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < failedAddresses.size(); i++) { + sb.append(failedAddresses.get(i)).append(" : ").append(messages.get(i)).append("\n"); + } + return sb.toString(); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EmailHeader.java b/modules/global/src/com/haulmont/cuba/core/global/EmailHeader.java index 6a42b00cec..27d0c88620 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EmailHeader.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EmailHeader.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import javax.annotation.Nullable; -import java.io.Serializable; - -/** - * The EmailHeader class stores a name/value pair to represent headers. - * - */ -public class EmailHeader implements Serializable { - - private static final long serialVersionUID = 2750666832862630139L; - private static final String SEPARATOR = ":"; - /** - * The name of the header. - */ - protected String name; - - /** - * The value of the header. - */ - protected String value; - - /** - * Construct a EmailHeader object. - * - * @param name name of the header - * @param value value of the header - */ - public EmailHeader(String name, String value) { - this.name = name; - this.value = value; - } - - /** - * Returns instance of EmailHeader object from String argument. - * @param line EmailHeader name and value separated with ":" symbol. - * @return Instance of EmailHeader object. Returns {@code null} if string has wrong format or {@code null} value. - */ - @Nullable - public static EmailHeader parse(@Nullable String line) { - if (line == null) - return null; - String[] values = line.split(SEPARATOR); - if (values.length == 2) { - String name = values[0].trim(); - String value = values[1].trim(); - return new EmailHeader(name, value); - } - return null; - } - - /** - * Returns the name of this header. - * - * @return name of the header - */ - public String getName() { - return name; - } - - /** - * Returns the value of this header. - * - * @return value of the header - */ - public String getValue() { - return value; - } - - @Override - public String toString() { - return String.format("%s%s %s", this.getName(), SEPARATOR, this.getValue()); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import javax.annotation.Nullable; +import java.io.Serializable; + +/** + * The EmailHeader class stores a name/value pair to represent headers. + * + */ +public class EmailHeader implements Serializable { + + private static final long serialVersionUID = 2750666832862630139L; + private static final String SEPARATOR = ":"; + /** + * The name of the header. + */ + protected String name; + + /** + * The value of the header. + */ + protected String value; + + /** + * Construct a EmailHeader object. + * + * @param name name of the header + * @param value value of the header + */ + public EmailHeader(String name, String value) { + this.name = name; + this.value = value; + } + + /** + * Returns instance of EmailHeader object from String argument. + * @param line EmailHeader name and value separated with ":" symbol. + * @return Instance of EmailHeader object. Returns {@code null} if string has wrong format or {@code null} value. + */ + @Nullable + public static EmailHeader parse(@Nullable String line) { + if (line == null) + return null; + String[] values = line.split(SEPARATOR); + if (values.length == 2) { + String name = values[0].trim(); + String value = values[1].trim(); + return new EmailHeader(name, value); + } + return null; + } + + /** + * Returns the name of this header. + * + * @return name of the header + */ + public String getName() { + return name; + } + + /** + * Returns the value of this header. + * + * @return value of the header + */ + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.format("%s%s %s", this.getName(), SEPARATOR, this.getValue()); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EmailInfo.java b/modules/global/src/com/haulmont/cuba/core/global/EmailInfo.java index 68370ea112..84d3e6bccf 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EmailInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EmailInfo.java @@ -1,193 +1,193 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import javax.annotation.Nullable; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Contains email details: list of recipients, from address, caption, body and attachments. - * See constructors for more information. - * - * @see com.haulmont.cuba.core.app.EmailService - */ -public class EmailInfo implements Serializable { - - private static final long serialVersionUID = -382773435130109083L; - - /** - * Recipient email addresses separated with "," or ";" symbol. - */ - private String addresses; - private String caption; - private String from; - private String templatePath; - private Map templateParameters; - private String body; - private EmailAttachment[] attachments; - private List headers; - - /** - * Constructor. Example usage: - *
-     *     EmailInfo emailInfo = new EmailInfo(
-                "john.doe@company.com,jane.roe@company.com",
-                "Company news",
-                "do-not-reply@company.com",
-                "com/company/sample/email_templates/news.txt",
-                Collections.singletonMap("some_var", some_value)
-            );
-     * 
- * - * @param addresses comma or semicolon separated list of addresses - * @param caption email subject - * @param from "from" address. If null, a default provided by {@code cuba.email.fromAddress} app property is used. - * @param templatePath path to a Freemarker template which is used to create the message body. The template - * is loaded through {@link Resources} in the core module. - * @param templateParameters map of parameters to be passed to the template - * @param attachments email attachments. Omit this parameter if there are no attachments. - */ - public EmailInfo(String addresses, String caption, @Nullable String from, String templatePath, - Map templateParameters, EmailAttachment... attachments) { - this.addresses = addresses; - this.caption = caption; - this.templatePath = templatePath; - this.attachments = attachments; - this.templateParameters = templateParameters; - this.from = from; - } - - /** - * Constructor. - *
-     *     EmailInfo emailInfo = new EmailInfo(
-                "john.doe@company.com,jane.roe@company.com",
-                "Company news",
-                null,
-                "Some content"
-            );
-     * 
- * - * @param addresses comma or semicolon separated list of addresses - * @param caption email subject - * @param from "from" address. If null, a default provided by {@code cuba.email.fromAddress} app property is used. - * @param body email body - * @param attachments email attachments. Omit this parameter if there are no attachments. - */ - public EmailInfo(String addresses, String caption, @Nullable String from, String body, EmailAttachment... attachments) { - this.addresses = addresses; - this.caption = caption; - this.body = body; - this.attachments = attachments; - this.from = from; - } - - /** - * Constructor. The "from" address is taken from the {@code cuba.email.fromAddress} app property. - *
-     *     EmailInfo emailInfo = new EmailInfo(
-                "john.doe@company.com,jane.roe@company.com",
-                "Company news",
-                "Some content"
-            );
-     * 
- * - * @param addresses comma or semicolon separated list of addresses - * @param caption email subject - * @param body email body - */ - public EmailInfo(String addresses, String caption, String body) { - this.addresses = addresses; - this.caption = caption; - this.body = body; - } - - - public String getAddresses() { - return addresses; - } - - public void setAddresses(String addresses) { - this.addresses = addresses; - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } - - public String getTemplatePath() { - return templatePath; - } - - public void setTemplatePath(String templatePath) { - this.templatePath = templatePath; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - public EmailAttachment[] getAttachments() { - return attachments; - } - - public void setAttachments(EmailAttachment[] attachments) { - this.attachments = attachments; - } - - public Map getTemplateParameters() { - return templateParameters; - } - - public void setTemplateParameters(Map templateParameters) { - this.templateParameters = templateParameters; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public List getHeaders() { - return headers; - } - - public void setHeaders(List headers) { - this.headers = headers; - } - - public void addHeader(String name, String value) { - if (this.headers == null) - this.headers = new ArrayList<>(); - this.headers.add(new EmailHeader(name, value)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Contains email details: list of recipients, from address, caption, body and attachments. + * See constructors for more information. + * + * @see com.haulmont.cuba.core.app.EmailService + */ +public class EmailInfo implements Serializable { + + private static final long serialVersionUID = -382773435130109083L; + + /** + * Recipient email addresses separated with "," or ";" symbol. + */ + private String addresses; + private String caption; + private String from; + private String templatePath; + private Map templateParameters; + private String body; + private EmailAttachment[] attachments; + private List headers; + + /** + * Constructor. Example usage: + *
+     *     EmailInfo emailInfo = new EmailInfo(
+                "john.doe@company.com,jane.roe@company.com",
+                "Company news",
+                "do-not-reply@company.com",
+                "com/company/sample/email_templates/news.txt",
+                Collections.singletonMap("some_var", some_value)
+            );
+     * 
+ * + * @param addresses comma or semicolon separated list of addresses + * @param caption email subject + * @param from "from" address. If null, a default provided by {@code cuba.email.fromAddress} app property is used. + * @param templatePath path to a Freemarker template which is used to create the message body. The template + * is loaded through {@link Resources} in the core module. + * @param templateParameters map of parameters to be passed to the template + * @param attachments email attachments. Omit this parameter if there are no attachments. + */ + public EmailInfo(String addresses, String caption, @Nullable String from, String templatePath, + Map templateParameters, EmailAttachment... attachments) { + this.addresses = addresses; + this.caption = caption; + this.templatePath = templatePath; + this.attachments = attachments; + this.templateParameters = templateParameters; + this.from = from; + } + + /** + * Constructor. + *
+     *     EmailInfo emailInfo = new EmailInfo(
+                "john.doe@company.com,jane.roe@company.com",
+                "Company news",
+                null,
+                "Some content"
+            );
+     * 
+ * + * @param addresses comma or semicolon separated list of addresses + * @param caption email subject + * @param from "from" address. If null, a default provided by {@code cuba.email.fromAddress} app property is used. + * @param body email body + * @param attachments email attachments. Omit this parameter if there are no attachments. + */ + public EmailInfo(String addresses, String caption, @Nullable String from, String body, EmailAttachment... attachments) { + this.addresses = addresses; + this.caption = caption; + this.body = body; + this.attachments = attachments; + this.from = from; + } + + /** + * Constructor. The "from" address is taken from the {@code cuba.email.fromAddress} app property. + *
+     *     EmailInfo emailInfo = new EmailInfo(
+                "john.doe@company.com,jane.roe@company.com",
+                "Company news",
+                "Some content"
+            );
+     * 
+ * + * @param addresses comma or semicolon separated list of addresses + * @param caption email subject + * @param body email body + */ + public EmailInfo(String addresses, String caption, String body) { + this.addresses = addresses; + this.caption = caption; + this.body = body; + } + + + public String getAddresses() { + return addresses; + } + + public void setAddresses(String addresses) { + this.addresses = addresses; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public String getTemplatePath() { + return templatePath; + } + + public void setTemplatePath(String templatePath) { + this.templatePath = templatePath; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public EmailAttachment[] getAttachments() { + return attachments; + } + + public void setAttachments(EmailAttachment[] attachments) { + this.attachments = attachments; + } + + public Map getTemplateParameters() { + return templateParameters; + } + + public void setTemplateParameters(Map templateParameters) { + this.templateParameters = templateParameters; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public List getHeaders() { + return headers; + } + + public void setHeaders(List headers) { + this.headers = headers; + } + + public void addHeader(String name, String value) { + if (this.headers == null) + this.headers = new ArrayList<>(); + this.headers.add(new EmailHeader(name, value)); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/EntityAccessException.java b/modules/global/src/com/haulmont/cuba/core/global/EntityAccessException.java index fbde645235..ad9dd9c9da 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EntityAccessException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EntityAccessException.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.MetaClass; - -/** - * This exception is raised on attempt to load a deleted object. - */ -public class EntityAccessException extends RuntimeException { - public static final String ERR_MESSAGE_1 = "Unable to load entity "; - public static final String ERR_MESSAGE_2 = "because it has been deleted or access denied"; - - public EntityAccessException() { - super(ERR_MESSAGE_1 + ERR_MESSAGE_2); - } - - public EntityAccessException(Class entityClass, Object entityId) { - super(ERR_MESSAGE_1 + getEntityName(entityClass) + "-" + entityId + " " + ERR_MESSAGE_2); - } - - public EntityAccessException(MetaClass metaClass, Object entityId) { - super(ERR_MESSAGE_1 + metaClass.getName() + "-" + entityId + " " + ERR_MESSAGE_2); - } - - protected static String getEntityName(Class entityClass) { - MetaClass metaClass = AppBeans.get(Metadata.class).getClass(entityClass); - return metaClass != null ? metaClass.getName() : ""; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.MetaClass; + +/** + * This exception is raised on attempt to load a deleted object. + */ +public class EntityAccessException extends RuntimeException { + public static final String ERR_MESSAGE_1 = "Unable to load entity "; + public static final String ERR_MESSAGE_2 = "because it has been deleted or access denied"; + + public EntityAccessException() { + super(ERR_MESSAGE_1 + ERR_MESSAGE_2); + } + + public EntityAccessException(Class entityClass, Object entityId) { + super(ERR_MESSAGE_1 + getEntityName(entityClass) + "-" + entityId + " " + ERR_MESSAGE_2); + } + + public EntityAccessException(MetaClass metaClass, Object entityId) { + super(ERR_MESSAGE_1 + metaClass.getName() + "-" + entityId + " " + ERR_MESSAGE_2); + } + + protected static String getEntityName(Class entityClass) { + MetaClass metaClass = AppBeans.get(Metadata.class).getClass(entityClass); + return metaClass != null ? metaClass.getName() : ""; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EntityAttributeVisitor.java b/modules/global/src/com/haulmont/cuba/core/global/EntityAttributeVisitor.java index 8c7107a8e2..3a6389fd75 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EntityAttributeVisitor.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EntityAttributeVisitor.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Visitor to be submitted to {@link MetadataTools#traverseAttributes(Entity, EntityAttributeVisitor)}. - * - */ -public interface EntityAttributeVisitor { - - /** - * Visits an entity attribute. - * - * @param entity entity instance - * @param property meta-property pointing to the visited attribute - */ - void visit(Entity entity, MetaProperty property); - - /** - * Optionally indicates, whether the property has to be visited - * @param property meta-property that is about to be visited - * @return false if the property has to be visited - */ - default boolean skip(MetaProperty property) { - return false; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Visitor to be submitted to {@link MetadataTools#traverseAttributes(Entity, EntityAttributeVisitor)}. + * + */ +public interface EntityAttributeVisitor { + + /** + * Visits an entity attribute. + * + * @param entity entity instance + * @param property meta-property pointing to the visited attribute + */ + void visit(Entity entity, MetaProperty property); + + /** + * Optionally indicates, whether the property has to be visited + * @param property meta-property that is about to be visited + * @return false if the property has to be visited + */ + default boolean skip(MetaProperty property) { + return false; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/EntityLoadInfo.java b/modules/global/src/com/haulmont/cuba/core/global/EntityLoadInfo.java index d0b24417e6..84fbe88066 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/EntityLoadInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/global/EntityLoadInfo.java @@ -1,121 +1,121 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; - -import javax.annotation.Nullable; - -/** - * Class that encapsulates an information needed to load an entity instance. - *
- * This information has the following string representation: - * {@code metaclassName-id[-viewName]}, e.g.: - *
- * sec$User-60885987-1b61-4247-94c7-dff348347f93
- * sec$Role-0c018061-b26f-4de2-a5be-dff348347f93-role.browse
- * ref$Seller-101
- * ref$Currency-{usd}
- * 
- *
viewName part is optional. - *
id part should be: - *
    - *
  • For UUID keys: canonical UUID representation with 5 groups of hex digits delimited by dashes
  • - *
  • For numeric keys: decimal representation of the number
  • - *
  • For string keys: the key surrounded by curly brackets, e.g {mykey}
  • - *
- * Use {@link EntityLoadInfoBuilder#parse(String)} and {@link #toString()} methods to convert from/to a string. - */ -public class EntityLoadInfo { - - public static final String NEW_PREFIX = "NEW-"; - - private MetaClass metaClass; - private Object id; - private String viewName; - private boolean newEntity; - private boolean stringKey; - - protected EntityLoadInfo(Object id, MetaClass metaClass, String viewName, boolean stringKey) { - this(id, metaClass, viewName, stringKey, false); - } - - protected EntityLoadInfo(Object id, MetaClass metaClass, String viewName, boolean stringKey, boolean newEntity) { - this.id = id; - this.metaClass = metaClass; - this.viewName = viewName; - this.newEntity = newEntity; - this.stringKey = stringKey; - } - - public Object getId() { - return id; - } - - public MetaClass getMetaClass() { - return metaClass; - } - - @Nullable - public String getViewName() { - return viewName; - } - - public boolean isNewEntity() { - return newEntity; - } - - /** - * Create a new info instance. - *

Consider using {@link EntityLoadInfoBuilder} for better performance.

- * @param entity entity instance - * @param viewName view name, can be null - * @return info instance - */ - public static EntityLoadInfo create(Entity entity, @Nullable String viewName) { - EntityLoadInfoBuilder builder = AppBeans.get(EntityLoadInfoBuilder.NAME); - return builder.create(entity, viewName); - } - - /** - * Create a new info instance with empty view name. - *

Consider using {@link EntityLoadInfoBuilder} for better performance.

- * @param entity entity instance - * @return info instance - */ - public static EntityLoadInfo create(Entity entity) { - return create(entity, null); - } - - /** - * Parse an info from the string. - *

Consider using {@link EntityLoadInfoBuilder} for better performance.

- * @param str string representation of the info - * @return info instance or null if the string can not be parsed. Any exception is silently swallowed. - */ - public static @Nullable EntityLoadInfo parse(String str) { - EntityLoadInfoBuilder builder = AppBeans.get(EntityLoadInfoBuilder.NAME); - return builder.parse(str); - } - - @Override - public String toString() { - String key = stringKey ? "{" + id + "}" : id.toString(); - return metaClass.getName() + "-" + key + (viewName == null ? "" : "-" + viewName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; + +import javax.annotation.Nullable; + +/** + * Class that encapsulates an information needed to load an entity instance. + *
+ * This information has the following string representation: + * {@code metaclassName-id[-viewName]}, e.g.: + *
+ * sec$User-60885987-1b61-4247-94c7-dff348347f93
+ * sec$Role-0c018061-b26f-4de2-a5be-dff348347f93-role.browse
+ * ref$Seller-101
+ * ref$Currency-{usd}
+ * 
+ *
viewName part is optional. + *
id part should be: + *
    + *
  • For UUID keys: canonical UUID representation with 5 groups of hex digits delimited by dashes
  • + *
  • For numeric keys: decimal representation of the number
  • + *
  • For string keys: the key surrounded by curly brackets, e.g {mykey}
  • + *
+ * Use {@link EntityLoadInfoBuilder#parse(String)} and {@link #toString()} methods to convert from/to a string. + */ +public class EntityLoadInfo { + + public static final String NEW_PREFIX = "NEW-"; + + private MetaClass metaClass; + private Object id; + private String viewName; + private boolean newEntity; + private boolean stringKey; + + protected EntityLoadInfo(Object id, MetaClass metaClass, String viewName, boolean stringKey) { + this(id, metaClass, viewName, stringKey, false); + } + + protected EntityLoadInfo(Object id, MetaClass metaClass, String viewName, boolean stringKey, boolean newEntity) { + this.id = id; + this.metaClass = metaClass; + this.viewName = viewName; + this.newEntity = newEntity; + this.stringKey = stringKey; + } + + public Object getId() { + return id; + } + + public MetaClass getMetaClass() { + return metaClass; + } + + @Nullable + public String getViewName() { + return viewName; + } + + public boolean isNewEntity() { + return newEntity; + } + + /** + * Create a new info instance. + *

Consider using {@link EntityLoadInfoBuilder} for better performance.

+ * @param entity entity instance + * @param viewName view name, can be null + * @return info instance + */ + public static EntityLoadInfo create(Entity entity, @Nullable String viewName) { + EntityLoadInfoBuilder builder = AppBeans.get(EntityLoadInfoBuilder.NAME); + return builder.create(entity, viewName); + } + + /** + * Create a new info instance with empty view name. + *

Consider using {@link EntityLoadInfoBuilder} for better performance.

+ * @param entity entity instance + * @return info instance + */ + public static EntityLoadInfo create(Entity entity) { + return create(entity, null); + } + + /** + * Parse an info from the string. + *

Consider using {@link EntityLoadInfoBuilder} for better performance.

+ * @param str string representation of the info + * @return info instance or null if the string can not be parsed. Any exception is silently swallowed. + */ + public static @Nullable EntityLoadInfo parse(String str) { + EntityLoadInfoBuilder builder = AppBeans.get(EntityLoadInfoBuilder.NAME); + return builder.parse(str); + } + + @Override + public String toString() { + String key = stringKey ? "{" + id + "}" : id.toString(); + return metaClass.getName() + "-" + key + (viewName == null ? "" : "-" + viewName); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/FetchMode.java b/modules/global/src/com/haulmont/cuba/core/global/FetchMode.java index e3492fd162..adaedcfda8 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/FetchMode.java +++ b/modules/global/src/com/haulmont/cuba/core/global/FetchMode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -/** - * Specifies how to fetch a referenced entity from the database. - * - */ -public enum FetchMode { - /** - * The platform will choose an optimal mode - */ - AUTO, - - /** - * Fetching will be performed according to JPA rules, which effectively means loading by a separate select - */ - UNDEFINED, - - /** - * Fetching in the same select by joining with referenced table - */ - JOIN, - - /** - * Fetching by one separate select for all referenced entities - */ - BATCH -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +/** + * Specifies how to fetch a referenced entity from the database. + * + */ +public enum FetchMode { + /** + * The platform will choose an optimal mode + */ + AUTO, + + /** + * Fetching will be performed according to JPA rules, which effectively means loading by a separate select + */ + UNDEFINED, + + /** + * Fetching in the same select by joining with referenced table + */ + JOIN, + + /** + * Fetching by one separate select for all referenced entities + */ + BATCH +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/FileStorageException.java b/modules/global/src/com/haulmont/cuba/core/global/FileStorageException.java index 4756a953b9..b84a8a37db 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/FileStorageException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/FileStorageException.java @@ -1,77 +1,77 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import javax.annotation.Nullable; - -@SupportedByClient -public class FileStorageException extends Exception { - - public enum Type { - IO_EXCEPTION("I/O error", 500), - FILE_ALREADY_EXISTS("File already exists", 500), - FILE_NOT_FOUND("File not found", 404), - MORE_THAN_ONE_FILE("More than one file with this name exists", 500), - STORAGE_INACCESSIBLE("Can not get access to the storage", 503); - - private String message; - - private int httpStatus; - - Type(String message, int httpStatus) { - this.message = message; - this.httpStatus = httpStatus; - } - - public String getMessage() { - return message; - } - - public int getHttpStatus() { - return httpStatus; - } - - public static Type fromHttpStatus(int status) { - for (Type type : values()) { - if (type.getHttpStatus() == status) - return type; - } - return IO_EXCEPTION; - } - } - - private Type type; - private String fileName; - - public FileStorageException(Type type, String fileName) { - this(type, fileName, null); - } - - public FileStorageException(Type type, String fileName, @Nullable Throwable cause) { - super(type.getMessage() + ": " + fileName, cause); - this.type = type; - this.fileName = fileName; - } - - public String getFileName() { - return fileName; - } - - public Type getType() { - return type; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import javax.annotation.Nullable; + +@SupportedByClient +public class FileStorageException extends Exception { + + public enum Type { + IO_EXCEPTION("I/O error", 500), + FILE_ALREADY_EXISTS("File already exists", 500), + FILE_NOT_FOUND("File not found", 404), + MORE_THAN_ONE_FILE("More than one file with this name exists", 500), + STORAGE_INACCESSIBLE("Can not get access to the storage", 503); + + private String message; + + private int httpStatus; + + Type(String message, int httpStatus) { + this.message = message; + this.httpStatus = httpStatus; + } + + public String getMessage() { + return message; + } + + public int getHttpStatus() { + return httpStatus; + } + + public static Type fromHttpStatus(int status) { + for (Type type : values()) { + if (type.getHttpStatus() == status) + return type; + } + return IO_EXCEPTION; + } + } + + private Type type; + private String fileName; + + public FileStorageException(Type type, String fileName) { + this(type, fileName, null); + } + + public FileStorageException(Type type, String fileName, @Nullable Throwable cause) { + super(type.getMessage() + ": " + fileName, cause); + this.type = type; + this.fileName = fileName; + } + + public String getFileName() { + return fileName; + } + + public Type getType() { + return type; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/FileTypesHelper.java b/modules/global/src/com/haulmont/cuba/core/global/FileTypesHelper.java index 620bea7654..446b60ee30 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/FileTypesHelper.java +++ b/modules/global/src/com/haulmont/cuba/core/global/FileTypesHelper.java @@ -1,318 +1,318 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; - -public class FileTypesHelper { - - /** - * Default mime-type. - */ - public static final String DEFAULT_MIME_TYPE = "application/octet-stream"; - - private static final String initialExtToMIMEMap = "application/vnd.ms-word.document.macroEnabled.12 docm," - + "application/vnd.openxmlformats-officedocument.wordprocessingml.document docx," - + "application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx," - + "application/vnd.ms-powerpoint.template.macroEnabled.12 potm," - + "application/vnd.openxmlformats-officedocument.presentationml.template potx," - + "application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam," - + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12 ppsm," - + "application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx," - + "application/vnd.ms-powerpoint.presentation.macroEnabled.12 pptm," - + "application/vnd.openxmlformats-officedocument.presentationml.presentation pptx," - + "application/vnd.ms-excel.addin.macroEnabled.12 xlam," - + "application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb," - + "application/vnd.ms-excel.sheet.macroEnabled.12 xlsm," - + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx," - + "application/vnd.ms-excel.template.macroEnabled.12 xltm," - + "application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx," - + "application/cu-seeme csm cu," - + "application/dsptype tsp," - + "application/futuresplash spl," - + "application/mac-binhex40 hqx," - + "application/msaccess mdb," - + "application/msword doc dot," - + "application/octet-stream bin," - + "application/oda oda," - + "application/pdf pdf," - + "application/pgp-signature pgp," - + "application/postscript ps ai eps," - + "application/rtf rtf," - + "application/vnd.ms-excel xls xlb," - + "application/vnd.ms-powerpoint ppt pps pot," - + "application/vnd.wap.wmlc wmlc," - + "application/vnd.wap.wmlscriptc wmlsc," - + "application/wordperfect5.1 wp5," - + "application/zip zip," - + "application/x-123 wk," - + "application/x-bcpio bcpio," - + "application/x-chess-pgn pgn," - + "application/x-cpio cpio," - + "application/x-debian-package deb," - + "application/x-director dcr dir dxr," - + "application/x-dms dms," - + "application/x-dvi dvi," - + "application/x-xfig fig," - + "application/x-font pfa pfb gsf pcf pcf.Z," - + "application/x-gnumeric gnumeric," - + "application/x-gtar gtar tgz taz," - + "application/x-hdf hdf," - + "application/x-httpd-php phtml pht php," - + "application/x-httpd-php3 php3," - + "application/x-httpd-php3-source phps," - + "application/x-httpd-php3-preprocessed php3p," - + "application/x-httpd-php4 php4," - + "application/x-ica ica," - + "application/x-java-archive jar," - + "application/x-java-serialized-object ser," - + "application/x-java-vm class," - + "application/x-javascript js," - + "application/x-kchart chrt," - + "application/x-killustrator kil," - + "application/x-kpresenter kpr kpt," - + "application/x-kspread ksp," - + "application/x-kword kwd kwt," - + "application/x-latex latex," - + "application/x-lha lha," - + "application/x-lzh lzh," - + "application/x-lzx lzx," - + "application/x-maker frm maker frame fm fb book fbdoc," - + "application/x-mif mif," - + "application/x-msdos-program com exe bat dll," - + "application/x-msi msi," - + "application/x-netcdf nc cdf," - + "application/x-ns-proxy-autoconfig pac," - + "application/x-object o," - + "application/x-ogg ogg," - + "application/x-oz-application oza," - + "application/x-perl pl pm," - + "application/x-pkcs7-crl crl," - + "application/x-redhat-package-manager rpm," - + "application/x-shar shar," - + "application/x-shockwave-flash swf swfl," - + "application/x-star-office sdd sda," - + "application/x-stuffit sit," - + "application/x-sv4cpio sv4cpio," - + "application/x-sv4crc sv4crc," - + "application/x-tar tar," - + "application/x-tex-gf gf," - + "application/x-tex-pk pk PK," - + "application/x-texinfo texinfo texi," - + "application/x-trash ~ % bak old sik," - + "application/x-troff t tr roff," - + "application/x-troff-man man," - + "application/x-troff-me me," - + "application/x-troff-ms ms," - + "application/x-ustar ustar," - + "application/x-wais-source src," - + "application/x-wingz wz," - + "application/x-x509-ca-cert crt," - + "audio/basic au snd," - + "audio/midi mid midi," - + "audio/mpeg mpga mpega mp2 mp3," - + "audio/mpegurl m3u," - + "audio/prs.sid sid," - + "audio/x-aiff aif aiff aifc," - + "audio/x-gsm gsm," - + "audio/x-pn-realaudio ra rm ram," - + "audio/x-scpls pls," - + "audio/x-wav wav," - + "image/bmp bmp bm," - + "image/gif gif," - + "image/ief ief," - + "image/jpeg jpeg jpg jpe," - + "image/pcx pcx," - + "image/png png," - + "image/svg+xml svg," - + "image/tiff tiff tif," - + "image/vnd.wap.wbmp wbmp," - + "image/x-cmu-raster ras," - + "image/x-coreldraw cdr," - + "image/x-coreldrawpattern pat," - + "image/x-coreldrawtemplate cdt," - + "image/x-corelphotopaint cpt," - + "image/x-jng jng," - + "image/x-portable-anymap pnm," - + "image/x-portable-bitmap pbm," - + "image/x-portable-graymap pgm," - + "image/x-portable-pixmap ppm," - + "image/x-rgb rgb," - + "image/x-xbitmap xbm," - + "image/x-xpixmap xpm," - + "image/x-xwindowdump xwd," - + "text/comma-separated-values csv," - + "text/css css," - + "text/html htm html xhtml," - + "text/mathml mml," - + "text/plain txt text diff," - + "text/richtext rtx," - + "text/tab-separated-values tsv," - + "text/vnd.wap.wml wml," - + "text/vnd.wap.wmlscript wmls," - + "text/xml xml," - + "text/x-c++hdr h++ hpp hxx hh," - + "text/x-c++src c++ cpp cxx cc," - + "text/x-chdr h," - + "text/x-csh csh," - + "text/x-csrc c," - + "text/x-java java," - + "text/x-moc moc," - + "text/x-pascal p pas," - + "text/x-setext etx," - + "text/x-sh sh," - + "text/x-tcl tcl tk," - + "text/x-tex tex ltx sty cls," - + "text/x-vcalendar vcs," - + "text/x-vcard vcf," - + "video/dl dl," - + "video/fli fli," - + "video/gl gl," - + "video/mpeg mpeg mpg mpe," - + "video/quicktime qt mov," - + "video/x-mng mng," - + "video/x-ms-asf asf asx," - + "video/x-msvideo avi," - + "video/x-sgi-movie movie," - + "x-world/x-vrml vrm vrml wrl," - + "application/vnd.oasis.opendocument.text odt," - + "application/vnd.oasis.opendocument.text-template ott," - + "application/vnd.oasis.opendocument.graphics odg," - + "application/vnd.oasis.opendocument.graphics-template otg," - + "application/vnd.oasis.opendocument.presentation odp," - + "application/vnd.oasis.opendocument.presentation-template otp," - + "application/vnd.oasis.opendocument.spreadsheet ods," - + "application/vnd.oasis.opendocument.spreadsheet-template ots," - + "application/vnd.oasis.opendocument.chart odc," - + "application/vnd.oasis.opendocument.chart-template otc," - + "application/vnd.oasis.opendocument.image odi," - + "application/vnd.oasis.opendocument.image-template oti," - + "application/vnd.oasis.opendocument.formula odf," - + "application/vnd.oasis.opendocument.formula-template otf," - + "application/vnd.oasis.opendocument.text-master odm," - + "application/vnd.oasis.opendocument.text-web oth"; - - /** - * File extension to MIME type mapping. - */ - private static Map extToMIMEMap = new HashMap<>(); - - static { - // Initialize extension to MIME map - final StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap, - ","); - while (lines.hasMoreTokens()) { - final String line = lines.nextToken(); - final StringTokenizer exts = new StringTokenizer(line); - final String type = exts.nextToken(); - while (exts.hasMoreTokens()) { - final String ext = exts.nextToken(); - addExtension(ext, type); - } - } - } - - /** - * Gets the mime-type of a file. Currently the mime-type is resolved based - * only on the file name extension. - * - * @param fileName - * the name of the file whose mime-type is requested. - * @return mime-type String for the given filename - */ - public static String getMIMEType(String fileName) { - - // Checks for nulls - if (fileName == null) { - throw new NullPointerException("Filename can not be null"); - } - - // Calculates the extension of the file - int dotIndex = fileName.lastIndexOf("."); - if (dotIndex > -1) { - final String ext = StringUtils.substring(fileName, dotIndex + 1).toLowerCase(); - - // Return type from extension map, if found - final String type = extToMIMEMap.get(ext); - if (type != null) { - return type; - } - } - - return DEFAULT_MIME_TYPE; - } - - /** - * Gets the mime-type for a file. Currently the returned file type is - * resolved by the filename extension only. - * - * @param file - * the file whose mime-type is requested. - * @return the files mime-type String - */ - public static String getMIMEType(File file) { - - // Checks for nulls - if (file == null) { - throw new NullPointerException("File can not be null"); - } - - // Directories - if (file.isDirectory()) { - // Drives - if (file.getParentFile() == null) { - return "inode/drive"; - } else { - return "inode/directory"; - } - } - - // Return type from extension - return getMIMEType(file.getName()); - } - - /** - * Adds a mime-type mapping for the given filename extension. If the - * extension is already in the internal mapping it is overwritten. - * - * @param extension - * the filename extension to be associated with - * MIMEType. - * @param MIMEType - * the new mime-type for extension. - */ - public static void addExtension(String extension, String MIMEType) { - extToMIMEMap.put(extension, MIMEType); - } - - /** - * Gets the internal file extension to mime-type mapping. - * - * @return unmodifiable map containing the current file extension to - * mime-type mapping - */ - public static Map getExtensionToMIMETypeMapping() { - return Collections.unmodifiableMap(extToMIMEMap); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import org.apache.commons.lang.StringUtils; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +public class FileTypesHelper { + + /** + * Default mime-type. + */ + public static final String DEFAULT_MIME_TYPE = "application/octet-stream"; + + private static final String initialExtToMIMEMap = "application/vnd.ms-word.document.macroEnabled.12 docm," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.document docx," + + "application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx," + + "application/vnd.ms-powerpoint.template.macroEnabled.12 potm," + + "application/vnd.openxmlformats-officedocument.presentationml.template potx," + + "application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam," + + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12 ppsm," + + "application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx," + + "application/vnd.ms-powerpoint.presentation.macroEnabled.12 pptm," + + "application/vnd.openxmlformats-officedocument.presentationml.presentation pptx," + + "application/vnd.ms-excel.addin.macroEnabled.12 xlam," + + "application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb," + + "application/vnd.ms-excel.sheet.macroEnabled.12 xlsm," + + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx," + + "application/vnd.ms-excel.template.macroEnabled.12 xltm," + + "application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx," + + "application/cu-seeme csm cu," + + "application/dsptype tsp," + + "application/futuresplash spl," + + "application/mac-binhex40 hqx," + + "application/msaccess mdb," + + "application/msword doc dot," + + "application/octet-stream bin," + + "application/oda oda," + + "application/pdf pdf," + + "application/pgp-signature pgp," + + "application/postscript ps ai eps," + + "application/rtf rtf," + + "application/vnd.ms-excel xls xlb," + + "application/vnd.ms-powerpoint ppt pps pot," + + "application/vnd.wap.wmlc wmlc," + + "application/vnd.wap.wmlscriptc wmlsc," + + "application/wordperfect5.1 wp5," + + "application/zip zip," + + "application/x-123 wk," + + "application/x-bcpio bcpio," + + "application/x-chess-pgn pgn," + + "application/x-cpio cpio," + + "application/x-debian-package deb," + + "application/x-director dcr dir dxr," + + "application/x-dms dms," + + "application/x-dvi dvi," + + "application/x-xfig fig," + + "application/x-font pfa pfb gsf pcf pcf.Z," + + "application/x-gnumeric gnumeric," + + "application/x-gtar gtar tgz taz," + + "application/x-hdf hdf," + + "application/x-httpd-php phtml pht php," + + "application/x-httpd-php3 php3," + + "application/x-httpd-php3-source phps," + + "application/x-httpd-php3-preprocessed php3p," + + "application/x-httpd-php4 php4," + + "application/x-ica ica," + + "application/x-java-archive jar," + + "application/x-java-serialized-object ser," + + "application/x-java-vm class," + + "application/x-javascript js," + + "application/x-kchart chrt," + + "application/x-killustrator kil," + + "application/x-kpresenter kpr kpt," + + "application/x-kspread ksp," + + "application/x-kword kwd kwt," + + "application/x-latex latex," + + "application/x-lha lha," + + "application/x-lzh lzh," + + "application/x-lzx lzx," + + "application/x-maker frm maker frame fm fb book fbdoc," + + "application/x-mif mif," + + "application/x-msdos-program com exe bat dll," + + "application/x-msi msi," + + "application/x-netcdf nc cdf," + + "application/x-ns-proxy-autoconfig pac," + + "application/x-object o," + + "application/x-ogg ogg," + + "application/x-oz-application oza," + + "application/x-perl pl pm," + + "application/x-pkcs7-crl crl," + + "application/x-redhat-package-manager rpm," + + "application/x-shar shar," + + "application/x-shockwave-flash swf swfl," + + "application/x-star-office sdd sda," + + "application/x-stuffit sit," + + "application/x-sv4cpio sv4cpio," + + "application/x-sv4crc sv4crc," + + "application/x-tar tar," + + "application/x-tex-gf gf," + + "application/x-tex-pk pk PK," + + "application/x-texinfo texinfo texi," + + "application/x-trash ~ % bak old sik," + + "application/x-troff t tr roff," + + "application/x-troff-man man," + + "application/x-troff-me me," + + "application/x-troff-ms ms," + + "application/x-ustar ustar," + + "application/x-wais-source src," + + "application/x-wingz wz," + + "application/x-x509-ca-cert crt," + + "audio/basic au snd," + + "audio/midi mid midi," + + "audio/mpeg mpga mpega mp2 mp3," + + "audio/mpegurl m3u," + + "audio/prs.sid sid," + + "audio/x-aiff aif aiff aifc," + + "audio/x-gsm gsm," + + "audio/x-pn-realaudio ra rm ram," + + "audio/x-scpls pls," + + "audio/x-wav wav," + + "image/bmp bmp bm," + + "image/gif gif," + + "image/ief ief," + + "image/jpeg jpeg jpg jpe," + + "image/pcx pcx," + + "image/png png," + + "image/svg+xml svg," + + "image/tiff tiff tif," + + "image/vnd.wap.wbmp wbmp," + + "image/x-cmu-raster ras," + + "image/x-coreldraw cdr," + + "image/x-coreldrawpattern pat," + + "image/x-coreldrawtemplate cdt," + + "image/x-corelphotopaint cpt," + + "image/x-jng jng," + + "image/x-portable-anymap pnm," + + "image/x-portable-bitmap pbm," + + "image/x-portable-graymap pgm," + + "image/x-portable-pixmap ppm," + + "image/x-rgb rgb," + + "image/x-xbitmap xbm," + + "image/x-xpixmap xpm," + + "image/x-xwindowdump xwd," + + "text/comma-separated-values csv," + + "text/css css," + + "text/html htm html xhtml," + + "text/mathml mml," + + "text/plain txt text diff," + + "text/richtext rtx," + + "text/tab-separated-values tsv," + + "text/vnd.wap.wml wml," + + "text/vnd.wap.wmlscript wmls," + + "text/xml xml," + + "text/x-c++hdr h++ hpp hxx hh," + + "text/x-c++src c++ cpp cxx cc," + + "text/x-chdr h," + + "text/x-csh csh," + + "text/x-csrc c," + + "text/x-java java," + + "text/x-moc moc," + + "text/x-pascal p pas," + + "text/x-setext etx," + + "text/x-sh sh," + + "text/x-tcl tcl tk," + + "text/x-tex tex ltx sty cls," + + "text/x-vcalendar vcs," + + "text/x-vcard vcf," + + "video/dl dl," + + "video/fli fli," + + "video/gl gl," + + "video/mpeg mpeg mpg mpe," + + "video/quicktime qt mov," + + "video/x-mng mng," + + "video/x-ms-asf asf asx," + + "video/x-msvideo avi," + + "video/x-sgi-movie movie," + + "x-world/x-vrml vrm vrml wrl," + + "application/vnd.oasis.opendocument.text odt," + + "application/vnd.oasis.opendocument.text-template ott," + + "application/vnd.oasis.opendocument.graphics odg," + + "application/vnd.oasis.opendocument.graphics-template otg," + + "application/vnd.oasis.opendocument.presentation odp," + + "application/vnd.oasis.opendocument.presentation-template otp," + + "application/vnd.oasis.opendocument.spreadsheet ods," + + "application/vnd.oasis.opendocument.spreadsheet-template ots," + + "application/vnd.oasis.opendocument.chart odc," + + "application/vnd.oasis.opendocument.chart-template otc," + + "application/vnd.oasis.opendocument.image odi," + + "application/vnd.oasis.opendocument.image-template oti," + + "application/vnd.oasis.opendocument.formula odf," + + "application/vnd.oasis.opendocument.formula-template otf," + + "application/vnd.oasis.opendocument.text-master odm," + + "application/vnd.oasis.opendocument.text-web oth"; + + /** + * File extension to MIME type mapping. + */ + private static Map extToMIMEMap = new HashMap<>(); + + static { + // Initialize extension to MIME map + final StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap, + ","); + while (lines.hasMoreTokens()) { + final String line = lines.nextToken(); + final StringTokenizer exts = new StringTokenizer(line); + final String type = exts.nextToken(); + while (exts.hasMoreTokens()) { + final String ext = exts.nextToken(); + addExtension(ext, type); + } + } + } + + /** + * Gets the mime-type of a file. Currently the mime-type is resolved based + * only on the file name extension. + * + * @param fileName + * the name of the file whose mime-type is requested. + * @return mime-type String for the given filename + */ + public static String getMIMEType(String fileName) { + + // Checks for nulls + if (fileName == null) { + throw new NullPointerException("Filename can not be null"); + } + + // Calculates the extension of the file + int dotIndex = fileName.lastIndexOf("."); + if (dotIndex > -1) { + final String ext = StringUtils.substring(fileName, dotIndex + 1).toLowerCase(); + + // Return type from extension map, if found + final String type = extToMIMEMap.get(ext); + if (type != null) { + return type; + } + } + + return DEFAULT_MIME_TYPE; + } + + /** + * Gets the mime-type for a file. Currently the returned file type is + * resolved by the filename extension only. + * + * @param file + * the file whose mime-type is requested. + * @return the files mime-type String + */ + public static String getMIMEType(File file) { + + // Checks for nulls + if (file == null) { + throw new NullPointerException("File can not be null"); + } + + // Directories + if (file.isDirectory()) { + // Drives + if (file.getParentFile() == null) { + return "inode/drive"; + } else { + return "inode/directory"; + } + } + + // Return type from extension + return getMIMEType(file.getName()); + } + + /** + * Adds a mime-type mapping for the given filename extension. If the + * extension is already in the internal mapping it is overwritten. + * + * @param extension + * the filename extension to be associated with + * MIMEType. + * @param MIMEType + * the new mime-type for extension. + */ + public static void addExtension(String extension, String MIMEType) { + extToMIMEMap.put(extension, MIMEType); + } + + /** + * Gets the internal file extension to mime-type mapping. + * + * @return unmodifiable map containing the current file extension to + * mime-type mapping + */ + public static Map getExtensionToMIMETypeMapping() { + return Collections.unmodifiableMap(extToMIMEMap); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/GlobalConfig.java b/modules/global/src/com/haulmont/cuba/core/global/GlobalConfig.java index bbe9d061e0..b1e4203cfa 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/GlobalConfig.java +++ b/modules/global/src/com/haulmont/cuba/core/global/GlobalConfig.java @@ -1,221 +1,221 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.config.Config; -import com.haulmont.cuba.core.config.Property; -import com.haulmont.cuba.core.config.Source; -import com.haulmont.cuba.core.config.SourceType; -import com.haulmont.cuba.core.config.defaults.Default; -import com.haulmont.cuba.core.config.defaults.DefaultBoolean; -import com.haulmont.cuba.core.config.defaults.DefaultInt; -import com.haulmont.cuba.core.config.defaults.DefaultString; -import com.haulmont.cuba.core.config.type.Factory; -import com.haulmont.cuba.core.config.type.UuidTypeFactory; -import com.haulmont.cuba.core.sys.AvailableLocalesFactory; -import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; - -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Configuration parameters interface used by all layers: CORE, WEB, DESKTOP. - */ -@Source(type = SourceType.APP) -public interface GlobalConfig extends Config { - - /** - * @return This web application host name. Makes sense for CORE and WEB modules. - */ - @Property("cuba.webHostName") - @DefaultString("localhost") - String getWebHostName(); - - /** - * @return This web application port. Makes sense for CORE and WEB modules. - */ - @Property("cuba.webPort") - @DefaultString("8080") - String getWebPort(); - - /** - * @return This web application context name. Makes sense for CORE and WEB modules. - */ - @Property("cuba.webContextName") - @DefaultString("cuba") - String getWebContextName(); - - /** - * @return Web-client connection URL. Used for making external links to the application screens and for other purposes. - */ - @Property("cuba.webAppUrl") - @Source(type = SourceType.DATABASE) - @DefaultString("http://localhost:8080/app") - String getWebAppUrl(); - - /** - * @return Base url for dispatcher servlet of web application. Specific for core, web and portal blocks. - */ - @Property("cuba.dispatcherBaseUrl") - String getDispatcherBaseUrl(); - - /** - * DEPRECATED as obsolete. - * @return REST API connection URL - */ - @Deprecated - @Property("cuba.restApiUrl") - @Source(type = SourceType.DATABASE) - @DefaultString("http://localhost:8080/app-portal/api") - String getRestApiUrl(); - - /** - * @return Configuration directory. {@link Scripting} searches for dynamic resources here. - * Must not end with "/" - */ - @Property("cuba.confDir") - String getConfDir(); - - /** - * @return Logs directory. Place app-specific log files here. - * Must not end with "/" - */ - @Property("cuba.logDir") - String getLogDir(); - - /** - * @return Temporary files directory. Place app-specific temp files here. - * Must not end with "/" - */ - @Property("cuba.tempDir") - String getTempDir(); - - /** - * @return Data directory. Place persistent app-specific data files here. - * Must not end with "/" - */ - @Property("cuba.dataDir") - String getDataDir(); - - /** - * Automatic testing mode indication. - * @return true if in test mode - */ - @Property("cuba.testMode") - @DefaultBoolean(false) - boolean getTestMode(); - - /** - * Supported locales. List of locales is shown on user login. - * @return map of labels to locales - */ - @Property("cuba.availableLocales") - @Factory(factory = AvailableLocalesFactory.class) - @Default("English|en;Russian|ru") - Map getAvailableLocales(); - - /** - * Show locale select in LoginWindow. - * @return true if show - */ - @Property("cuba.localeSelectVisible") - @DefaultBoolean(true) - boolean getLocaleSelectVisible(); - - /** - * Whether to use {@link com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased} instead of - * {@link QueryTransformerRegex} - * @return true or false - */ - @Property("cuba.useAstBasedJpqlTransformer") - @DefaultBoolean(true) - boolean getUseAstBasedJpqlTransformer(); - - /** - * @return Overridden AppFolderEditWindow class name - */ - @Property("cuba.web.appFolderEditWindow") - String getAppFolderEditWindowClassName(); - - /** - * @return Overridden FolderEditWindow class name - */ - @Property("cuba.web.folderEditWindow") - String getFolderEditWindowClassName(); - - /** - * @return Allows to apply a filter to previously selected rows - */ - @Property("cuba.allowQueryFromSelected") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(true) - boolean getAllowQueryFromSelected(); - - /** - * @return Classpath directories for dynamic class loader. Separated by ; - */ - @Property("cuba.classpath.directories") - String getCubaClasspathDirectories(); - - /** - * @return the maximum number of idle instances of compiled groovy expressions in {@code Scripting.evaluateGroovy()} - * @see GenericKeyedObjectPoolConfig#setMaxIdlePerKey(int) - */ - @Property("cuba.groovyEvaluationPoolMaxIdle") - @DefaultInt(8) - int getGroovyEvaluationPoolMaxIdle(); - - @Property("cuba.numberIdCacheSize") - @DefaultInt(100) - int getNumberIdCacheSize(); - - @Property("cuba.anonymousSessionId") - @Factory(factory = UuidTypeFactory.class) - UUID getAnonymousSessionId(); - - /** - * @return anonymous access to REST API is allowed - */ - @Property("cuba.rest.anonymousEnabled") - @DefaultBoolean(false) - boolean getRestAnonymousEnabled(); - - /** - * @return response of the HTTP GET request on the health check URL - */ - @Property("cuba.healthCheckResponse") - @Default("ok") - String getHealthCheckResponse(); - - /** - * @return whether the user session log is enabled - */ - @Property("cuba.userSessionLogEnabled") - @Source(type = SourceType.DATABASE) - @DefaultBoolean(false) - boolean getUserSessionLogEnabled(); - void setUserSessionLogEnabled(boolean enabled); - - /** - * @return whether the new (since 6.7) behavior regarding session parameters in query filter is enabled - */ - @Property("cuba.enableSessionParamsInQueryFilter") - @DefaultBoolean(true) - boolean getEnableSessionParamsInQueryFilter(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.config.Config; +import com.haulmont.cuba.core.config.Property; +import com.haulmont.cuba.core.config.Source; +import com.haulmont.cuba.core.config.SourceType; +import com.haulmont.cuba.core.config.defaults.Default; +import com.haulmont.cuba.core.config.defaults.DefaultBoolean; +import com.haulmont.cuba.core.config.defaults.DefaultInt; +import com.haulmont.cuba.core.config.defaults.DefaultString; +import com.haulmont.cuba.core.config.type.Factory; +import com.haulmont.cuba.core.config.type.UuidTypeFactory; +import com.haulmont.cuba.core.sys.AvailableLocalesFactory; +import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; + +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +/** + * Configuration parameters interface used by all layers: CORE, WEB, DESKTOP. + */ +@Source(type = SourceType.APP) +public interface GlobalConfig extends Config { + + /** + * @return This web application host name. Makes sense for CORE and WEB modules. + */ + @Property("cuba.webHostName") + @DefaultString("localhost") + String getWebHostName(); + + /** + * @return This web application port. Makes sense for CORE and WEB modules. + */ + @Property("cuba.webPort") + @DefaultString("8080") + String getWebPort(); + + /** + * @return This web application context name. Makes sense for CORE and WEB modules. + */ + @Property("cuba.webContextName") + @DefaultString("cuba") + String getWebContextName(); + + /** + * @return Web-client connection URL. Used for making external links to the application screens and for other purposes. + */ + @Property("cuba.webAppUrl") + @Source(type = SourceType.DATABASE) + @DefaultString("http://localhost:8080/app") + String getWebAppUrl(); + + /** + * @return Base url for dispatcher servlet of web application. Specific for core, web and portal blocks. + */ + @Property("cuba.dispatcherBaseUrl") + String getDispatcherBaseUrl(); + + /** + * DEPRECATED as obsolete. + * @return REST API connection URL + */ + @Deprecated + @Property("cuba.restApiUrl") + @Source(type = SourceType.DATABASE) + @DefaultString("http://localhost:8080/app-portal/api") + String getRestApiUrl(); + + /** + * @return Configuration directory. {@link Scripting} searches for dynamic resources here. + * Must not end with "/" + */ + @Property("cuba.confDir") + String getConfDir(); + + /** + * @return Logs directory. Place app-specific log files here. + * Must not end with "/" + */ + @Property("cuba.logDir") + String getLogDir(); + + /** + * @return Temporary files directory. Place app-specific temp files here. + * Must not end with "/" + */ + @Property("cuba.tempDir") + String getTempDir(); + + /** + * @return Data directory. Place persistent app-specific data files here. + * Must not end with "/" + */ + @Property("cuba.dataDir") + String getDataDir(); + + /** + * Automatic testing mode indication. + * @return true if in test mode + */ + @Property("cuba.testMode") + @DefaultBoolean(false) + boolean getTestMode(); + + /** + * Supported locales. List of locales is shown on user login. + * @return map of labels to locales + */ + @Property("cuba.availableLocales") + @Factory(factory = AvailableLocalesFactory.class) + @Default("English|en;Russian|ru") + Map getAvailableLocales(); + + /** + * Show locale select in LoginWindow. + * @return true if show + */ + @Property("cuba.localeSelectVisible") + @DefaultBoolean(true) + boolean getLocaleSelectVisible(); + + /** + * Whether to use {@link com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased} instead of + * {@link QueryTransformerRegex} + * @return true or false + */ + @Property("cuba.useAstBasedJpqlTransformer") + @DefaultBoolean(true) + boolean getUseAstBasedJpqlTransformer(); + + /** + * @return Overridden AppFolderEditWindow class name + */ + @Property("cuba.web.appFolderEditWindow") + String getAppFolderEditWindowClassName(); + + /** + * @return Overridden FolderEditWindow class name + */ + @Property("cuba.web.folderEditWindow") + String getFolderEditWindowClassName(); + + /** + * @return Allows to apply a filter to previously selected rows + */ + @Property("cuba.allowQueryFromSelected") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(true) + boolean getAllowQueryFromSelected(); + + /** + * @return Classpath directories for dynamic class loader. Separated by ; + */ + @Property("cuba.classpath.directories") + String getCubaClasspathDirectories(); + + /** + * @return the maximum number of idle instances of compiled groovy expressions in {@code Scripting.evaluateGroovy()} + * @see GenericKeyedObjectPoolConfig#setMaxIdlePerKey(int) + */ + @Property("cuba.groovyEvaluationPoolMaxIdle") + @DefaultInt(8) + int getGroovyEvaluationPoolMaxIdle(); + + @Property("cuba.numberIdCacheSize") + @DefaultInt(100) + int getNumberIdCacheSize(); + + @Property("cuba.anonymousSessionId") + @Factory(factory = UuidTypeFactory.class) + UUID getAnonymousSessionId(); + + /** + * @return anonymous access to REST API is allowed + */ + @Property("cuba.rest.anonymousEnabled") + @DefaultBoolean(false) + boolean getRestAnonymousEnabled(); + + /** + * @return response of the HTTP GET request on the health check URL + */ + @Property("cuba.healthCheckResponse") + @Default("ok") + String getHealthCheckResponse(); + + /** + * @return whether the user session log is enabled + */ + @Property("cuba.userSessionLogEnabled") + @Source(type = SourceType.DATABASE) + @DefaultBoolean(false) + boolean getUserSessionLogEnabled(); + void setUserSessionLogEnabled(boolean enabled); + + /** + * @return whether the new (since 6.7) behavior regarding session parameters in query filter is enabled + */ + @Property("cuba.enableSessionParamsInQueryFilter") + @DefaultBoolean(true) + boolean getEnableSessionParamsInQueryFilter(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/GlobalPersistentAttributesLoadChecker.java b/modules/global/src/com/haulmont/cuba/core/global/GlobalPersistentAttributesLoadChecker.java index 22d4fc0591..b80d31a6ee 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/GlobalPersistentAttributesLoadChecker.java +++ b/modules/global/src/com/haulmont/cuba/core/global/GlobalPersistentAttributesLoadChecker.java @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import org.eclipse.persistence.queries.FetchGroup; -import org.eclipse.persistence.queries.FetchGroupTracker; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collection; -import java.util.List; - -@Component(PersistentAttributesLoadChecker.NAME) -public class GlobalPersistentAttributesLoadChecker implements PersistentAttributesLoadChecker { - - @Inject - protected MetadataTools metadataTools; - - @Inject - protected Metadata metadata; - - protected enum PropertyLoadedState { - YES, - NO, - UNKNOWN - } - - @Override - public boolean isLoaded(Object entity, String property) { - MetaClass metaClass = metadata.getClassNN(entity.getClass()); - MetaProperty metaProperty = metaClass.getPropertyNN(property); - - if (!metadataTools.isPersistent(metaProperty)) { - List relatedProperties = metadataTools.getRelatedProperties(metaProperty); - if (relatedProperties.isEmpty()) { - return true; - } else { - for (String relatedProperty : relatedProperties) { - if (!isLoaded(entity, relatedProperty)) - return false; - } - return true; - } - } - - PropertyLoadedState isLoaded = isLoadedCommonCheck(entity, property); - if (isLoaded != PropertyLoadedState.UNKNOWN) { - return isLoaded == PropertyLoadedState.YES; - } - - return isLoadedSpecificCheck(entity, property, metaClass, metaProperty); - } - - protected PropertyLoadedState isLoadedCommonCheck(Object entity, String property) { - if (entity instanceof BaseGenericIdEntity) { - BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) entity; - - String[] inaccessibleAttributes = BaseEntityInternalAccess.getInaccessibleAttributes(baseGenericIdEntity); - if (inaccessibleAttributes != null) { - for (String inaccessibleAttr : inaccessibleAttributes) { - if (inaccessibleAttr.equals(property)) - return PropertyLoadedState.NO; - } - } - - if (entity instanceof FetchGroupTracker) { - FetchGroup fetchGroup = ((FetchGroupTracker) entity)._persistence_getFetchGroup(); - if (fetchGroup != null) { - boolean inFetchGroup = fetchGroup.getAttributeNames().contains(property); - if (!inFetchGroup) { - // definitely not loaded - return PropertyLoadedState.NO; - } else { - // requires additional check specific for the tier - return PropertyLoadedState.UNKNOWN; - } - } - } - } - - return PropertyLoadedState.UNKNOWN; - } - - protected boolean isLoadedSpecificCheck(Object entity, String property, MetaClass metaClass, MetaProperty metaProperty) { - return checkIsLoadedWithGetter(entity, property); - } - - protected boolean checkIsLoadedWithGetter(Object entity, String property) { - if (entity instanceof Instance) { - try { - Object value = ((Instance) entity).getValue(property); - if (value instanceof Collection) {//check for IndirectCollection behaviour, should fail if property is not loaded - ((Collection) value).size(); - } - return true; - } catch (Exception ignored) { - return false; - } - } else { - throw new IllegalArgumentException("Unable to check if the attribute is loaded: the entity is of unknown type"); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import org.eclipse.persistence.queries.FetchGroup; +import org.eclipse.persistence.queries.FetchGroupTracker; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Collection; +import java.util.List; + +@Component(PersistentAttributesLoadChecker.NAME) +public class GlobalPersistentAttributesLoadChecker implements PersistentAttributesLoadChecker { + + @Inject + protected MetadataTools metadataTools; + + @Inject + protected Metadata metadata; + + protected enum PropertyLoadedState { + YES, + NO, + UNKNOWN + } + + @Override + public boolean isLoaded(Object entity, String property) { + MetaClass metaClass = metadata.getClassNN(entity.getClass()); + MetaProperty metaProperty = metaClass.getPropertyNN(property); + + if (!metadataTools.isPersistent(metaProperty)) { + List relatedProperties = metadataTools.getRelatedProperties(metaProperty); + if (relatedProperties.isEmpty()) { + return true; + } else { + for (String relatedProperty : relatedProperties) { + if (!isLoaded(entity, relatedProperty)) + return false; + } + return true; + } + } + + PropertyLoadedState isLoaded = isLoadedCommonCheck(entity, property); + if (isLoaded != PropertyLoadedState.UNKNOWN) { + return isLoaded == PropertyLoadedState.YES; + } + + return isLoadedSpecificCheck(entity, property, metaClass, metaProperty); + } + + protected PropertyLoadedState isLoadedCommonCheck(Object entity, String property) { + if (entity instanceof BaseGenericIdEntity) { + BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) entity; + + String[] inaccessibleAttributes = BaseEntityInternalAccess.getInaccessibleAttributes(baseGenericIdEntity); + if (inaccessibleAttributes != null) { + for (String inaccessibleAttr : inaccessibleAttributes) { + if (inaccessibleAttr.equals(property)) + return PropertyLoadedState.NO; + } + } + + if (entity instanceof FetchGroupTracker) { + FetchGroup fetchGroup = ((FetchGroupTracker) entity)._persistence_getFetchGroup(); + if (fetchGroup != null) { + boolean inFetchGroup = fetchGroup.getAttributeNames().contains(property); + if (!inFetchGroup) { + // definitely not loaded + return PropertyLoadedState.NO; + } else { + // requires additional check specific for the tier + return PropertyLoadedState.UNKNOWN; + } + } + } + } + + return PropertyLoadedState.UNKNOWN; + } + + protected boolean isLoadedSpecificCheck(Object entity, String property, MetaClass metaClass, MetaProperty metaProperty) { + return checkIsLoadedWithGetter(entity, property); + } + + protected boolean checkIsLoadedWithGetter(Object entity, String property) { + if (entity instanceof Instance) { + try { + Object value = ((Instance) entity).getValue(property); + if (value instanceof Collection) {//check for IndirectCollection behaviour, should fail if property is not loaded + ((Collection) value).size(); + } + return true; + } catch (Exception ignored) { + return false; + } + } else { + throw new IllegalArgumentException("Unable to check if the attribute is loaded: the entity is of unknown type"); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/HashDescriptor.java b/modules/global/src/com/haulmont/cuba/core/global/HashDescriptor.java index 00021f6856..70286bb482 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/HashDescriptor.java +++ b/modules/global/src/com/haulmont/cuba/core/global/HashDescriptor.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -/** - * Container for password hash and salt. - * - */ -public class HashDescriptor { - private final String hash; - - private final String salt; - - public HashDescriptor(String hash, String salt) { - this.hash = hash; - this.salt = salt; - } - - public String getHash() { - return hash; - } - - public String getSalt() { - return salt; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Hash: ") - .append(hash) - .append("\n"); - sb.append("Salt: ") - .append(salt); - - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +/** + * Container for password hash and salt. + * + */ +public class HashDescriptor { + private final String hash; + + private final String salt; + + public HashDescriptor(String hash, String salt) { + this.hash = hash; + this.salt = salt; + } + + public String getHash() { + return hash; + } + + public String getSalt() { + return salt; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Hash: ") + .append(hash) + .append("\n"); + sb.append("Salt: ") + .append(salt); + + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/LoadContext.java b/modules/global/src/com/haulmont/cuba/core/global/LoadContext.java index 1f25ce62bc..d0458eb69b 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/LoadContext.java +++ b/modules/global/src/com/haulmont/cuba/core/global/LoadContext.java @@ -1,446 +1,446 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Entity; - -import javax.persistence.TemporalType; -import java.io.Serializable; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Class that defines parameters for loading entities from the database via {@link DataManager}. - *

Typical usage: - *

-    LoadContext<User> context = LoadContext.create(User.class).setQuery(
-            LoadContext.createQuery("select u from sec$User u where u.login like :login")
-                    .setParameter("login", "a%")
-                    .setMaxResults(10))
-            .setView("user.browse");
-    List<User> users = dataManager.loadList(context);
- * 
- */ -public class LoadContext implements DataLoadContext, Serializable { - - private static final long serialVersionUID = -8808320502197308698L; - - protected String metaClass; - protected Query query; - protected View view; - protected Object id; - protected boolean softDeletion = true; - protected List prevQueries = new ArrayList<>(); - protected int queryKey; - - protected boolean loadDynamicAttributes = false; - protected boolean loadPartialEntities = true; - - protected Map dbHints; // lazy initialized map - - /** - * Factory method to create a LoadContext instance. - * - * @param entityClass class of the loaded entities - */ - public static LoadContext create(Class entityClass) { - return new LoadContext<>(entityClass); - } - - /** - * Factory method to create a LoadContext.Query instance for passing into {@link #setQuery(Query)} method. - * - * @param queryString JPQL query string. Only named parameters are supported. - */ - public static LoadContext.Query createQuery(String queryString) { - return new LoadContext.Query(queryString); - } - - /** - * @param metaClass metaclass of the loaded entities - */ - public LoadContext(MetaClass metaClass) { - Preconditions.checkNotNullArgument(metaClass, "metaClass is null"); - this.metaClass = AppBeans.get(Metadata.class).getExtendedEntities().getEffectiveMetaClass(metaClass).getName(); - } - - /** - * @param javaClass class of the loaded entities - */ - public LoadContext(Class javaClass) { - Preconditions.checkNotNullArgument(javaClass, "javaClass is null"); - this.metaClass = AppBeans.get(Metadata.class).getExtendedEntities().getEffectiveMetaClass(javaClass).getName(); - } - - protected LoadContext() { - } - - /** - * @return name of metaclass of the loaded entities - */ - public String getMetaClass() { - return metaClass; - } - - /** - * @return query definition - */ - public Query getQuery() { - return query; - } - - /** - * @param query query definition - * @return this instance for chaining - */ - public LoadContext setQuery(Query query) { - this.query = query; - return this; - } - - /** - * @param queryString JPQL query string. Only named parameters are supported. - * @return query definition object - */ - @Override - public Query setQueryString(String queryString) { - final Query query = new Query(queryString); - setQuery(query); - return query; - } - - /** - * @return view that is used for loading entities - */ - public View getView() { - return view; - } - - /** - * @param view view that is used for loading entities - * @return this instance for chaining - */ - public LoadContext setView(View view) { - this.view = view; - return this; - } - - /** - * @param viewName view that is used for loading entities - * @return this instance for chaining - */ - public LoadContext setView(String viewName) { - Metadata metadata = AppBeans.get(Metadata.NAME); - this.view = metadata.getViewRepository().getView(metadata.getSession().getClass(metaClass), viewName); - return this; - } - - /** - * @return id of an entity to be loaded - */ - public Object getId() { - return id; - } - - /** - * @param id id of an entity to be loaded - * @return this instance for chaining - */ - public LoadContext setId(Object id) { - this.id = id; - return this; - } - - /** - * @return whether to use soft deletion when loading entities - */ - public boolean isSoftDeletion() { - return softDeletion; - } - - /** - * @param softDeletion whether to use soft deletion when loading entities - */ - public LoadContext setSoftDeletion(boolean softDeletion) { - this.softDeletion = softDeletion; - return this; - } - - /** - * Allows to execute query on a previous query result. - * @return editable list of previous queries - */ - public List getPrevQueries() { - return prevQueries; - } - - /** - * @return key of the current stack of sequential queries, which is unique for the current user session - */ - public int getQueryKey() { - return queryKey; - } - - /** - * @param queryKey key of the current stack of sequential queries, which is unique for the current user session - */ - public LoadContext setQueryKey(int queryKey) { - this.queryKey = queryKey; - return this; - } - - /** - * @return custom hints which can be used later during query construction - */ - public Map getDbHints() { - if (dbHints == null) { - dbHints = new HashMap<>(); - } - return dbHints; - } - - /** - * @return whether to load dynamic attributes - */ - public boolean isLoadDynamicAttributes() { - return loadDynamicAttributes; - } - - /** - * @param loadDynamicAttributes whether to load dynamic attributes - */ - public LoadContext setLoadDynamicAttributes(boolean loadDynamicAttributes) { - this.loadDynamicAttributes = loadDynamicAttributes; - return this; - } - - /** - * @return whether to load partial entities. When true (which is by default), some local attributes can be unfetched - * according to {@link #setView(View)}. - *

The state of {@link View#loadPartialEntities} is ignored when the view is passed to {@link DataManager}. - */ - public boolean isLoadPartialEntities() { - return loadPartialEntities; - } - - /** - * Whether to load partial entities. When true (which is by default), some local attributes can be unfetched - * according to {@link #setView(View)}. - *

The state of {@link View#loadPartialEntities} is ignored when the view is passed to {@link DataManager}. - */ - public LoadContext setLoadPartialEntities(boolean loadPartialEntities) { - this.loadPartialEntities = loadPartialEntities; - return this; - } - - /** - * Creates a copy of this LoadContext instance. - */ - public LoadContext copy() { - LoadContext ctx; - try { - ctx = getClass().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Error copying LoadContext", e); - } - ctx.metaClass = metaClass; - ctx.setQuery(query.copy()); - ctx.view = view; - ctx.id = id; - ctx.softDeletion = softDeletion; - ctx.prevQueries.addAll(prevQueries.stream().map(Query::copy).collect(Collectors.toList())); - ctx.queryKey = queryKey; - if (dbHints != null) { - ctx.getDbHints().putAll(dbHints); - } - ctx.loadDynamicAttributes = loadDynamicAttributes; - return ctx; - } - - @Override - public String toString() { - return String.format( - "LoadContext{metaClass=%s, query=%s, view=%s, id=%s, softDeletion=%s, partialEntities=%s, dynamicAttributes=%s}", - metaClass, query, view, id, softDeletion, loadPartialEntities, loadDynamicAttributes - ); - } - - /** - * Class that defines a query to be executed for data loading. - */ - public static class Query implements DataLoadContextQuery, Serializable { - - private static final long serialVersionUID = 3819951144050635838L; - - private Map parameters = new HashMap<>(); - private String queryString; - private int firstResult; - private int maxResults; - private boolean cacheable; - - /** - * @param queryString JPQL query string. Only named parameters are supported. - */ - public Query(String queryString) { - this.queryString = queryString; - } - - /** - * @return JPQL query string - */ - public String getQueryString() { - return queryString; - } - - /** - * @param queryString JPQL query string. Only named parameters are supported. - */ - public Query setQueryString(String queryString) { - this.queryString = queryString; - return this; - } - - /** - * Set value for a query parameter. - * @param name parameter name - * @param value parameter value - * @return this query instance for chaining - */ - public Query setParameter(String name, Object value) { - parameters.put(name, value); - return this; - } - - /** - * Set value for a parameter of java.util.Date type. - * @param name parameter name - * @param value date value - * @param temporalType temporal type - * @return this query instance for chaining - */ - public Query setParameter(String name, Date value, TemporalType temporalType) { - parameters.put(name, new TemporalValue(value, temporalType)); - return this; - } - - /** - * @return editable map of the query parameters - */ - public Map getParameters() { - return parameters; - } - - /** - * @param parameters map of the query parameters - */ - public Query setParameters(Map parameters) { - this.parameters.putAll(parameters); - return this; - } - - /** - * @param firstResult results offset - * @return this query instance for chaining - */ - public Query setFirstResult(int firstResult) { - this.firstResult = firstResult; - return this; - } - - /** - * @param maxResults results limit - * @return this query instance for chaining - */ - public Query setMaxResults(int maxResults) { - this.maxResults = maxResults; - return this; - } - - /** - * Indicates that the query results should be cached. - * @return the same query instance - */ - public Query setCacheable(boolean cacheable) { - this.cacheable = cacheable; - return this; - } - - /** - * @return results offset - */ - public int getFirstResult() { - return firstResult; - } - - /** - * @return results limit - */ - public int getMaxResults() { - return maxResults; - } - - - public boolean isCacheable() { - return cacheable; - } - - /** - * Creates a copy of this Query instance. - */ - public Query copy() { - Query query = new Query(queryString); - query.parameters.putAll(parameters); - query.firstResult = firstResult; - query.maxResults = maxResults; - query.cacheable = cacheable; - return query; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Query query = (Query) o; - - if (firstResult != query.firstResult) return false; - if (maxResults != query.maxResults) return false; - if (!parameters.equals(query.parameters)) return false; - return queryString.equals(query.queryString); - } - - @Override - public int hashCode() { - int result = parameters.hashCode(); - result = 31 * result + queryString.hashCode(); - result = 31 * result + firstResult; - result = 31 * result + maxResults; - return result; - } - - @Override - public String toString() { - return "Query{" + - "queryString='" + queryString + '\'' + - ", firstResult=" + firstResult + - ", maxResults=" + maxResults + - '}'; - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Entity; + +import javax.persistence.TemporalType; +import java.io.Serializable; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Class that defines parameters for loading entities from the database via {@link DataManager}. + *

Typical usage: + *

+    LoadContext<User> context = LoadContext.create(User.class).setQuery(
+            LoadContext.createQuery("select u from sec$User u where u.login like :login")
+                    .setParameter("login", "a%")
+                    .setMaxResults(10))
+            .setView("user.browse");
+    List<User> users = dataManager.loadList(context);
+ * 
+ */ +public class LoadContext implements DataLoadContext, Serializable { + + private static final long serialVersionUID = -8808320502197308698L; + + protected String metaClass; + protected Query query; + protected View view; + protected Object id; + protected boolean softDeletion = true; + protected List prevQueries = new ArrayList<>(); + protected int queryKey; + + protected boolean loadDynamicAttributes = false; + protected boolean loadPartialEntities = true; + + protected Map dbHints; // lazy initialized map + + /** + * Factory method to create a LoadContext instance. + * + * @param entityClass class of the loaded entities + */ + public static LoadContext create(Class entityClass) { + return new LoadContext<>(entityClass); + } + + /** + * Factory method to create a LoadContext.Query instance for passing into {@link #setQuery(Query)} method. + * + * @param queryString JPQL query string. Only named parameters are supported. + */ + public static LoadContext.Query createQuery(String queryString) { + return new LoadContext.Query(queryString); + } + + /** + * @param metaClass metaclass of the loaded entities + */ + public LoadContext(MetaClass metaClass) { + Preconditions.checkNotNullArgument(metaClass, "metaClass is null"); + this.metaClass = AppBeans.get(Metadata.class).getExtendedEntities().getEffectiveMetaClass(metaClass).getName(); + } + + /** + * @param javaClass class of the loaded entities + */ + public LoadContext(Class javaClass) { + Preconditions.checkNotNullArgument(javaClass, "javaClass is null"); + this.metaClass = AppBeans.get(Metadata.class).getExtendedEntities().getEffectiveMetaClass(javaClass).getName(); + } + + protected LoadContext() { + } + + /** + * @return name of metaclass of the loaded entities + */ + public String getMetaClass() { + return metaClass; + } + + /** + * @return query definition + */ + public Query getQuery() { + return query; + } + + /** + * @param query query definition + * @return this instance for chaining + */ + public LoadContext setQuery(Query query) { + this.query = query; + return this; + } + + /** + * @param queryString JPQL query string. Only named parameters are supported. + * @return query definition object + */ + @Override + public Query setQueryString(String queryString) { + final Query query = new Query(queryString); + setQuery(query); + return query; + } + + /** + * @return view that is used for loading entities + */ + public View getView() { + return view; + } + + /** + * @param view view that is used for loading entities + * @return this instance for chaining + */ + public LoadContext setView(View view) { + this.view = view; + return this; + } + + /** + * @param viewName view that is used for loading entities + * @return this instance for chaining + */ + public LoadContext setView(String viewName) { + Metadata metadata = AppBeans.get(Metadata.NAME); + this.view = metadata.getViewRepository().getView(metadata.getSession().getClass(metaClass), viewName); + return this; + } + + /** + * @return id of an entity to be loaded + */ + public Object getId() { + return id; + } + + /** + * @param id id of an entity to be loaded + * @return this instance for chaining + */ + public LoadContext setId(Object id) { + this.id = id; + return this; + } + + /** + * @return whether to use soft deletion when loading entities + */ + public boolean isSoftDeletion() { + return softDeletion; + } + + /** + * @param softDeletion whether to use soft deletion when loading entities + */ + public LoadContext setSoftDeletion(boolean softDeletion) { + this.softDeletion = softDeletion; + return this; + } + + /** + * Allows to execute query on a previous query result. + * @return editable list of previous queries + */ + public List getPrevQueries() { + return prevQueries; + } + + /** + * @return key of the current stack of sequential queries, which is unique for the current user session + */ + public int getQueryKey() { + return queryKey; + } + + /** + * @param queryKey key of the current stack of sequential queries, which is unique for the current user session + */ + public LoadContext setQueryKey(int queryKey) { + this.queryKey = queryKey; + return this; + } + + /** + * @return custom hints which can be used later during query construction + */ + public Map getDbHints() { + if (dbHints == null) { + dbHints = new HashMap<>(); + } + return dbHints; + } + + /** + * @return whether to load dynamic attributes + */ + public boolean isLoadDynamicAttributes() { + return loadDynamicAttributes; + } + + /** + * @param loadDynamicAttributes whether to load dynamic attributes + */ + public LoadContext setLoadDynamicAttributes(boolean loadDynamicAttributes) { + this.loadDynamicAttributes = loadDynamicAttributes; + return this; + } + + /** + * @return whether to load partial entities. When true (which is by default), some local attributes can be unfetched + * according to {@link #setView(View)}. + *

The state of {@link View#loadPartialEntities} is ignored when the view is passed to {@link DataManager}. + */ + public boolean isLoadPartialEntities() { + return loadPartialEntities; + } + + /** + * Whether to load partial entities. When true (which is by default), some local attributes can be unfetched + * according to {@link #setView(View)}. + *

The state of {@link View#loadPartialEntities} is ignored when the view is passed to {@link DataManager}. + */ + public LoadContext setLoadPartialEntities(boolean loadPartialEntities) { + this.loadPartialEntities = loadPartialEntities; + return this; + } + + /** + * Creates a copy of this LoadContext instance. + */ + public LoadContext copy() { + LoadContext ctx; + try { + ctx = getClass().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Error copying LoadContext", e); + } + ctx.metaClass = metaClass; + ctx.setQuery(query.copy()); + ctx.view = view; + ctx.id = id; + ctx.softDeletion = softDeletion; + ctx.prevQueries.addAll(prevQueries.stream().map(Query::copy).collect(Collectors.toList())); + ctx.queryKey = queryKey; + if (dbHints != null) { + ctx.getDbHints().putAll(dbHints); + } + ctx.loadDynamicAttributes = loadDynamicAttributes; + return ctx; + } + + @Override + public String toString() { + return String.format( + "LoadContext{metaClass=%s, query=%s, view=%s, id=%s, softDeletion=%s, partialEntities=%s, dynamicAttributes=%s}", + metaClass, query, view, id, softDeletion, loadPartialEntities, loadDynamicAttributes + ); + } + + /** + * Class that defines a query to be executed for data loading. + */ + public static class Query implements DataLoadContextQuery, Serializable { + + private static final long serialVersionUID = 3819951144050635838L; + + private Map parameters = new HashMap<>(); + private String queryString; + private int firstResult; + private int maxResults; + private boolean cacheable; + + /** + * @param queryString JPQL query string. Only named parameters are supported. + */ + public Query(String queryString) { + this.queryString = queryString; + } + + /** + * @return JPQL query string + */ + public String getQueryString() { + return queryString; + } + + /** + * @param queryString JPQL query string. Only named parameters are supported. + */ + public Query setQueryString(String queryString) { + this.queryString = queryString; + return this; + } + + /** + * Set value for a query parameter. + * @param name parameter name + * @param value parameter value + * @return this query instance for chaining + */ + public Query setParameter(String name, Object value) { + parameters.put(name, value); + return this; + } + + /** + * Set value for a parameter of java.util.Date type. + * @param name parameter name + * @param value date value + * @param temporalType temporal type + * @return this query instance for chaining + */ + public Query setParameter(String name, Date value, TemporalType temporalType) { + parameters.put(name, new TemporalValue(value, temporalType)); + return this; + } + + /** + * @return editable map of the query parameters + */ + public Map getParameters() { + return parameters; + } + + /** + * @param parameters map of the query parameters + */ + public Query setParameters(Map parameters) { + this.parameters.putAll(parameters); + return this; + } + + /** + * @param firstResult results offset + * @return this query instance for chaining + */ + public Query setFirstResult(int firstResult) { + this.firstResult = firstResult; + return this; + } + + /** + * @param maxResults results limit + * @return this query instance for chaining + */ + public Query setMaxResults(int maxResults) { + this.maxResults = maxResults; + return this; + } + + /** + * Indicates that the query results should be cached. + * @return the same query instance + */ + public Query setCacheable(boolean cacheable) { + this.cacheable = cacheable; + return this; + } + + /** + * @return results offset + */ + public int getFirstResult() { + return firstResult; + } + + /** + * @return results limit + */ + public int getMaxResults() { + return maxResults; + } + + + public boolean isCacheable() { + return cacheable; + } + + /** + * Creates a copy of this Query instance. + */ + public Query copy() { + Query query = new Query(queryString); + query.parameters.putAll(parameters); + query.firstResult = firstResult; + query.maxResults = maxResults; + query.cacheable = cacheable; + return query; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Query query = (Query) o; + + if (firstResult != query.firstResult) return false; + if (maxResults != query.maxResults) return false; + if (!parameters.equals(query.parameters)) return false; + return queryString.equals(query.queryString); + } + + @Override + public int hashCode() { + int result = parameters.hashCode(); + result = 31 * result + queryString.hashCode(); + result = 31 * result + firstResult; + result = 31 * result + maxResults; + return result; + } + + @Override + public String toString() { + return "Query{" + + "queryString='" + queryString + '\'' + + ", firstResult=" + firstResult + + ", maxResults=" + maxResults + + '}'; + } + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/LockInfo.java b/modules/global/src/com/haulmont/cuba/core/global/LockInfo.java index 1e64c85538..588a4d2348 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/LockInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/global/LockInfo.java @@ -1,85 +1,85 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.security.entity.User; - -import java.util.Date; - -/** - * Describes a pessimistic lock of an object. - */ -@MetaClass(name = "sys$LockInfo") -@SystemLevel -public class LockInfo extends BaseUuidEntity { - - private static final long serialVersionUID = -1991047219638006414L; - - private final String entityName; - private final String entityId; - private final Date since; - private final User user; - - public LockInfo(User user, String entityName, String entityId) { - this.entityName = entityName; - this.entityId = entityId; - TimeSource timeSource = AppBeans.get(TimeSource.NAME); - this.since = timeSource.currentTimestamp(); - this.user = user; - } - - /** - * @return locked object id - */ - @MetaProperty - public String getEntityId() { - return entityId; - } - - /** - * @return locked object type - */ - @MetaProperty - public String getEntityName() { - return entityName; - } - - /** - * @return when the lock occurred - */ - @MetaProperty - public Date getSince() { - return since; - } - - /** - * @return a user which holds the lock - */ - @MetaProperty - public User getUser() { - return user; - } - - @Override - public String toString() { - return entityName + "/" + entityId + ", user=" + user + ", since=" + since; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.security.entity.User; + +import java.util.Date; + +/** + * Describes a pessimistic lock of an object. + */ +@MetaClass(name = "sys$LockInfo") +@SystemLevel +public class LockInfo extends BaseUuidEntity { + + private static final long serialVersionUID = -1991047219638006414L; + + private final String entityName; + private final String entityId; + private final Date since; + private final User user; + + public LockInfo(User user, String entityName, String entityId) { + this.entityName = entityName; + this.entityId = entityId; + TimeSource timeSource = AppBeans.get(TimeSource.NAME); + this.since = timeSource.currentTimestamp(); + this.user = user; + } + + /** + * @return locked object id + */ + @MetaProperty + public String getEntityId() { + return entityId; + } + + /** + * @return locked object type + */ + @MetaProperty + public String getEntityName() { + return entityName; + } + + /** + * @return when the lock occurred + */ + @MetaProperty + public Date getSince() { + return since; + } + + /** + * @return a user which holds the lock + */ + @MetaProperty + public User getUser() { + return user; + } + + @Override + public String toString() { + return entityName + "/" + entityId + ", user=" + user + ", since=" + since; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/LockNotSupported.java b/modules/global/src/com/haulmont/cuba/core/global/LockNotSupported.java index 235a70a72a..5c2144bff9 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/LockNotSupported.java +++ b/modules/global/src/com/haulmont/cuba/core/global/LockNotSupported.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -/** - * A special case of {@link LockInfo} that is returned from LockManagerAPI and - * {@link com.haulmont.cuba.core.app.LockService} methods to indicate that locking is not supported for a - * specified object type. - * - */ -public class LockNotSupported extends LockInfo { - - private static final long serialVersionUID = -5382095361423998544L; - - public LockNotSupported() { - super(null, null, null); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +/** + * A special case of {@link LockInfo} that is returned from LockManagerAPI and + * {@link com.haulmont.cuba.core.app.LockService} methods to indicate that locking is not supported for a + * specified object type. + * + */ +public class LockNotSupported extends LockInfo { + + private static final long serialVersionUID = -5382095361423998544L; + + public LockNotSupported() { + super(null, null, null); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/NodeIdentifier.java b/modules/global/src/com/haulmont/cuba/core/global/NodeIdentifier.java index 5d696f0f7f..b3e7f08236 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/NodeIdentifier.java +++ b/modules/global/src/com/haulmont/cuba/core/global/NodeIdentifier.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -public interface NodeIdentifier { - - String NAME = "cuba_NodeIdentifier"; - - String getNodeName(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +public interface NodeIdentifier { + + String NAME = "cuba_NodeIdentifier"; + + String getNodeName(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/OriginalEntityLoadInfo.java b/modules/global/src/com/haulmont/cuba/core/global/OriginalEntityLoadInfo.java index 6623b6b3fe..a5d6137d1c 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/OriginalEntityLoadInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/global/OriginalEntityLoadInfo.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.Entity; - -import java.util.Objects; -import java.util.UUID; - -/** - * Class that encapsulates an information needed to load an entity instance. - *

- * The same as {@link EntityLoadInfo} but always creates an entity of original class if an extended MetaClass is - * provided. - * - */ -public class OriginalEntityLoadInfo extends EntityLoadInfo { - - private OriginalEntityLoadInfo(UUID id, MetaClass metaClass, boolean isStringKey) { - super(id, metaClass, null, isStringKey); - } - - /** - * Create a new info instance. - * @param entity entity instance - * @return info instance - */ - public static OriginalEntityLoadInfo create(Entity entity) { - Objects.requireNonNull(entity, "entity is null"); - - Metadata metadata = AppBeans.get(Metadata.NAME); - MetaClass metaClass = metadata.getSession().getClassNN(entity.getClass()); - - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); - if (originalMetaClass != null) { - metaClass = originalMetaClass; - } - - MetaProperty primaryKeyProperty = metadata.getTools().getPrimaryKeyProperty(metaClass); - boolean stringKey = primaryKeyProperty != null && primaryKeyProperty.getJavaType().equals(String.class); - - return new OriginalEntityLoadInfo((UUID) entity.getId(), metaClass, stringKey); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.Entity; + +import java.util.Objects; +import java.util.UUID; + +/** + * Class that encapsulates an information needed to load an entity instance. + *

+ * The same as {@link EntityLoadInfo} but always creates an entity of original class if an extended MetaClass is + * provided. + * + */ +public class OriginalEntityLoadInfo extends EntityLoadInfo { + + private OriginalEntityLoadInfo(UUID id, MetaClass metaClass, boolean isStringKey) { + super(id, metaClass, null, isStringKey); + } + + /** + * Create a new info instance. + * @param entity entity instance + * @return info instance + */ + public static OriginalEntityLoadInfo create(Entity entity) { + Objects.requireNonNull(entity, "entity is null"); + + Metadata metadata = AppBeans.get(Metadata.NAME); + MetaClass metaClass = metadata.getSession().getClassNN(entity.getClass()); + + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); + if (originalMetaClass != null) { + metaClass = originalMetaClass; + } + + MetaProperty primaryKeyProperty = metadata.getTools().getPrimaryKeyProperty(metaClass); + boolean stringKey = primaryKeyProperty != null && primaryKeyProperty.getJavaType().equals(String.class); + + return new OriginalEntityLoadInfo((UUID) entity.getId(), metaClass, stringKey); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/PasswordEncryption.java b/modules/global/src/com/haulmont/cuba/core/global/PasswordEncryption.java index 09771f97f1..7058a70a88 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/PasswordEncryption.java +++ b/modules/global/src/com/haulmont/cuba/core/global/PasswordEncryption.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.security.entity.User; - -import java.util.UUID; - -/** - * Encryption support for hashing passwords. - * - */ -public interface PasswordEncryption { - - String NAME = "cuba_PasswordEncryption"; - - /** - * @return a random password with Base64 symbols - */ - String generateRandomPassword(); - - /** - * @return a hashing method in use - */ - String getHashMethod(); - - /** - * Hashing string with salt. - * - * @param content string for hashing - * @return hash with random salt. If the current HashMethod doesn't support salt, it is set to null. - */ - HashDescriptor getHash(String content); - - /** - * Hashing password to store it into DB. - * - * @param userId user id - * @param password content for hashing - * @return hash with salt, if it is supported by the current HashMethod - */ - String getPasswordHash(UUID userId, String password); - - /** - * Hashing string. - * - * @param content content for hashing - * @param salt salt - * @return hash with salt, if it is supported by the current HashMethod - */ - String getHash(String content, String salt); - - /** - * Hashing string without salt. - * This method must be used to encrypt password on a client tier before sending it to the middleware. - * - * @param content content for hashing - * @return hash - */ - String getPlainHash(String content); - - /** - * Check password for a user. - * This method is used on the middleware to compare password passed from a client with the one stored in the DB. - * - * @param user user - * @param password password to check. It must be previously encrypted with {@link #getPlainHash(String)} method. - * @return true if the password is valid - */ - boolean checkPassword(User user, String password); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.security.entity.User; + +import java.util.UUID; + +/** + * Encryption support for hashing passwords. + * + */ +public interface PasswordEncryption { + + String NAME = "cuba_PasswordEncryption"; + + /** + * @return a random password with Base64 symbols + */ + String generateRandomPassword(); + + /** + * @return a hashing method in use + */ + String getHashMethod(); + + /** + * Hashing string with salt. + * + * @param content string for hashing + * @return hash with random salt. If the current HashMethod doesn't support salt, it is set to null. + */ + HashDescriptor getHash(String content); + + /** + * Hashing password to store it into DB. + * + * @param userId user id + * @param password content for hashing + * @return hash with salt, if it is supported by the current HashMethod + */ + String getPasswordHash(UUID userId, String password); + + /** + * Hashing string. + * + * @param content content for hashing + * @param salt salt + * @return hash with salt, if it is supported by the current HashMethod + */ + String getHash(String content, String salt); + + /** + * Hashing string without salt. + * This method must be used to encrypt password on a client tier before sending it to the middleware. + * + * @param content content for hashing + * @return hash + */ + String getPlainHash(String content); + + /** + * Check password for a user. + * This method is used on the middleware to compare password passed from a client with the one stored in the DB. + * + * @param user user + * @param password password to check. It must be previously encrypted with {@link #getPlainHash(String)} method. + * @return true if the password is valid + */ + boolean checkPassword(User user, String password); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/PersistenceHelper.java b/modules/global/src/com/haulmont/cuba/core/global/PersistenceHelper.java index e0f96007d6..304afd0ba7 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/PersistenceHelper.java +++ b/modules/global/src/com/haulmont/cuba/core/global/PersistenceHelper.java @@ -1,158 +1,158 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Entity; - -/** - * Utility class providing information about entity states. - *

- * Delegates to {@link EntityStates} bean, so consider using it directly. - */ -public class PersistenceHelper { - - //this instance is required for unit tests where application context can be not created - private static EntityStates _entityStates = new EntityStates(); - - /** - * @see EntityStates#isNew(Object) - */ - public static boolean isNew(Object entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isNew(entity) : _entityStates.isNew(entity); - } - - /** - * @see EntityStates#isManaged(Object) - */ - public static boolean isManaged(Object entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isManaged(entity) : _entityStates.isManaged(entity); - } - - /** - * @see EntityStates#isDeleted(Object) - */ - public static boolean isDetached(Object entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isDetached(entity) : _entityStates.isDetached(entity); - } - - /** - * DEPRECATED. Use {@link MetadataTools#getEntityName(Class)} instead. - */ - @Deprecated - public static String getEntityName(Class entityClass) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.getEntityName(entityClass) : _entityStates.getEntityName(entityClass); - } - - /** - * DEPRECATED. Use {@link MetadataTools#isSoftDeleted(java.lang.Class)} instead. - */ - @Deprecated - public static boolean isSoftDeleted(Class entityClass) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isSoftDeleted(entityClass) : _entityStates.isSoftDeleted(entityClass); - } - - /** - * @see EntityStates#isLoaded(Object, String) - */ - public static boolean isLoaded(Object entity, String property) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isLoaded(entity, property) : _entityStates.isLoaded(entity, property); - } - - /** - * @see EntityStates#checkLoaded(Object, String...) - */ - public static void checkLoaded(Object entity, String... properties) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - if (entityStates != null) { - entityStates.checkLoaded(entity, properties); - } else { - _entityStates.checkLoaded(entity, properties); - } - } - - /** - * Check that all properties of the view are loaded from DB for the passed entity. - * Throws exception if some property is not loaded. - * - * @param entity entity - * @param viewName view name - * @throws IllegalArgumentException if at least one of properties is not loaded - */ - public static void checkLoadedWithView(Entity entity, String viewName) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - if (entityStates != null) { - entityStates.checkLoadedWithView(entity, viewName); - } else { - _entityStates.checkLoadedWithView(entity, viewName); - } - } - - /** - * Check that all properties of the view are loaded from DB for the passed entity. - * - * @param entity entity - * @param viewName view name - * @return false if at least one of properties is not loaded - */ - public static boolean isLoadedWithView(Entity entity, String viewName) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - if (entityStates != null) { - return entityStates.isLoadedWithView(entity, viewName); - } else { - return _entityStates.isLoadedWithView(entity, viewName); - } - } - - /** - * @see EntityStates#isDeleted(Object) - */ - public static boolean isDeleted(Object entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - return entityStates != null ? entityStates.isDeleted(entity) : _entityStates.isDeleted(entity); - } - - /** - * @see EntityStates#makeDetached(BaseGenericIdEntity) - */ - public static void makeDetached(BaseGenericIdEntity entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - if (entityStates != null) { - entityStates.makeDetached(entity); - } else { - _entityStates.makeDetached(entity); - } - } - - /** - * @see EntityStates#makePatch(BaseGenericIdEntity) - */ - public static void makePatch(BaseGenericIdEntity entity) { - EntityStates entityStates = AppBeans.get(EntityStates.class); - if (entityStates != null) { - entityStates.makePatch(entity); - } else { - _entityStates.makePatch(entity); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Entity; + +/** + * Utility class providing information about entity states. + *

+ * Delegates to {@link EntityStates} bean, so consider using it directly. + */ +public class PersistenceHelper { + + //this instance is required for unit tests where application context can be not created + private static EntityStates _entityStates = new EntityStates(); + + /** + * @see EntityStates#isNew(Object) + */ + public static boolean isNew(Object entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isNew(entity) : _entityStates.isNew(entity); + } + + /** + * @see EntityStates#isManaged(Object) + */ + public static boolean isManaged(Object entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isManaged(entity) : _entityStates.isManaged(entity); + } + + /** + * @see EntityStates#isDeleted(Object) + */ + public static boolean isDetached(Object entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isDetached(entity) : _entityStates.isDetached(entity); + } + + /** + * DEPRECATED. Use {@link MetadataTools#getEntityName(Class)} instead. + */ + @Deprecated + public static String getEntityName(Class entityClass) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.getEntityName(entityClass) : _entityStates.getEntityName(entityClass); + } + + /** + * DEPRECATED. Use {@link MetadataTools#isSoftDeleted(java.lang.Class)} instead. + */ + @Deprecated + public static boolean isSoftDeleted(Class entityClass) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isSoftDeleted(entityClass) : _entityStates.isSoftDeleted(entityClass); + } + + /** + * @see EntityStates#isLoaded(Object, String) + */ + public static boolean isLoaded(Object entity, String property) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isLoaded(entity, property) : _entityStates.isLoaded(entity, property); + } + + /** + * @see EntityStates#checkLoaded(Object, String...) + */ + public static void checkLoaded(Object entity, String... properties) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + if (entityStates != null) { + entityStates.checkLoaded(entity, properties); + } else { + _entityStates.checkLoaded(entity, properties); + } + } + + /** + * Check that all properties of the view are loaded from DB for the passed entity. + * Throws exception if some property is not loaded. + * + * @param entity entity + * @param viewName view name + * @throws IllegalArgumentException if at least one of properties is not loaded + */ + public static void checkLoadedWithView(Entity entity, String viewName) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + if (entityStates != null) { + entityStates.checkLoadedWithView(entity, viewName); + } else { + _entityStates.checkLoadedWithView(entity, viewName); + } + } + + /** + * Check that all properties of the view are loaded from DB for the passed entity. + * + * @param entity entity + * @param viewName view name + * @return false if at least one of properties is not loaded + */ + public static boolean isLoadedWithView(Entity entity, String viewName) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + if (entityStates != null) { + return entityStates.isLoadedWithView(entity, viewName); + } else { + return _entityStates.isLoadedWithView(entity, viewName); + } + } + + /** + * @see EntityStates#isDeleted(Object) + */ + public static boolean isDeleted(Object entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + return entityStates != null ? entityStates.isDeleted(entity) : _entityStates.isDeleted(entity); + } + + /** + * @see EntityStates#makeDetached(BaseGenericIdEntity) + */ + public static void makeDetached(BaseGenericIdEntity entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + if (entityStates != null) { + entityStates.makeDetached(entity); + } else { + _entityStates.makeDetached(entity); + } + } + + /** + * @see EntityStates#makePatch(BaseGenericIdEntity) + */ + public static void makePatch(BaseGenericIdEntity entity) { + EntityStates entityStates = AppBeans.get(EntityStates.class); + if (entityStates != null) { + entityStates.makePatch(entity); + } else { + _entityStates.makePatch(entity); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/PersistentAttributesLoadChecker.java b/modules/global/src/com/haulmont/cuba/core/global/PersistentAttributesLoadChecker.java index 03b5f9c4b5..244b3649ee 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/PersistentAttributesLoadChecker.java +++ b/modules/global/src/com/haulmont/cuba/core/global/PersistentAttributesLoadChecker.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -public interface PersistentAttributesLoadChecker { - String NAME = "cuba_PersistentAttributesLoadChecker"; - - boolean isLoaded(Object entity, String property); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +public interface PersistentAttributesLoadChecker { + String NAME = "cuba_PersistentAttributesLoadChecker"; + + boolean isLoaded(Object entity, String property); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/QueryParser.java b/modules/global/src/com/haulmont/cuba/core/global/QueryParser.java index 24e37aa2e3..90d9e80fed 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/QueryParser.java +++ b/modules/global/src/com/haulmont/cuba/core/global/QueryParser.java @@ -1,125 +1,125 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - - -import javax.annotation.Nullable; -import java.util.List; -import java.util.Set; - -/** - * Parses JPQL query and returns some information about it. - */ -public interface QueryParser { - String NAME = "cuba_QueryParser"; - - /** - * Get all parameter names - */ - Set getParamNames(); - - /** - * Main entity name - */ - String getEntityName(); - - Set getAllEntityNames(); - - /** - * Main entity alias - */ - String getEntityAlias(String targetEntity); - - String getEntityAlias(); - - /** - * Returns true if this is a standard select from an entity - not count() and not fields (e.id, etc.) - */ - boolean isEntitySelect(String targetEntity); - - boolean hasIsNullCondition(String attribute); - - /** - * Returns true if SELECT query contains joins - */ - boolean hasJoins(); - - /** - * @return Entity name if not main entity name is returned, otherwise null - * Example: select u.group from sec$User u -> sec$Group - * Example: select g from sec$User u join u.group g -> sec$Group - */ - @Nullable - String getEntityNameIfSecondaryReturnedInsteadOfMain(); - - /** - * @return Entity path if not main entity name is returned, otherwise null - * Example: select u.group from sec$User u -> u.group - * Example: select g from sec$User u join u.group g -> g - */ - @Nullable - String getEntityPathIfSecondaryReturnedInsteadOfMain(); - - /** - * @return true if not main entity selected and it's path with collection - * Example: select u.group from sec$User u -> false - * Example: select u.userRoles from sec$User u -> true - */ - boolean isCollectionSecondaryEntitySelect(); - - boolean isParameterInCondition(String parameterName); - - List getQueryPaths(); - - class QueryPath { - protected String entityName; - protected String pathString; - protected String variableName; - protected boolean selectedPath; - - public QueryPath(String entityName, String variableName, String pathString, boolean selectedPath) { - this.entityName = entityName; - this.variableName = variableName; - this.pathString = pathString; - this.selectedPath = selectedPath; - } - - public String getEntityName() { - return entityName; - } - - public String getFullPath() { - return pathString; - } - - public String getPropertyPath() { - if (pathString.contains(".")) { - return pathString.replace(variableName + ".", ""); - } else { - return pathString; - } - } - - public String getVariableName() { - return variableName; - } - - public boolean isSelectedPath() { - return selectedPath; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + +/** + * Parses JPQL query and returns some information about it. + */ +public interface QueryParser { + String NAME = "cuba_QueryParser"; + + /** + * Get all parameter names + */ + Set getParamNames(); + + /** + * Main entity name + */ + String getEntityName(); + + Set getAllEntityNames(); + + /** + * Main entity alias + */ + String getEntityAlias(String targetEntity); + + String getEntityAlias(); + + /** + * Returns true if this is a standard select from an entity - not count() and not fields (e.id, etc.) + */ + boolean isEntitySelect(String targetEntity); + + boolean hasIsNullCondition(String attribute); + + /** + * Returns true if SELECT query contains joins + */ + boolean hasJoins(); + + /** + * @return Entity name if not main entity name is returned, otherwise null + * Example: select u.group from sec$User u -> sec$Group + * Example: select g from sec$User u join u.group g -> sec$Group + */ + @Nullable + String getEntityNameIfSecondaryReturnedInsteadOfMain(); + + /** + * @return Entity path if not main entity name is returned, otherwise null + * Example: select u.group from sec$User u -> u.group + * Example: select g from sec$User u join u.group g -> g + */ + @Nullable + String getEntityPathIfSecondaryReturnedInsteadOfMain(); + + /** + * @return true if not main entity selected and it's path with collection + * Example: select u.group from sec$User u -> false + * Example: select u.userRoles from sec$User u -> true + */ + boolean isCollectionSecondaryEntitySelect(); + + boolean isParameterInCondition(String parameterName); + + List getQueryPaths(); + + class QueryPath { + protected String entityName; + protected String pathString; + protected String variableName; + protected boolean selectedPath; + + public QueryPath(String entityName, String variableName, String pathString, boolean selectedPath) { + this.entityName = entityName; + this.variableName = variableName; + this.pathString = pathString; + this.selectedPath = selectedPath; + } + + public String getEntityName() { + return entityName; + } + + public String getFullPath() { + return pathString; + } + + public String getPropertyPath() { + if (pathString.contains(".")) { + return pathString.replace(variableName + ".", ""); + } else { + return pathString; + } + } + + public String getVariableName() { + return variableName; + } + + public boolean isSelectedPath() { + return selectedPath; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/QueryParserRegex.java b/modules/global/src/com/haulmont/cuba/core/global/QueryParserRegex.java index ba2f119cb9..b9a1f76328 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/QueryParserRegex.java +++ b/modules/global/src/com/haulmont/cuba/core/global/QueryParserRegex.java @@ -1,177 +1,177 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.google.common.collect.Sets; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Implementation of {@link QueryParser} based on regular expressions. - * - */ -public class QueryParserRegex implements QueryParser { - public static final String QUERY_START_PATTERN_REGEX = "select(\\s+distinct)?\\s+([a-z]+[a-z0-9]*)*\\b"; - public static final Pattern QUERY_START_PATTERN = Pattern.compile(QUERY_START_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - public static final int QS_ALIAS = 2; - - public static final String ENTITY_PATH_PATTERN_REGEX = "select(\\s+distinct)?\\s+(%s[\\.]*[a-z0-9]*)?\\s+\\b"; - public static final int ENTITY_PATH_ALIAS = 2; - - public static final String ENTITY_PATTERN_REGEX = "(\\b[_A-Za-z]+\\$[A-Z][_A-Za-z0-9]*)(\\s+as\\b)?\\s+([a-z]+[a-z0-9]*)*\\b"; - public static final Pattern ENTITY_PATTERN = Pattern.compile(ENTITY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - public static final int EP_ALIAS = 3; - - public static final Pattern FROM_ENTITY_PATTERN = Pattern.compile("\\b(from|update)\\s+" + ENTITY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - public static final int FEP_ENTITY = 2; - public static final int FEP_ALIAS = 4; - - public static final String DISTINCT_PATTERN_REGEX = "\\bDISTINCT\\b"; - public static final Pattern DISTINCT_PATTERN = Pattern.compile(DISTINCT_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String SELECT_DISTINCT_PATTERN_REGEX = "\\bSELECT\\s+DISTINCT\\b"; - public static final Pattern SELECT_DISTINCT_PATTERN = Pattern.compile(SELECT_DISTINCT_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String WHERE_PATTERN_REGEX = "\\bWHERE\\b"; - public static final Pattern WHERE_PATTERN = Pattern.compile(WHERE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String LAST_CLAUSE_PATTERN_REGEX = "(\\bGROUP\\s+BY\\b)|(\\bORDER\\s+BY\\b)|(\\bHAVING\\b)"; - public static final Pattern LAST_CLAUSE_PATTERN = Pattern.compile(LAST_CLAUSE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String ORDER_BY_PATTERN_REGEX = "\\bORDER\\s+BY\\b"; - public static final Pattern ORDER_BY_PATTERN = Pattern.compile(ORDER_BY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String PARAM_PATTERN_REGEX = ":([a-zA-Z_0-9$\\.]+)"; - public static final Pattern PARAM_PATTERN = Pattern.compile(PARAM_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - public static final String COND_PATTERN_REGEX = "([a-zA-Z_0-9$\\.]+)\\s*([=<>]+|like)\\s*"; - - public static final String OR_PATTERN_REGEX = "\\bOR\\b"; - public static final Pattern OR_PATTERN = Pattern.compile(OR_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); - - protected String source; - - QueryParserRegex(String source) { - this.source = source; - } - - @Override - public Set getParamNames() { - Set result = new HashSet<>(); - - Matcher matcher = PARAM_PATTERN.matcher(source); - while (matcher.find()) { - result.add(matcher.group(1)); - } - - return result; - } - - @Override - public String getEntityName() { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(source); - if (entityMatcher.find()) { - return entityMatcher.group(2); - } - throw new RuntimeException("Unable to find entity name [" + source + "]"); - } - - @Override - public String getEntityAlias(String targetEntity) { - return getEntityAlias(); - } - - @Override - public String getEntityAlias() { - String alias = null; - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(source); - if (entityMatcher.find()) { - alias = entityMatcher.group(FEP_ALIAS); - } - if (StringUtils.isBlank(alias)) - throw new RuntimeException("Unable to find entity alias [" + source + "]"); - - return alias; - } - - @Override - public boolean isEntitySelect(String targetEntity) { - String alias = getEntityAlias(targetEntity); - Pattern pattern = Pattern.compile("\\bselect\\s+(distinct\\s+)*" + alias + "\\s+"); - Matcher matcher = pattern.matcher(source); - return matcher.find(); - } - - @Override - public boolean hasIsNullCondition(String attribute) { - Matcher whereMatcher = WHERE_PATTERN.matcher(source); - if (whereMatcher.find()) { - String alias = getEntityAlias(); - Pattern isNullPattern = Pattern.compile("\\b" + alias + "\\." + attribute + "((?i)\\s+is\\s+null)\\b"); - Matcher isNullMatcher = isNullPattern.matcher(source); - return isNullMatcher.find(whereMatcher.end()); - } - return false; - } - - @Override - public boolean hasJoins() { - return false; - } - - @Override - public Set getAllEntityNames() { - Matcher entityNamesMatcher = ENTITY_PATTERN.matcher(source); - Set entityNames = Sets.newHashSet(); - while (entityNamesMatcher.find()) { - entityNames.add(entityNamesMatcher.group(1)); - } - return entityNames; - } - - @Override - public String getEntityNameIfSecondaryReturnedInsteadOfMain() { - return null; - } - - @Override - public String getEntityPathIfSecondaryReturnedInsteadOfMain() { - return null; - } - - @Override - public boolean isCollectionSecondaryEntitySelect() { - return false; - } - - @Override - public boolean isParameterInCondition(String parameterName) { - return false; - } - - @Override - public List getQueryPaths() { - return Collections.emptyList(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.google.common.collect.Sets; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implementation of {@link QueryParser} based on regular expressions. + * + */ +public class QueryParserRegex implements QueryParser { + public static final String QUERY_START_PATTERN_REGEX = "select(\\s+distinct)?\\s+([a-z]+[a-z0-9]*)*\\b"; + public static final Pattern QUERY_START_PATTERN = Pattern.compile(QUERY_START_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + public static final int QS_ALIAS = 2; + + public static final String ENTITY_PATH_PATTERN_REGEX = "select(\\s+distinct)?\\s+(%s[\\.]*[a-z0-9]*)?\\s+\\b"; + public static final int ENTITY_PATH_ALIAS = 2; + + public static final String ENTITY_PATTERN_REGEX = "(\\b[_A-Za-z]+\\$[A-Z][_A-Za-z0-9]*)(\\s+as\\b)?\\s+([a-z]+[a-z0-9]*)*\\b"; + public static final Pattern ENTITY_PATTERN = Pattern.compile(ENTITY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + public static final int EP_ALIAS = 3; + + public static final Pattern FROM_ENTITY_PATTERN = Pattern.compile("\\b(from|update)\\s+" + ENTITY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + public static final int FEP_ENTITY = 2; + public static final int FEP_ALIAS = 4; + + public static final String DISTINCT_PATTERN_REGEX = "\\bDISTINCT\\b"; + public static final Pattern DISTINCT_PATTERN = Pattern.compile(DISTINCT_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String SELECT_DISTINCT_PATTERN_REGEX = "\\bSELECT\\s+DISTINCT\\b"; + public static final Pattern SELECT_DISTINCT_PATTERN = Pattern.compile(SELECT_DISTINCT_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String WHERE_PATTERN_REGEX = "\\bWHERE\\b"; + public static final Pattern WHERE_PATTERN = Pattern.compile(WHERE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String LAST_CLAUSE_PATTERN_REGEX = "(\\bGROUP\\s+BY\\b)|(\\bORDER\\s+BY\\b)|(\\bHAVING\\b)"; + public static final Pattern LAST_CLAUSE_PATTERN = Pattern.compile(LAST_CLAUSE_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String ORDER_BY_PATTERN_REGEX = "\\bORDER\\s+BY\\b"; + public static final Pattern ORDER_BY_PATTERN = Pattern.compile(ORDER_BY_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String PARAM_PATTERN_REGEX = ":([a-zA-Z_0-9$\\.]+)"; + public static final Pattern PARAM_PATTERN = Pattern.compile(PARAM_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + public static final String COND_PATTERN_REGEX = "([a-zA-Z_0-9$\\.]+)\\s*([=<>]+|like)\\s*"; + + public static final String OR_PATTERN_REGEX = "\\bOR\\b"; + public static final Pattern OR_PATTERN = Pattern.compile(OR_PATTERN_REGEX, Pattern.CASE_INSENSITIVE); + + protected String source; + + QueryParserRegex(String source) { + this.source = source; + } + + @Override + public Set getParamNames() { + Set result = new HashSet<>(); + + Matcher matcher = PARAM_PATTERN.matcher(source); + while (matcher.find()) { + result.add(matcher.group(1)); + } + + return result; + } + + @Override + public String getEntityName() { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(source); + if (entityMatcher.find()) { + return entityMatcher.group(2); + } + throw new RuntimeException("Unable to find entity name [" + source + "]"); + } + + @Override + public String getEntityAlias(String targetEntity) { + return getEntityAlias(); + } + + @Override + public String getEntityAlias() { + String alias = null; + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(source); + if (entityMatcher.find()) { + alias = entityMatcher.group(FEP_ALIAS); + } + if (StringUtils.isBlank(alias)) + throw new RuntimeException("Unable to find entity alias [" + source + "]"); + + return alias; + } + + @Override + public boolean isEntitySelect(String targetEntity) { + String alias = getEntityAlias(targetEntity); + Pattern pattern = Pattern.compile("\\bselect\\s+(distinct\\s+)*" + alias + "\\s+"); + Matcher matcher = pattern.matcher(source); + return matcher.find(); + } + + @Override + public boolean hasIsNullCondition(String attribute) { + Matcher whereMatcher = WHERE_PATTERN.matcher(source); + if (whereMatcher.find()) { + String alias = getEntityAlias(); + Pattern isNullPattern = Pattern.compile("\\b" + alias + "\\." + attribute + "((?i)\\s+is\\s+null)\\b"); + Matcher isNullMatcher = isNullPattern.matcher(source); + return isNullMatcher.find(whereMatcher.end()); + } + return false; + } + + @Override + public boolean hasJoins() { + return false; + } + + @Override + public Set getAllEntityNames() { + Matcher entityNamesMatcher = ENTITY_PATTERN.matcher(source); + Set entityNames = Sets.newHashSet(); + while (entityNamesMatcher.find()) { + entityNames.add(entityNamesMatcher.group(1)); + } + return entityNames; + } + + @Override + public String getEntityNameIfSecondaryReturnedInsteadOfMain() { + return null; + } + + @Override + public String getEntityPathIfSecondaryReturnedInsteadOfMain() { + return null; + } + + @Override + public boolean isCollectionSecondaryEntitySelect() { + return false; + } + + @Override + public boolean isParameterInCondition(String parameterName) { + return false; + } + + @Override + public List getQueryPaths() { + return Collections.emptyList(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformer.java b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformer.java index 4d2127915a..adacf686b5 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformer.java +++ b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformer.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import java.util.Set; - -/** - * Transforms JPQL query - * - */ -public interface QueryTransformer { - String NAME = "cuba_QueryTransformer"; - - /** Main entity alias placeholder */ - String ALIAS_PLACEHOLDER = "{E}"; - - /** Adds 'where' clause replacing entity alias */ - void addWhere(String where); - - /** Adds 'where' clause */ - void addWhereAsIs(String where); - - /** Adds 'join' clause */ - void addJoinAsIs(String join); - - /** Adds 'join' and 'where' clauses. Replaces alias in 'join' but doesn't replace it in 'where'*/ - void addJoinAndWhere(String join, String where); - - /* Adds 'selection' to from clause. It will be inserted as first selection after FROM keyword*/ - void addFirstSelectionSource(String selection); - - /** Adds 'where' clause from the query provided. Replaces entity alias */ - void mergeWhere(String query); - - /** Replaces select e.f1, e.f2, ... clause with select count(e) ... */ - void replaceWithCount(); - - /** Replaces select e from ... clause with select e.id from ... */ - void replaceWithSelectId(); - - /** Replaces select e from ... clause with select e.pkName from ... */ - void replaceWithSelectId(String pkName); - - /** Replaces select e from ... clause with select 'selectEntityVariable' from ... */ - void replaceWithSelectEntityVariable(String selectEntityVariable); - - /** - * Replaces 'select distinct' with 'select'. - * @return true if 'distinct' was really removed, false if there was no 'distinct' in the query - */ - boolean removeDistinct(); - - /** - * Replaces 'select' with 'select distinct'. - */ - void addDistinct(); - - /** Adds or replaces 'order by' clause */ - void replaceOrderBy(boolean desc, String... properties); - - /** Adds @param entityAlias to 'group by' clause */ - void addEntityInGroupBy(String entityAlias); - - /** Removes 'order by' clause */ - void removeOrderBy(); - - /** Replace main entity name, e.g. "select d ref$Driver d" with "select d ref$ExtDriver d" */ - void replaceEntityName(String newName); - - /** Reset internal buffer */ - void reset(); - - /** Get buffer */ - String getResult(); - - /** Get parameter names found during transformation */ - Set getAddedParams(); - - void handleCaseInsensitiveParam(String paramName); - - void replaceInCondition(String paramName); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import java.util.Set; + +/** + * Transforms JPQL query + * + */ +public interface QueryTransformer { + String NAME = "cuba_QueryTransformer"; + + /** Main entity alias placeholder */ + String ALIAS_PLACEHOLDER = "{E}"; + + /** Adds 'where' clause replacing entity alias */ + void addWhere(String where); + + /** Adds 'where' clause */ + void addWhereAsIs(String where); + + /** Adds 'join' clause */ + void addJoinAsIs(String join); + + /** Adds 'join' and 'where' clauses. Replaces alias in 'join' but doesn't replace it in 'where'*/ + void addJoinAndWhere(String join, String where); + + /* Adds 'selection' to from clause. It will be inserted as first selection after FROM keyword*/ + void addFirstSelectionSource(String selection); + + /** Adds 'where' clause from the query provided. Replaces entity alias */ + void mergeWhere(String query); + + /** Replaces select e.f1, e.f2, ... clause with select count(e) ... */ + void replaceWithCount(); + + /** Replaces select e from ... clause with select e.id from ... */ + void replaceWithSelectId(); + + /** Replaces select e from ... clause with select e.pkName from ... */ + void replaceWithSelectId(String pkName); + + /** Replaces select e from ... clause with select 'selectEntityVariable' from ... */ + void replaceWithSelectEntityVariable(String selectEntityVariable); + + /** + * Replaces 'select distinct' with 'select'. + * @return true if 'distinct' was really removed, false if there was no 'distinct' in the query + */ + boolean removeDistinct(); + + /** + * Replaces 'select' with 'select distinct'. + */ + void addDistinct(); + + /** Adds or replaces 'order by' clause */ + void replaceOrderBy(boolean desc, String... properties); + + /** Adds @param entityAlias to 'group by' clause */ + void addEntityInGroupBy(String entityAlias); + + /** Removes 'order by' clause */ + void removeOrderBy(); + + /** Replace main entity name, e.g. "select d ref$Driver d" with "select d ref$ExtDriver d" */ + void replaceEntityName(String newName); + + /** Reset internal buffer */ + void reset(); + + /** Get buffer */ + String getResult(); + + /** Get parameter names found during transformation */ + Set getAddedParams(); + + void handleCaseInsensitiveParam(String paramName); + + void replaceInCondition(String paramName); +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerFactory.java b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerFactory.java index 319602c962..47d7aebe75 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerFactory.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.DomainModelBuilder; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -/** - * Factory to get {@link QueryParser} and {@link QueryTransformer} instances. - */ -@Component(QueryTransformerFactory.NAME) -public class QueryTransformerFactory { - - public static final String NAME = "cuba_QueryTransformerFactory"; - - protected boolean useAst = true; - - protected volatile DomainModel domainModel; - - @Inject - public void setConfiguration(Configuration configuration) { - useAst = configuration.getConfig(GlobalConfig.class).getUseAstBasedJpqlTransformer(); - } - - public static QueryTransformer createTransformer(String query) { - return AppBeans.get(NAME, QueryTransformerFactory.class).transformer(query); - } - - public static QueryParser createParser(String query) { - return AppBeans.get(NAME, QueryTransformerFactory.class).parser(query); - } - - public QueryTransformer transformer(String query) { - if (useAst) { - if (domainModel == null) { - DomainModelBuilder builder = AppBeans.get(DomainModelBuilder.NAME); - domainModel = builder.produce(); - } - return AppBeans.getPrototype(QueryTransformer.NAME, domainModel, query); - } else { - return new QueryTransformerRegex(query); - } - } - - public QueryParser parser(String query) { - if (useAst) { - if (domainModel == null) { - DomainModelBuilder builder = AppBeans.get(DomainModelBuilder.NAME); - domainModel = builder.produce(); - } - return AppBeans.getPrototype(QueryParser.NAME, domainModel, query); - } else { - return new QueryParserRegex(query); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.DomainModelBuilder; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; + +/** + * Factory to get {@link QueryParser} and {@link QueryTransformer} instances. + */ +@Component(QueryTransformerFactory.NAME) +public class QueryTransformerFactory { + + public static final String NAME = "cuba_QueryTransformerFactory"; + + protected boolean useAst = true; + + protected volatile DomainModel domainModel; + + @Inject + public void setConfiguration(Configuration configuration) { + useAst = configuration.getConfig(GlobalConfig.class).getUseAstBasedJpqlTransformer(); + } + + public static QueryTransformer createTransformer(String query) { + return AppBeans.get(NAME, QueryTransformerFactory.class).transformer(query); + } + + public static QueryParser createParser(String query) { + return AppBeans.get(NAME, QueryTransformerFactory.class).parser(query); + } + + public QueryTransformer transformer(String query) { + if (useAst) { + if (domainModel == null) { + DomainModelBuilder builder = AppBeans.get(DomainModelBuilder.NAME); + domainModel = builder.produce(); + } + return AppBeans.getPrototype(QueryTransformer.NAME, domainModel, query); + } else { + return new QueryTransformerRegex(query); + } + } + + public QueryParser parser(String query) { + if (useAst) { + if (domainModel == null) { + DomainModelBuilder builder = AppBeans.get(DomainModelBuilder.NAME); + domainModel = builder.produce(); + } + return AppBeans.getPrototype(QueryParser.NAME, domainModel, query); + } else { + return new QueryParserRegex(query); + } + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerRegex.java b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerRegex.java index 674bdaacf9..779eabdbd6 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerRegex.java +++ b/modules/global/src/com/haulmont/cuba/core/global/QueryTransformerRegex.java @@ -1,428 +1,428 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import org.apache.commons.lang.StringUtils; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Implementation of {@link QueryTransformer} based on regular expressions. - * - */ -public class QueryTransformerRegex extends QueryParserRegex implements QueryTransformer { - - private StringBuffer buffer; - private Set addedParams; - - public QueryTransformerRegex(String source) { - super(source); - buffer = new StringBuffer(source); - addedParams = new HashSet<>(); - } - - @Override - public void addWhere(String where) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - String alias = findAlias(entityMatcher); - - int insertPos = buffer.length(); - Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); - if (lastClauseMatcher.find(entityMatcher.end())) - insertPos = lastClauseMatcher.start() - 1; - - StringBuilder sb = new StringBuilder(); - Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); - int whereEnd = -1; - boolean needOpenBracket = false; - if (whereMatcher.find(entityMatcher.end())) { - whereEnd = whereMatcher.end(); - - Matcher orMatcher = OR_PATTERN.matcher(buffer); - orMatcher.region(whereEnd + 1, insertPos); - if (orMatcher.find()) { // surround with brackets if there is OR inside WHERE - sb.append(")"); - needOpenBracket = true; - } - sb.append(" and "); - } else { - sb.append(" where "); - } - - sb.append("(").append(where); - int idx; - while ((idx = sb.indexOf(ALIAS_PLACEHOLDER)) >= 0) { - sb.replace(idx, idx + ALIAS_PLACEHOLDER.length(), alias); - } - sb.append(")"); - - if (needOpenBracket) { - buffer.insert(whereEnd + 1, "("); - insertPos++; - } - - buffer.insert(insertPos, sb); - - Matcher paramMatcher = PARAM_PATTERN.matcher(where); - while (paramMatcher.find()) { - addedParams.add(paramMatcher.group(1)); - } - } - - @Override - public void addWhereAsIs(String where) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - findAlias(entityMatcher); - - int insertPos = buffer.length(); - Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); - if (lastClauseMatcher.find(entityMatcher.end())) - insertPos = lastClauseMatcher.start() - 1; - - StringBuilder sb = new StringBuilder(); - Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); - if (whereMatcher.find(entityMatcher.end())) - sb.append(" and "); - else - sb.append(" where "); - - sb.append("(").append(where).append(")"); - - buffer.insert(insertPos, sb); - - Matcher paramMatcher = PARAM_PATTERN.matcher(where); - while (paramMatcher.find()) { - addedParams.add(paramMatcher.group(1)); - } - } - - @Override - public void addJoinAsIs(String join) { - Matcher matcher = findReturnedEntityDeclaration(); - int insertPos = matcher.end(); - - buffer.insert(insertPos, " "); - insertPos++; - - buffer.insert(insertPos, join); - - Matcher paramMatcher = PARAM_PATTERN.matcher(join); - while (paramMatcher.find()) { - addedParams.add(paramMatcher.group(1)); - } - } - - @Override - public void addJoinAndWhere(String join, String where) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - String alias = findAlias(entityMatcher); - - int insertPos = buffer.length(); - - Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); - if (whereMatcher.find(entityMatcher.end())) { - insertPos = whereMatcher.start() - 1; - } else { - Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); - if (lastClauseMatcher.find(entityMatcher.end())) - insertPos = lastClauseMatcher.start() - 1; - } - - if (!StringUtils.isBlank(join)) { - buffer.insert(insertPos, " "); - insertPos++; - buffer.insert(insertPos, join); - - Matcher paramMatcher = PARAM_PATTERN.matcher(join); - while (paramMatcher.find()) { - addedParams.add(paramMatcher.group(1)); - } - } - if (!StringUtils.isBlank(where)) { - insertPos = buffer.length(); - Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); - if (lastClauseMatcher.find(entityMatcher.end())) - insertPos = lastClauseMatcher.start() - 1; - - StringBuilder sb = new StringBuilder(); - whereMatcher = WHERE_PATTERN.matcher(buffer); - int whereEnd = -1; - boolean needOpenBracket = false; - if (whereMatcher.find(entityMatcher.end())) { - whereEnd = whereMatcher.end(); - - Matcher orMatcher = OR_PATTERN.matcher(buffer); - orMatcher.region(whereEnd + 1, insertPos); - if (orMatcher.find()) { // surround with brackets if there is OR inside WHERE - sb.append(")"); - needOpenBracket = true; - } - sb.append(" and "); - } else { - sb.append(" where "); - } - - sb.append("(").append(where).append(")"); - - if (needOpenBracket) { - buffer.insert(whereEnd + 1, "("); - insertPos++; - } - - buffer.insert(insertPos, sb); - - Matcher paramMatcher = PARAM_PATTERN.matcher(where); - while (paramMatcher.find()) { - addedParams.add(paramMatcher.group(1)); - } - } - - // replace ALIAS_PLACEHOLDER - int idx; - while ((idx = buffer.indexOf(ALIAS_PLACEHOLDER)) >= 0) { - buffer.replace(idx, idx + ALIAS_PLACEHOLDER.length(), alias); - } - } - - @Override - public void addFirstSelectionSource(String selection) { - throw new UnsupportedOperationException(); - } - - @Override - public void mergeWhere(String query) { - int startPos = 0; - Matcher whereMatcher = WHERE_PATTERN.matcher(query); - if (whereMatcher.find()) - startPos = whereMatcher.end() + 1; - - int endPos = query.length(); - Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(query); - if (lastClauseMatcher.find()) - endPos = lastClauseMatcher.start(); - - addWhere(query.substring(startPos, endPos)); - } - - @Override - public void replaceWithCount() { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - String alias = findAlias(entityMatcher); - String entityPath = alias; - - Matcher entityPathMatcher = Pattern.compile(String.format(ENTITY_PATH_PATTERN_REGEX, alias)) - .matcher(buffer); - - if (entityPathMatcher.find()) { - String group = entityPathMatcher.group(ENTITY_PATH_ALIAS); - if (group != null && group.startsWith(alias)) { - entityPath = group; - } - } - - Matcher distinctMatcher = DISTINCT_PATTERN.matcher(buffer); - - buffer.replace(0, entityMatcher.start(), - "select count(" + (distinctMatcher.find() ? "distinct " : "") + entityPath + ") "); - - Matcher orderMatcher = ORDER_BY_PATTERN.matcher(buffer); - if (orderMatcher.find()) { - buffer.delete(orderMatcher.start(), buffer.length()); - } - } - - @Override - public void replaceWithSelectId() { - replaceWithSelectId("id"); - } - - @Override - public void replaceWithSelectId(String pkName) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - String alias = findAlias(entityMatcher); - String entityPath = alias; - - Matcher entityPathMatcher = Pattern.compile(String.format(ENTITY_PATH_PATTERN_REGEX, alias)) - .matcher(buffer); - - if (entityPathMatcher.find()) { - String group = entityPathMatcher.group(ENTITY_PATH_ALIAS); - if (group != null && group.startsWith(alias)) { - entityPath = group; - } - } - - Matcher distinctMatcher = DISTINCT_PATTERN.matcher(buffer); - - buffer.replace(0, entityMatcher.start(), - "select " + (distinctMatcher.find() ? "distinct " : "") + entityPath + "." + pkName + " "); - - Matcher orderMatcher = ORDER_BY_PATTERN.matcher(buffer); - if (orderMatcher.find()) { - buffer.delete(orderMatcher.start(), buffer.length()); - } - } - - @Override - public void replaceWithSelectEntityVariable(String selectEntityVariable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeDistinct() { - Matcher matcher = SELECT_DISTINCT_PATTERN.matcher(buffer); - if (matcher.find()) { - buffer.replace(matcher.start(), matcher.end(), "select"); - return true; - } - return false; - } - - @Override - public void addDistinct() { - //not supported - } - - @Override - public void replaceOrderBy(boolean desc, String... properties) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - String alias = findAlias(entityMatcher); - - Matcher orderByMatcher = ORDER_BY_PATTERN.matcher(buffer); - if (orderByMatcher.find()) { - buffer.replace(orderByMatcher.end(), buffer.length(), ""); - } else { - buffer.append(" order by"); - } - - String separator = " "; - for (String property : properties) { - int dotPos = property.lastIndexOf("."); - if (dotPos > -1) { - String path = property.substring(0, dotPos); - String joinedAlias = alias + "_" + path.replace(".", "_"); - if (buffer.indexOf(" " + joinedAlias) == -1) { - String join = "left join " + alias + "." + path + " " + joinedAlias; - addJoinAsIs(join); - } - - String orderBy = joinedAlias + "." + property.substring(dotPos + 1) + (desc ? " desc" : ""); - buffer.append(separator).append(orderBy); - } else { - String orderBy = alias + "." + property + (desc ? " desc" : ""); - buffer.append(separator).append(orderBy); - } - separator = ", "; - } - } - - @Override - public void addEntityInGroupBy(String entityAlias) { - //not supported - } - - @Override - public void removeOrderBy() { - Matcher matcher = ORDER_BY_PATTERN.matcher(buffer); - if (matcher.find()) { - buffer.delete(matcher.start(), buffer.length()); - } - } - - @Override - public void replaceEntityName(String newName) { - Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); - if (entityMatcher.find()) { - buffer.replace(entityMatcher.start(FEP_ENTITY), entityMatcher.end(FEP_ENTITY), newName); - return; - } - error("Unable to find entity name"); - } - - @Override - public void reset() { - buffer = new StringBuffer(source); - addedParams.clear(); - } - - @Override - public String getResult() { - return buffer.toString().trim(); - } - - @Override - public Set getAddedParams() { - return Collections.unmodifiableSet(addedParams); - } - - @Override - public void handleCaseInsensitiveParam(String paramName) { - Pattern pattern = Pattern.compile(COND_PATTERN_REGEX + ":" + paramName, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(buffer); - if (matcher.find()) { - String field = matcher.group(1); - buffer.replace(matcher.start(1), matcher.end(1), "lower(" + field + ")"); - } - } - - @Override - public void replaceInCondition(String paramName) { - //not supported - } - - private String findAlias(Matcher entityMatcher) { - String alias = null; - if (entityMatcher.find()) { - alias = entityMatcher.group(FEP_ALIAS); - } - if (StringUtils.isBlank(alias)) - error("Unable to find entity alias"); - return alias; - } - - private Matcher findReturnedEntityDeclaration() { - Matcher firstAliasMatcher = QUERY_START_PATTERN.matcher(buffer); - String firstAlias = null; - if (firstAliasMatcher.find()) { - firstAlias = firstAliasMatcher.group(QS_ALIAS); - } - - Matcher entityMatcher = ENTITY_PATTERN.matcher(buffer); - String alias = null; - while (entityMatcher.find()) { - String matchedAlias = entityMatcher.group(EP_ALIAS); - if (matchedAlias != null && matchedAlias.equalsIgnoreCase(firstAlias)) { - alias = matchedAlias; - break; - } - } - - if (StringUtils.isBlank(alias)) { - error("Unable to find entity alias"); - } - - return entityMatcher; - } - - private void error(String message) { - throw new RuntimeException(message + " [" + buffer.toString() + "]"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import org.apache.commons.lang.StringUtils; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implementation of {@link QueryTransformer} based on regular expressions. + * + */ +public class QueryTransformerRegex extends QueryParserRegex implements QueryTransformer { + + private StringBuffer buffer; + private Set addedParams; + + public QueryTransformerRegex(String source) { + super(source); + buffer = new StringBuffer(source); + addedParams = new HashSet<>(); + } + + @Override + public void addWhere(String where) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + String alias = findAlias(entityMatcher); + + int insertPos = buffer.length(); + Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); + if (lastClauseMatcher.find(entityMatcher.end())) + insertPos = lastClauseMatcher.start() - 1; + + StringBuilder sb = new StringBuilder(); + Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); + int whereEnd = -1; + boolean needOpenBracket = false; + if (whereMatcher.find(entityMatcher.end())) { + whereEnd = whereMatcher.end(); + + Matcher orMatcher = OR_PATTERN.matcher(buffer); + orMatcher.region(whereEnd + 1, insertPos); + if (orMatcher.find()) { // surround with brackets if there is OR inside WHERE + sb.append(")"); + needOpenBracket = true; + } + sb.append(" and "); + } else { + sb.append(" where "); + } + + sb.append("(").append(where); + int idx; + while ((idx = sb.indexOf(ALIAS_PLACEHOLDER)) >= 0) { + sb.replace(idx, idx + ALIAS_PLACEHOLDER.length(), alias); + } + sb.append(")"); + + if (needOpenBracket) { + buffer.insert(whereEnd + 1, "("); + insertPos++; + } + + buffer.insert(insertPos, sb); + + Matcher paramMatcher = PARAM_PATTERN.matcher(where); + while (paramMatcher.find()) { + addedParams.add(paramMatcher.group(1)); + } + } + + @Override + public void addWhereAsIs(String where) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + findAlias(entityMatcher); + + int insertPos = buffer.length(); + Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); + if (lastClauseMatcher.find(entityMatcher.end())) + insertPos = lastClauseMatcher.start() - 1; + + StringBuilder sb = new StringBuilder(); + Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); + if (whereMatcher.find(entityMatcher.end())) + sb.append(" and "); + else + sb.append(" where "); + + sb.append("(").append(where).append(")"); + + buffer.insert(insertPos, sb); + + Matcher paramMatcher = PARAM_PATTERN.matcher(where); + while (paramMatcher.find()) { + addedParams.add(paramMatcher.group(1)); + } + } + + @Override + public void addJoinAsIs(String join) { + Matcher matcher = findReturnedEntityDeclaration(); + int insertPos = matcher.end(); + + buffer.insert(insertPos, " "); + insertPos++; + + buffer.insert(insertPos, join); + + Matcher paramMatcher = PARAM_PATTERN.matcher(join); + while (paramMatcher.find()) { + addedParams.add(paramMatcher.group(1)); + } + } + + @Override + public void addJoinAndWhere(String join, String where) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + String alias = findAlias(entityMatcher); + + int insertPos = buffer.length(); + + Matcher whereMatcher = WHERE_PATTERN.matcher(buffer); + if (whereMatcher.find(entityMatcher.end())) { + insertPos = whereMatcher.start() - 1; + } else { + Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); + if (lastClauseMatcher.find(entityMatcher.end())) + insertPos = lastClauseMatcher.start() - 1; + } + + if (!StringUtils.isBlank(join)) { + buffer.insert(insertPos, " "); + insertPos++; + buffer.insert(insertPos, join); + + Matcher paramMatcher = PARAM_PATTERN.matcher(join); + while (paramMatcher.find()) { + addedParams.add(paramMatcher.group(1)); + } + } + if (!StringUtils.isBlank(where)) { + insertPos = buffer.length(); + Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(buffer); + if (lastClauseMatcher.find(entityMatcher.end())) + insertPos = lastClauseMatcher.start() - 1; + + StringBuilder sb = new StringBuilder(); + whereMatcher = WHERE_PATTERN.matcher(buffer); + int whereEnd = -1; + boolean needOpenBracket = false; + if (whereMatcher.find(entityMatcher.end())) { + whereEnd = whereMatcher.end(); + + Matcher orMatcher = OR_PATTERN.matcher(buffer); + orMatcher.region(whereEnd + 1, insertPos); + if (orMatcher.find()) { // surround with brackets if there is OR inside WHERE + sb.append(")"); + needOpenBracket = true; + } + sb.append(" and "); + } else { + sb.append(" where "); + } + + sb.append("(").append(where).append(")"); + + if (needOpenBracket) { + buffer.insert(whereEnd + 1, "("); + insertPos++; + } + + buffer.insert(insertPos, sb); + + Matcher paramMatcher = PARAM_PATTERN.matcher(where); + while (paramMatcher.find()) { + addedParams.add(paramMatcher.group(1)); + } + } + + // replace ALIAS_PLACEHOLDER + int idx; + while ((idx = buffer.indexOf(ALIAS_PLACEHOLDER)) >= 0) { + buffer.replace(idx, idx + ALIAS_PLACEHOLDER.length(), alias); + } + } + + @Override + public void addFirstSelectionSource(String selection) { + throw new UnsupportedOperationException(); + } + + @Override + public void mergeWhere(String query) { + int startPos = 0; + Matcher whereMatcher = WHERE_PATTERN.matcher(query); + if (whereMatcher.find()) + startPos = whereMatcher.end() + 1; + + int endPos = query.length(); + Matcher lastClauseMatcher = LAST_CLAUSE_PATTERN.matcher(query); + if (lastClauseMatcher.find()) + endPos = lastClauseMatcher.start(); + + addWhere(query.substring(startPos, endPos)); + } + + @Override + public void replaceWithCount() { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + String alias = findAlias(entityMatcher); + String entityPath = alias; + + Matcher entityPathMatcher = Pattern.compile(String.format(ENTITY_PATH_PATTERN_REGEX, alias)) + .matcher(buffer); + + if (entityPathMatcher.find()) { + String group = entityPathMatcher.group(ENTITY_PATH_ALIAS); + if (group != null && group.startsWith(alias)) { + entityPath = group; + } + } + + Matcher distinctMatcher = DISTINCT_PATTERN.matcher(buffer); + + buffer.replace(0, entityMatcher.start(), + "select count(" + (distinctMatcher.find() ? "distinct " : "") + entityPath + ") "); + + Matcher orderMatcher = ORDER_BY_PATTERN.matcher(buffer); + if (orderMatcher.find()) { + buffer.delete(orderMatcher.start(), buffer.length()); + } + } + + @Override + public void replaceWithSelectId() { + replaceWithSelectId("id"); + } + + @Override + public void replaceWithSelectId(String pkName) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + String alias = findAlias(entityMatcher); + String entityPath = alias; + + Matcher entityPathMatcher = Pattern.compile(String.format(ENTITY_PATH_PATTERN_REGEX, alias)) + .matcher(buffer); + + if (entityPathMatcher.find()) { + String group = entityPathMatcher.group(ENTITY_PATH_ALIAS); + if (group != null && group.startsWith(alias)) { + entityPath = group; + } + } + + Matcher distinctMatcher = DISTINCT_PATTERN.matcher(buffer); + + buffer.replace(0, entityMatcher.start(), + "select " + (distinctMatcher.find() ? "distinct " : "") + entityPath + "." + pkName + " "); + + Matcher orderMatcher = ORDER_BY_PATTERN.matcher(buffer); + if (orderMatcher.find()) { + buffer.delete(orderMatcher.start(), buffer.length()); + } + } + + @Override + public void replaceWithSelectEntityVariable(String selectEntityVariable) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeDistinct() { + Matcher matcher = SELECT_DISTINCT_PATTERN.matcher(buffer); + if (matcher.find()) { + buffer.replace(matcher.start(), matcher.end(), "select"); + return true; + } + return false; + } + + @Override + public void addDistinct() { + //not supported + } + + @Override + public void replaceOrderBy(boolean desc, String... properties) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + String alias = findAlias(entityMatcher); + + Matcher orderByMatcher = ORDER_BY_PATTERN.matcher(buffer); + if (orderByMatcher.find()) { + buffer.replace(orderByMatcher.end(), buffer.length(), ""); + } else { + buffer.append(" order by"); + } + + String separator = " "; + for (String property : properties) { + int dotPos = property.lastIndexOf("."); + if (dotPos > -1) { + String path = property.substring(0, dotPos); + String joinedAlias = alias + "_" + path.replace(".", "_"); + if (buffer.indexOf(" " + joinedAlias) == -1) { + String join = "left join " + alias + "." + path + " " + joinedAlias; + addJoinAsIs(join); + } + + String orderBy = joinedAlias + "." + property.substring(dotPos + 1) + (desc ? " desc" : ""); + buffer.append(separator).append(orderBy); + } else { + String orderBy = alias + "." + property + (desc ? " desc" : ""); + buffer.append(separator).append(orderBy); + } + separator = ", "; + } + } + + @Override + public void addEntityInGroupBy(String entityAlias) { + //not supported + } + + @Override + public void removeOrderBy() { + Matcher matcher = ORDER_BY_PATTERN.matcher(buffer); + if (matcher.find()) { + buffer.delete(matcher.start(), buffer.length()); + } + } + + @Override + public void replaceEntityName(String newName) { + Matcher entityMatcher = FROM_ENTITY_PATTERN.matcher(buffer); + if (entityMatcher.find()) { + buffer.replace(entityMatcher.start(FEP_ENTITY), entityMatcher.end(FEP_ENTITY), newName); + return; + } + error("Unable to find entity name"); + } + + @Override + public void reset() { + buffer = new StringBuffer(source); + addedParams.clear(); + } + + @Override + public String getResult() { + return buffer.toString().trim(); + } + + @Override + public Set getAddedParams() { + return Collections.unmodifiableSet(addedParams); + } + + @Override + public void handleCaseInsensitiveParam(String paramName) { + Pattern pattern = Pattern.compile(COND_PATTERN_REGEX + ":" + paramName, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(buffer); + if (matcher.find()) { + String field = matcher.group(1); + buffer.replace(matcher.start(1), matcher.end(1), "lower(" + field + ")"); + } + } + + @Override + public void replaceInCondition(String paramName) { + //not supported + } + + private String findAlias(Matcher entityMatcher) { + String alias = null; + if (entityMatcher.find()) { + alias = entityMatcher.group(FEP_ALIAS); + } + if (StringUtils.isBlank(alias)) + error("Unable to find entity alias"); + return alias; + } + + private Matcher findReturnedEntityDeclaration() { + Matcher firstAliasMatcher = QUERY_START_PATTERN.matcher(buffer); + String firstAlias = null; + if (firstAliasMatcher.find()) { + firstAlias = firstAliasMatcher.group(QS_ALIAS); + } + + Matcher entityMatcher = ENTITY_PATTERN.matcher(buffer); + String alias = null; + while (entityMatcher.find()) { + String matchedAlias = entityMatcher.group(EP_ALIAS); + if (matchedAlias != null && matchedAlias.equalsIgnoreCase(firstAlias)) { + alias = matchedAlias; + break; + } + } + + if (StringUtils.isBlank(alias)) { + error("Unable to find entity alias"); + } + + return entityMatcher; + } + + private void error(String message) { + throw new RuntimeException(message + " [" + buffer.toString() + "]"); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/RowLevelSecurityException.java b/modules/global/src/com/haulmont/cuba/core/global/RowLevelSecurityException.java index d5e47e83cb..a209c87eb8 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/RowLevelSecurityException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/RowLevelSecurityException.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.security.entity.ConstraintOperationType; - -/** - * Exception that is raised on different exceptions related to Row Level Security. - *

- * - */ -@SupportedByClient -@Logging(Logging.Type.BRIEF) -public class RowLevelSecurityException extends RuntimeException { - private static final long serialVersionUID = -3097861878301424338L; - - private final String entity; - private final ConstraintOperationType operationType; - - public RowLevelSecurityException(String message, String entity) { - super(message); - this.entity = entity; - this.operationType = null; - } - - public RowLevelSecurityException(String message, String entity, ConstraintOperationType operationType) { - super(message); - this.entity = entity; - this.operationType = operationType; - } - - public String getEntity() { - return entity; - } - - public ConstraintOperationType getOperationType() { - return operationType; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.security.entity.ConstraintOperationType; + +/** + * Exception that is raised on different exceptions related to Row Level Security. + *

+ * + */ +@SupportedByClient +@Logging(Logging.Type.BRIEF) +public class RowLevelSecurityException extends RuntimeException { + private static final long serialVersionUID = -3097861878301424338L; + + private final String entity; + private final ConstraintOperationType operationType; + + public RowLevelSecurityException(String message, String entity) { + super(message); + this.entity = entity; + this.operationType = null; + } + + public RowLevelSecurityException(String message, String entity, ConstraintOperationType operationType) { + super(message); + this.entity = entity; + this.operationType = operationType; + } + + public String getEntity() { + return entity; + } + + public ConstraintOperationType getOperationType() { + return operationType; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/SendingStatus.java b/modules/global/src/com/haulmont/cuba/core/global/SendingStatus.java index bc9a6c1fb8..e78406edd9 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/SendingStatus.java +++ b/modules/global/src/com/haulmont/cuba/core/global/SendingStatus.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; - -public enum SendingStatus implements EnumClass { - QUEUE(0), - SENDING(100), - SENT(200), - NOTSENT(300); - - private Integer id; - - SendingStatus(Integer id) { - this.id=id; - } - - @Override - public Integer getId() { - return id; - } - - public static SendingStatus fromId(Integer id) { - for (SendingStatus ss : SendingStatus.values()) { - if (id.equals(ss.getId())) { - return ss; - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; + +public enum SendingStatus implements EnumClass { + QUEUE(0), + SENDING(100), + SENT(200), + NOTSENT(300); + + private Integer id; + + SendingStatus(Integer id) { + this.id=id; + } + + @Override + public Integer getId() { + return id; + } + + public static SendingStatus fromId(Integer id) { + for (SendingStatus ss : SendingStatus.values()) { + if (id.equals(ss.getId())) { + return ss; + } + } + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/SilentException.java b/modules/global/src/com/haulmont/cuba/core/global/SilentException.java index 3f15d3c3fa..ce1c57a66b 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/SilentException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/SilentException.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -/** - * Exception that is used to interrupt an execution flow without any messages to the user. - * - */ -@Logging(Logging.Type.NONE) -public class SilentException extends RuntimeException { - - private static final long serialVersionUID = 6598108074890603763L; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +/** + * Exception that is used to interrupt an execution flow without any messages to the user. + * + */ +@Logging(Logging.Type.NONE) +public class SilentException extends RuntimeException { + + private static final long serialVersionUID = 6598108074890603763L; +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/TemplateHelper.java b/modules/global/src/com/haulmont/cuba/core/global/TemplateHelper.java index 74f38be46d..a70a18554b 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/TemplateHelper.java +++ b/modules/global/src/com/haulmont/cuba/core/global/TemplateHelper.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.AppContext; -import freemarker.cache.FileTemplateLoader; -import freemarker.cache.StringTemplateLoader; -import freemarker.cache.TemplateLoader; -import freemarker.ext.beans.BeansWrapper; -import freemarker.template.Configuration; -import freemarker.template.Template; -import org.apache.commons.collections4.map.LazyMap; -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Map; - -/** - * Use static methods of this class to process Freemarker templates. - * Does not cache templates. - */ -public class TemplateHelper { - public static String processTemplate(String templateStr, Map parameterValues) { - final StringTemplateLoader templateLoader = new StringTemplateLoader(); - templateLoader.putTemplate("template", templateStr); - return __processTemplate(templateLoader, "template", parameterValues); - } - - public static String processTemplateFromFile(String templatePath, Map parameterValues) { - final FileTemplateLoader templateLoader; - try { - String rootPath = AppContext.getProperty("cuba.templateRootDir"); - if (StringUtils.isEmpty(rootPath)) rootPath = AppContext.getProperty("cuba.confDir"); - templateLoader = new FileTemplateLoader(new File(rootPath), true); - } catch (IOException e) { - throw new RuntimeException("Unable to process template from file", e); - } - return __processTemplate(templateLoader, templatePath, parameterValues); - } - - protected static String __processTemplate(TemplateLoader templateLoader, String templateName, - Map parameterValues) { - Map params = prepareParams(parameterValues); - - final StringWriter writer = new StringWriter(); - - try { - final Configuration configuration = new Configuration(); - configuration.setTemplateLoader(templateLoader); - final Template template = configuration.getTemplate(templateName); - template.process(params, writer); - - return writer.toString(); - } catch (Throwable e) { - throw new RuntimeException("Unable to process template", e); - } - } - - protected static Map prepareParams(Map parameterValues) { - Map parameterValuesWithStats = new HashMap<>(parameterValues); - parameterValuesWithStats.put("statics", BeansWrapper.getDefaultInstance().getStaticModels()); - - @SuppressWarnings("unchecked") - Map params = LazyMap.lazyMap(parameterValuesWithStats, propertyName -> { - for (String appProperty : AppContext.getPropertyNames()) { - if (appProperty.replace(".", "_").equals(propertyName)) { - return AppContext.getProperty(propertyName); - } - } - return null; - }); - - return params; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.AppContext; +import freemarker.cache.FileTemplateLoader; +import freemarker.cache.StringTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.Template; +import org.apache.commons.collections4.map.LazyMap; +import org.apache.commons.lang.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +/** + * Use static methods of this class to process Freemarker templates. + * Does not cache templates. + */ +public class TemplateHelper { + public static String processTemplate(String templateStr, Map parameterValues) { + final StringTemplateLoader templateLoader = new StringTemplateLoader(); + templateLoader.putTemplate("template", templateStr); + return __processTemplate(templateLoader, "template", parameterValues); + } + + public static String processTemplateFromFile(String templatePath, Map parameterValues) { + final FileTemplateLoader templateLoader; + try { + String rootPath = AppContext.getProperty("cuba.templateRootDir"); + if (StringUtils.isEmpty(rootPath)) rootPath = AppContext.getProperty("cuba.confDir"); + templateLoader = new FileTemplateLoader(new File(rootPath), true); + } catch (IOException e) { + throw new RuntimeException("Unable to process template from file", e); + } + return __processTemplate(templateLoader, templatePath, parameterValues); + } + + protected static String __processTemplate(TemplateLoader templateLoader, String templateName, + Map parameterValues) { + Map params = prepareParams(parameterValues); + + final StringWriter writer = new StringWriter(); + + try { + final Configuration configuration = new Configuration(); + configuration.setTemplateLoader(templateLoader); + final Template template = configuration.getTemplate(templateName); + template.process(params, writer); + + return writer.toString(); + } catch (Throwable e) { + throw new RuntimeException("Unable to process template", e); + } + } + + protected static Map prepareParams(Map parameterValues) { + Map parameterValuesWithStats = new HashMap<>(parameterValues); + parameterValuesWithStats.put("statics", BeansWrapper.getDefaultInstance().getStaticModels()); + + @SuppressWarnings("unchecked") + Map params = LazyMap.lazyMap(parameterValuesWithStats, propertyName -> { + for (String appProperty : AppContext.getPropertyNames()) { + if (appProperty.replace(".", "_").equals(propertyName)) { + return AppContext.getProperty(propertyName); + } + } + return null; + }); + + return params; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/UserFormatTools.java b/modules/global/src/com/haulmont/cuba/core/global/UserFormatTools.java index 8adb5a9bf8..370aca5559 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/UserFormatTools.java +++ b/modules/global/src/com/haulmont/cuba/core/global/UserFormatTools.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.security.entity.User; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface UserFormatTools { - - String NAME = "cuba_UserFormatTools"; - - String formatSubstitution(@Nonnull User user, @Nullable User substitutedUser); - - String formatOfficial(User user); - - String formatUser(@Nonnull User user, @Nullable User substitutedUser); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.security.entity.User; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface UserFormatTools { + + String NAME = "cuba_UserFormatTools"; + + String formatSubstitution(@Nonnull User user, @Nullable User substitutedUser); + + String formatOfficial(User user); + + String formatUser(@Nonnull User user, @Nullable User substitutedUser); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/UserFormatToolsImpl.java b/modules/global/src/com/haulmont/cuba/core/global/UserFormatToolsImpl.java index a7f52017e5..65dec3c8ec 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/UserFormatToolsImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/global/UserFormatToolsImpl.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; - -import org.springframework.stereotype.Component; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.inject.Inject; - -@Component(UserFormatTools.NAME) -public class UserFormatToolsImpl implements UserFormatTools { - - @Inject - protected Messages messages; - - @Override - public String formatOfficial(User user) { - return StringUtils.defaultIfBlank(user.getName(), user.getLogin()); - } - - @Override - public String formatSubstitution(@Nonnull User user, @Nullable User substitutedUser) { - Preconditions.checkNotNullArgument(user); - - if (substitutedUser == null || user.equals(substitutedUser)) { - return formatOfficial(user); - } else { - return messages.formatMessage(getClass(), "onBehalfOf", - formatOfficial(user), - formatOfficial(substitutedUser)); - } - } - - @Override - public String formatUser(@Nonnull User user, @Nullable User substitutedUser) { - if (substitutedUser != null && !ObjectUtils.equals(user, substitutedUser)) { - return formatSubstitution(user, substitutedUser); - } else { - return formatOfficial(user); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringUtils; + +import org.springframework.stereotype.Component; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Inject; + +@Component(UserFormatTools.NAME) +public class UserFormatToolsImpl implements UserFormatTools { + + @Inject + protected Messages messages; + + @Override + public String formatOfficial(User user) { + return StringUtils.defaultIfBlank(user.getName(), user.getLogin()); + } + + @Override + public String formatSubstitution(@Nonnull User user, @Nullable User substitutedUser) { + Preconditions.checkNotNullArgument(user); + + if (substitutedUser == null || user.equals(substitutedUser)) { + return formatOfficial(user); + } else { + return messages.formatMessage(getClass(), "onBehalfOf", + formatOfficial(user), + formatOfficial(substitutedUser)); + } + } + + @Override + public String formatUser(@Nonnull User user, @Nullable User substitutedUser) { + if (substitutedUser != null && !ObjectUtils.equals(user, substitutedUser)) { + return formatSubstitution(user, substitutedUser); + } else { + return formatOfficial(user); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/UuidProvider.java b/modules/global/src/com/haulmont/cuba/core/global/UuidProvider.java index 5b85b50921..37c5076537 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/UuidProvider.java +++ b/modules/global/src/com/haulmont/cuba/core/global/UuidProvider.java @@ -1,99 +1,99 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.AppContext; - -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -/** - * Provides static method to create UUIDs. - */ -public abstract class UuidProvider { - - private static volatile UuidSource uuidSource; - - /** - * @return new UUID - */ - public static UUID createUuid() { - if (AppContext.getApplicationContext() == null) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - return new UUID(random.nextLong(), random.nextLong()); - } - - if (uuidSource == null) { - uuidSource = AppBeans.get(UuidSource.NAME, UuidSource.class); - } - return uuidSource.createUuid(); - } - - /** - * Fast implementation of creating a {@code UUID} from the standard string representation. - *
- * Borrowed from Apache Jackrabbit project which is licensed under the Apache License, Version 2.0. - * See http://www.apache.org/licenses/LICENSE-2.0. - * - * @param str a string according to {@link java.util.UUID#toString()} rules - * @return UUID instance - */ - public static UUID fromString(String str) { - if (str == null) - return null; - - if (str.length() != 36) { - if (!str.contains("-") && str.length() == 32) { - str = str.substring(0, 8) + "-" - + str.substring(8, 12) + "-" - + str.substring(12, 16) + "-" - + str.substring(16, 20) + "-" - + str.substring(20); - } else { - throw new IllegalArgumentException(str); - } - } - long m = 0, x = 0; - for (int i = 0; i < 36; i++) { - int c = str.charAt(i); - switch (i) { - case 18: - m = x; - x = 0; - // fall through - case 8: - case 13: - case 23: - if (c != '-') { - throw new IllegalArgumentException(str); - } - break; - default: - if (c >= '0' && c <= '9') { - x = (x << 4) | (c - '0'); - } else if (c >= 'a' && c <= 'f') { - x = (x << 4) | (c - 'a' + 0xa); - } else if (c >= 'A' && c <= 'F') { - x = (x << 4) | (c - 'A' + 0xa); - } else { - throw new IllegalArgumentException(str); - } - } - } - return new UUID(m, x); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.AppContext; + +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Provides static method to create UUIDs. + */ +public abstract class UuidProvider { + + private static volatile UuidSource uuidSource; + + /** + * @return new UUID + */ + public static UUID createUuid() { + if (AppContext.getApplicationContext() == null) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + return new UUID(random.nextLong(), random.nextLong()); + } + + if (uuidSource == null) { + uuidSource = AppBeans.get(UuidSource.NAME, UuidSource.class); + } + return uuidSource.createUuid(); + } + + /** + * Fast implementation of creating a {@code UUID} from the standard string representation. + *
+ * Borrowed from Apache Jackrabbit project which is licensed under the Apache License, Version 2.0. + * See http://www.apache.org/licenses/LICENSE-2.0. + * + * @param str a string according to {@link java.util.UUID#toString()} rules + * @return UUID instance + */ + public static UUID fromString(String str) { + if (str == null) + return null; + + if (str.length() != 36) { + if (!str.contains("-") && str.length() == 32) { + str = str.substring(0, 8) + "-" + + str.substring(8, 12) + "-" + + str.substring(12, 16) + "-" + + str.substring(16, 20) + "-" + + str.substring(20); + } else { + throw new IllegalArgumentException(str); + } + } + long m = 0, x = 0; + for (int i = 0; i < 36; i++) { + int c = str.charAt(i); + switch (i) { + case 18: + m = x; + x = 0; + // fall through + case 8: + case 13: + case 23: + if (c != '-') { + throw new IllegalArgumentException(str); + } + break; + default: + if (c >= '0' && c <= '9') { + x = (x << 4) | (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) | (c - 'a' + 0xa); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) | (c - 'A' + 0xa); + } else { + throw new IllegalArgumentException(str); + } + } + } + return new UUID(m, x); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/View.java b/modules/global/src/com/haulmont/cuba/core/global/View.java index ae9fe31f04..ab1a953021 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/View.java +++ b/modules/global/src/com/haulmont/cuba/core/global/View.java @@ -1,338 +1,338 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.cuba.core.entity.Creatable; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.SoftDelete; -import com.haulmont.cuba.core.entity.Updatable; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.*; - -/** - * Class to declare a graph of objects that must be retrieved from the database. - *

- * A view can be constructed in Java code or defined in XML and deployed - * to the {@link com.haulmont.cuba.core.global.ViewRepository} for recurring usage. - *

- * There are the following predefined view types: - *
    - *
  • {@link #LOCAL}
  • - *
  • {@link #MINIMAL}
  • - *
  • {@link #BASE}
  • - *
- * - */ -public class View implements Serializable { - - /** - * Parameters object to be used in constructors. - */ - public static class ViewParams { - protected View src; - protected Class entityClass; - protected String name; - protected boolean includeSystemProperties; - - public ViewParams src(View src) { - this.src = src; - return this; - } - - public ViewParams entityClass(Class entityClass) { - this.entityClass = entityClass; - return this; - } - - public ViewParams name(String name) { - this.name = name; - return this; - } - - public ViewParams includeSystemProperties(boolean includeSystemProperties) { - this.includeSystemProperties = includeSystemProperties; - return this; - } - } - - /** - * Includes all local non-system properties. - */ - public static final String LOCAL = "_local"; - - /** - * Includes only properties contained in {@link com.haulmont.chile.core.annotations.NamePattern}. - */ - public static final String MINIMAL = "_minimal"; - - /** - * Includes all local non-system properties and properties defined by {@link com.haulmont.chile.core.annotations.NamePattern} - * (effectively {@link #MINIMAL} + {@link #LOCAL}). - */ - public static final String BASE = "_base"; - - private static final long serialVersionUID = 4313784222934349594L; - - private Class entityClass; - - private String name; - - private Map properties = new LinkedHashMap<>(); - - private boolean loadPartialEntities; - - public View(Class entityClass) { - this(entityClass, "", true); - } - - public View(Class entityClass, boolean includeSystemProperties) { - this(entityClass, "", includeSystemProperties); - } - - public View(Class entityClass, String name) { - this(entityClass, name, true); - } - - public View(Class entityClass, String name, boolean includeSystemProperties) { - this(new ViewParams().entityClass(entityClass) - .name(name) - .includeSystemProperties(includeSystemProperties) - ); - } - - public View(View src, String name, boolean includeSystemProperties) { - this(src, null, name, includeSystemProperties); - } - - public View(View src, @Nullable Class entityClass, String name, boolean includeSystemProperties) { - this(new ViewParams().src(src) - .entityClass(entityClass != null ? entityClass : src.entityClass) - .name(name) - .includeSystemProperties(includeSystemProperties) - ); - } - - public View(ViewParams viewParams) { - this.entityClass = viewParams.entityClass; - this.name = viewParams.name != null ? viewParams.name : ""; - if (viewParams.includeSystemProperties) { - for (String propertyName : findSystemProperties(entityClass)) { - addProperty(propertyName); - } - } - if (viewParams.src != null) { - this.properties.putAll(viewParams.src.properties); - if (entityClass == null) { - this.entityClass = viewParams.src.entityClass; - } - } - } - - public static View copy(@Nullable View view) { - if (view == null) { - return null; - } - - View.ViewParams viewParams = new View.ViewParams() - .entityClass(view.getEntityClass()) - .name(view.getName()); - View copy = new View(viewParams); - for (ViewProperty property : view.getProperties()) { - copy.addProperty(property.getName(), copy(property.getView()), property.getFetchMode()); - } - - return copy; - } - - /** - * @return entity class this view belongs to - */ - public Class getEntityClass() { - return entityClass; - } - - /** - * @return view name, unique within an entity - */ - public String getName() { - return name; - } - - /** - * @return collection of properties - */ - public Collection getProperties() { - return properties.values(); - } - - /** - * Add a property to this view. - * @param name property name - * @param view a view for a reference attribute, or null - * @param fetchMode fetch mode for a reference attribute - * @return this view instance for chaining - */ - public View addProperty(String name, @Nullable View view, FetchMode fetchMode) { - properties.put(name, new ViewProperty(name, view, fetchMode)); - return this; - } - - @Deprecated - public View addProperty(String name, @Nullable View view, boolean lazy) { - properties.put(name, new ViewProperty(name, view, lazy)); - return this; - } - - /** - * Add a property to this view. - * @param name property name - * @param view a view for a reference attribute, or null - * @return this view instance for chaining - */ - public View addProperty(String name, View view) { - properties.put(name, new ViewProperty(name, view)); - return this; - } - - /** - * Add a property to this view. - * @param name property name - * @return this view instance for chaining - */ - public View addProperty(String name) { - properties.put(name, new ViewProperty(name, null)); - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - View view = (View) o; - - return entityClass.equals(view.entityClass) && name.equals(view.name); - } - - @Override - public int hashCode() { - int result = entityClass.hashCode(); - result = 31 * result + name.hashCode(); - return result; - } - - @Override - public String toString() { - return entityClass.getName() + "/" + name; - } - - /** - * Get directly owned view property by name. - * @param name property name - * @return view property instance or null if it is not found - */ - @Nullable - public ViewProperty getProperty(String name) { - return properties.get(name); - } - - /** - * Check if a directly owned property with the given name exists in the view. - * @param name property name - * @return true if such property found - */ - public boolean containsProperty(String name) { - return properties.containsKey(name); - } - - /** - * If true, the view affects loading of local attributes. If false, only reference attributes are affected and - * local are always loaded. - * - * @see #setLoadPartialEntities(boolean) - */ - public boolean loadPartialEntities() { - return loadPartialEntities; - } - - /** - * Specifies whether the view affects loading of local attributes. By default only reference attributes are affected and - * local are always loaded. - * - * @param loadPartialEntities true to affect loading of local attributes - * @return this view instance for chaining - */ - public View setLoadPartialEntities(boolean loadPartialEntities) { - this.loadPartialEntities = loadPartialEntities; - return this; - } - - /** - * DEPRECATED since v.6 - */ - @Deprecated - public boolean hasLazyProperties() { - return false; - } - - protected Set findSystemProperties(Class entityClass) { - Set result = new LinkedHashSet<>(); - - Metadata metadata = AppBeans.get(Metadata.NAME); - MetaClass metaClass = metadata.getClassNN(entityClass); - - String pkName = metadata.getTools().getPrimaryKeyName(metaClass); - if (pkName != null) { - result.add(pkName); - } - - addSystemPropertiesFrom(Creatable.class, entityClass, metaClass, metadata, result); - addSystemPropertiesFrom(Updatable.class, entityClass, metaClass, metadata, result); - addSystemPropertiesFrom(SoftDelete.class, entityClass, metaClass, metadata, result); - - return result; - } - - protected void addSystemPropertiesFrom(Class baseClass, Class entityClass, MetaClass metaClass, - Metadata metadata, Set result) { - if (baseClass.isAssignableFrom(entityClass)) { - MetadataTools metadataTools = metadata.getTools(); - for (String property : getInterfaceProperties(baseClass)) { - MetaProperty metaProperty = metaClass.getProperty(property); - if (metaProperty != null && metadataTools.isPersistent(metaProperty)) { - result.add(property); - } - } - } - } - - protected List getInterfaceProperties(Class intf) { - List result = new ArrayList<>(); - for (Method method : intf.getDeclaredMethods()) { - if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { - result.add(StringUtils.uncapitalize(method.getName().substring(3))); - } - } - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.cuba.core.entity.Creatable; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.SoftDelete; +import com.haulmont.cuba.core.entity.Updatable; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.*; + +/** + * Class to declare a graph of objects that must be retrieved from the database. + *

+ * A view can be constructed in Java code or defined in XML and deployed + * to the {@link com.haulmont.cuba.core.global.ViewRepository} for recurring usage. + *

+ * There are the following predefined view types: + *
    + *
  • {@link #LOCAL}
  • + *
  • {@link #MINIMAL}
  • + *
  • {@link #BASE}
  • + *
+ * + */ +public class View implements Serializable { + + /** + * Parameters object to be used in constructors. + */ + public static class ViewParams { + protected View src; + protected Class entityClass; + protected String name; + protected boolean includeSystemProperties; + + public ViewParams src(View src) { + this.src = src; + return this; + } + + public ViewParams entityClass(Class entityClass) { + this.entityClass = entityClass; + return this; + } + + public ViewParams name(String name) { + this.name = name; + return this; + } + + public ViewParams includeSystemProperties(boolean includeSystemProperties) { + this.includeSystemProperties = includeSystemProperties; + return this; + } + } + + /** + * Includes all local non-system properties. + */ + public static final String LOCAL = "_local"; + + /** + * Includes only properties contained in {@link com.haulmont.chile.core.annotations.NamePattern}. + */ + public static final String MINIMAL = "_minimal"; + + /** + * Includes all local non-system properties and properties defined by {@link com.haulmont.chile.core.annotations.NamePattern} + * (effectively {@link #MINIMAL} + {@link #LOCAL}). + */ + public static final String BASE = "_base"; + + private static final long serialVersionUID = 4313784222934349594L; + + private Class entityClass; + + private String name; + + private Map properties = new LinkedHashMap<>(); + + private boolean loadPartialEntities; + + public View(Class entityClass) { + this(entityClass, "", true); + } + + public View(Class entityClass, boolean includeSystemProperties) { + this(entityClass, "", includeSystemProperties); + } + + public View(Class entityClass, String name) { + this(entityClass, name, true); + } + + public View(Class entityClass, String name, boolean includeSystemProperties) { + this(new ViewParams().entityClass(entityClass) + .name(name) + .includeSystemProperties(includeSystemProperties) + ); + } + + public View(View src, String name, boolean includeSystemProperties) { + this(src, null, name, includeSystemProperties); + } + + public View(View src, @Nullable Class entityClass, String name, boolean includeSystemProperties) { + this(new ViewParams().src(src) + .entityClass(entityClass != null ? entityClass : src.entityClass) + .name(name) + .includeSystemProperties(includeSystemProperties) + ); + } + + public View(ViewParams viewParams) { + this.entityClass = viewParams.entityClass; + this.name = viewParams.name != null ? viewParams.name : ""; + if (viewParams.includeSystemProperties) { + for (String propertyName : findSystemProperties(entityClass)) { + addProperty(propertyName); + } + } + if (viewParams.src != null) { + this.properties.putAll(viewParams.src.properties); + if (entityClass == null) { + this.entityClass = viewParams.src.entityClass; + } + } + } + + public static View copy(@Nullable View view) { + if (view == null) { + return null; + } + + View.ViewParams viewParams = new View.ViewParams() + .entityClass(view.getEntityClass()) + .name(view.getName()); + View copy = new View(viewParams); + for (ViewProperty property : view.getProperties()) { + copy.addProperty(property.getName(), copy(property.getView()), property.getFetchMode()); + } + + return copy; + } + + /** + * @return entity class this view belongs to + */ + public Class getEntityClass() { + return entityClass; + } + + /** + * @return view name, unique within an entity + */ + public String getName() { + return name; + } + + /** + * @return collection of properties + */ + public Collection getProperties() { + return properties.values(); + } + + /** + * Add a property to this view. + * @param name property name + * @param view a view for a reference attribute, or null + * @param fetchMode fetch mode for a reference attribute + * @return this view instance for chaining + */ + public View addProperty(String name, @Nullable View view, FetchMode fetchMode) { + properties.put(name, new ViewProperty(name, view, fetchMode)); + return this; + } + + @Deprecated + public View addProperty(String name, @Nullable View view, boolean lazy) { + properties.put(name, new ViewProperty(name, view, lazy)); + return this; + } + + /** + * Add a property to this view. + * @param name property name + * @param view a view for a reference attribute, or null + * @return this view instance for chaining + */ + public View addProperty(String name, View view) { + properties.put(name, new ViewProperty(name, view)); + return this; + } + + /** + * Add a property to this view. + * @param name property name + * @return this view instance for chaining + */ + public View addProperty(String name) { + properties.put(name, new ViewProperty(name, null)); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + View view = (View) o; + + return entityClass.equals(view.entityClass) && name.equals(view.name); + } + + @Override + public int hashCode() { + int result = entityClass.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + + @Override + public String toString() { + return entityClass.getName() + "/" + name; + } + + /** + * Get directly owned view property by name. + * @param name property name + * @return view property instance or null if it is not found + */ + @Nullable + public ViewProperty getProperty(String name) { + return properties.get(name); + } + + /** + * Check if a directly owned property with the given name exists in the view. + * @param name property name + * @return true if such property found + */ + public boolean containsProperty(String name) { + return properties.containsKey(name); + } + + /** + * If true, the view affects loading of local attributes. If false, only reference attributes are affected and + * local are always loaded. + * + * @see #setLoadPartialEntities(boolean) + */ + public boolean loadPartialEntities() { + return loadPartialEntities; + } + + /** + * Specifies whether the view affects loading of local attributes. By default only reference attributes are affected and + * local are always loaded. + * + * @param loadPartialEntities true to affect loading of local attributes + * @return this view instance for chaining + */ + public View setLoadPartialEntities(boolean loadPartialEntities) { + this.loadPartialEntities = loadPartialEntities; + return this; + } + + /** + * DEPRECATED since v.6 + */ + @Deprecated + public boolean hasLazyProperties() { + return false; + } + + protected Set findSystemProperties(Class entityClass) { + Set result = new LinkedHashSet<>(); + + Metadata metadata = AppBeans.get(Metadata.NAME); + MetaClass metaClass = metadata.getClassNN(entityClass); + + String pkName = metadata.getTools().getPrimaryKeyName(metaClass); + if (pkName != null) { + result.add(pkName); + } + + addSystemPropertiesFrom(Creatable.class, entityClass, metaClass, metadata, result); + addSystemPropertiesFrom(Updatable.class, entityClass, metaClass, metadata, result); + addSystemPropertiesFrom(SoftDelete.class, entityClass, metaClass, metadata, result); + + return result; + } + + protected void addSystemPropertiesFrom(Class baseClass, Class entityClass, MetaClass metaClass, + Metadata metadata, Set result) { + if (baseClass.isAssignableFrom(entityClass)) { + MetadataTools metadataTools = metadata.getTools(); + for (String property : getInterfaceProperties(baseClass)) { + MetaProperty metaProperty = metaClass.getProperty(property); + if (metaProperty != null && metadataTools.isPersistent(metaProperty)) { + result.add(property); + } + } + } + } + + protected List getInterfaceProperties(Class intf) { + List result = new ArrayList<>(); + for (Method method : intf.getDeclaredMethods()) { + if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { + result.add(StringUtils.uncapitalize(method.getName().substring(3))); + } + } + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/ViewNotFoundException.java b/modules/global/src/com/haulmont/cuba/core/global/ViewNotFoundException.java index f3d6c4c41b..e7eb83e817 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/ViewNotFoundException.java +++ b/modules/global/src/com/haulmont/cuba/core/global/ViewNotFoundException.java @@ -1,28 +1,28 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -/** - * This exception is raised when you try to get nonexistent view by entity/name. - */ -public class ViewNotFoundException extends RuntimeException { - private static final long serialVersionUID = -7372799415486288473L; - - public ViewNotFoundException(String message) { - super(message); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +/** + * This exception is raised when you try to get nonexistent view by entity/name. + */ +public class ViewNotFoundException extends RuntimeException { + private static final long serialVersionUID = -7372799415486288473L; + + public ViewNotFoundException(String message) { + super(message); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/ViewProperty.java b/modules/global/src/com/haulmont/cuba/core/global/ViewProperty.java index daa6703876..66b7ae9abd 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/ViewProperty.java +++ b/modules/global/src/com/haulmont/cuba/core/global/ViewProperty.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global; - -import javax.annotation.Nullable; -import java.io.Serializable; - -/** - * Defines a {@link View} property. Each view property corresponds to a - * {@link com.haulmont.chile.core.model.MetaProperty} with the same name. - * - */ -public class ViewProperty implements Serializable { - - private static final long serialVersionUID = 4098678639930287203L; - - private String name; - - private View view; - - private FetchMode fetchMode = FetchMode.AUTO; - - public ViewProperty(String name, @Nullable View view) { - this(name, view, FetchMode.AUTO); - } - - @Deprecated - public ViewProperty(String name, @Nullable View view, boolean lazy) { - this.name = name; - this.view = view; - } - - public ViewProperty(String name, @Nullable View view, FetchMode fetchMode) { - this.name = name; - this.view = view; - this.fetchMode = fetchMode; - } - - /** - * @return property name that is a metaclass attribute name - */ - public String getName() { - return name; - } - - /** - * @return view of the property if the corresponding metaclass attribute is a reference - */ - @Nullable - public View getView() { - return view; - } - - /** - * @return fetch mode if the property is a reference - */ - public FetchMode getFetchMode() { - return fetchMode; - } - - /** - * DEPRECATED since v.6 - */ - @Deprecated - public boolean isLazy() { - return false; - } - - @Override - public String toString() { - return name; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global; + +import javax.annotation.Nullable; +import java.io.Serializable; + +/** + * Defines a {@link View} property. Each view property corresponds to a + * {@link com.haulmont.chile.core.model.MetaProperty} with the same name. + * + */ +public class ViewProperty implements Serializable { + + private static final long serialVersionUID = 4098678639930287203L; + + private String name; + + private View view; + + private FetchMode fetchMode = FetchMode.AUTO; + + public ViewProperty(String name, @Nullable View view) { + this(name, view, FetchMode.AUTO); + } + + @Deprecated + public ViewProperty(String name, @Nullable View view, boolean lazy) { + this.name = name; + this.view = view; + } + + public ViewProperty(String name, @Nullable View view, FetchMode fetchMode) { + this.name = name; + this.view = view; + this.fetchMode = fetchMode; + } + + /** + * @return property name that is a metaclass attribute name + */ + public String getName() { + return name; + } + + /** + * @return view of the property if the corresponding metaclass attribute is a reference + */ + @Nullable + public View getView() { + return view; + } + + /** + * @return fetch mode if the property is a reference + */ + public FetchMode getFetchMode() { + return fetchMode; + } + + /** + * DEPRECATED since v.6 + */ + @Deprecated + public boolean isLazy() { + return false; + } + + @Override + public String toString() { + return name; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/AbstractJpqlGenerator.java b/modules/global/src/com/haulmont/cuba/core/global/filter/AbstractJpqlGenerator.java index 8d9cd3e37e..5a49d195e4 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/AbstractJpqlGenerator.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/AbstractJpqlGenerator.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import java.util.Iterator; -import java.util.List; - -public abstract class AbstractJpqlGenerator { - public String generateJpql(Condition condition) { - if (condition instanceof LogicalCondition) { - LogicalOp operation = ((LogicalCondition) condition).getOperation(); - List conditions = condition.getConditions(); - if (conditions.isEmpty()) - return ""; - else { - StringBuilder sb = new StringBuilder(); - - if (conditions.size() > 1) - sb.append("("); - - for (Iterator it = conditions.iterator(); it.hasNext(); ) { - Condition currentCondition= it.next(); - sb.append(generateJpql(currentCondition)); - if (it.hasNext()) - sb.append(" ").append(operation.forJpql()).append(" "); - } - - if (conditions.size() > 1) - sb.append(")"); - - return sb.toString(); - } - } else if (condition instanceof Clause) { - return generateClauseText((Clause) condition); - } - throw new UnsupportedOperationException(); - } - - protected abstract String generateClauseText(Clause condition); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import java.util.Iterator; +import java.util.List; + +public abstract class AbstractJpqlGenerator { + public String generateJpql(Condition condition) { + if (condition instanceof LogicalCondition) { + LogicalOp operation = ((LogicalCondition) condition).getOperation(); + List conditions = condition.getConditions(); + if (conditions.isEmpty()) + return ""; + else { + StringBuilder sb = new StringBuilder(); + + if (conditions.size() > 1) + sb.append("("); + + for (Iterator it = conditions.iterator(); it.hasNext(); ) { + Condition currentCondition= it.next(); + sb.append(generateJpql(currentCondition)); + if (it.hasNext()) + sb.append(" ").append(operation.forJpql()).append(" "); + } + + if (conditions.size() > 1) + sb.append(")"); + + return sb.toString(); + } + } else if (condition instanceof Clause) { + return generateClauseText((Clause) condition); + } + throw new UnsupportedOperationException(); + } + + protected abstract String generateClauseText(Clause condition); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/Clause.java b/modules/global/src/com/haulmont/cuba/core/global/filter/Clause.java index 5eea3c5211..8731588330 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/Clause.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/Clause.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -public class Clause extends Condition { - protected String content; - - protected String join; - - protected Set parameters; - - protected Op operator; - - protected String type; - - public Clause(String name, String content, @Nullable String join, @Nullable String operator, @Nullable String type) { - super(name); - - this.content = content; - this.join = join; - this.parameters = ParametersHelper.parseQuery(content); - if (operator != null) { - this.operator = Op.valueOf(operator); - } - this.type = type; - } - - @Override - public List getConditions() { - return Collections.emptyList(); - } - - @Override - public void setConditions(List conditions) { - } - - public String getContent() { - return content; - } - - @Override - public Set getParameters() { - return parameters; - } - - @Override - public Set getJoins() { - return join == null ? Collections.EMPTY_SET : Collections.singleton(join); - } - - public Op getOperator() { - return operator; - } - - public ConditionType getType() { - try { - return ConditionType.valueOf(type); - } catch (IllegalArgumentException e) { - return null; - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class Clause extends Condition { + protected String content; + + protected String join; + + protected Set parameters; + + protected Op operator; + + protected String type; + + public Clause(String name, String content, @Nullable String join, @Nullable String operator, @Nullable String type) { + super(name); + + this.content = content; + this.join = join; + this.parameters = ParametersHelper.parseQuery(content); + if (operator != null) { + this.operator = Op.valueOf(operator); + } + this.type = type; + } + + @Override + public List getConditions() { + return Collections.emptyList(); + } + + @Override + public void setConditions(List conditions) { + } + + public String getContent() { + return content; + } + + @Override + public Set getParameters() { + return parameters; + } + + @Override + public Set getJoins() { + return join == null ? Collections.EMPTY_SET : Collections.singleton(join); + } + + public Op getOperator() { + return operator; + } + + public ConditionType getType() { + try { + return ConditionType.valueOf(type); + } catch (IllegalArgumentException e) { + return null; + } + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/Condition.java b/modules/global/src/com/haulmont/cuba/core/global/filter/Condition.java index 41de030cdc..ba8e5bddef 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/Condition.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/Condition.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import java.util.List; -import java.util.Set; - -public abstract class Condition implements Cloneable { - protected String name; - - public Condition(String name) { - this.name = name; - } - - public Condition copy() { - try { - return (Condition) clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - public abstract List getConditions(); - - public abstract void setConditions(List conditions); - - public abstract Set getParameters(); - - public abstract Set getJoins(); - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import java.util.List; +import java.util.Set; + +public abstract class Condition implements Cloneable { + protected String name; + + public Condition(String name) { + this.name = name; + } + + public Condition copy() { + try { + return (Condition) clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + + public abstract List getConditions(); + + public abstract void setConditions(List conditions); + + public abstract Set getParameters(); + + public abstract Set getJoins(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/DenyingClause.java b/modules/global/src/com/haulmont/cuba/core/global/filter/DenyingClause.java index 5bd012f574..212e1fb1ba 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/DenyingClause.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/DenyingClause.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -public class DenyingClause extends Clause { - - public DenyingClause() { - super("deny", "0<>0", null, null, null); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +public class DenyingClause extends Clause { + + public DenyingClause() { + super("deny", "0<>0", null, null, null); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/FilterJpqlGenerator.java b/modules/global/src/com/haulmont/cuba/core/global/filter/FilterJpqlGenerator.java index a0311640c4..76c3fad104 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/FilterJpqlGenerator.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/FilterJpqlGenerator.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -public class FilterJpqlGenerator extends AbstractJpqlGenerator { - @Override - protected String generateClauseText(Clause condition) { - return condition.getContent(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +public class FilterJpqlGenerator extends AbstractJpqlGenerator { + @Override + protected String generateClauseText(Clause condition) { + return condition.getContent(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/FilterParser.java b/modules/global/src/com/haulmont/cuba/core/global/filter/FilterParser.java index e20122bb22..c62c79ad8a 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/FilterParser.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/FilterParser.java @@ -1,122 +1,122 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.cuba.core.global.QueryTransformer; -import com.haulmont.cuba.core.global.QueryTransformerFactory; -import com.haulmont.cuba.core.global.TemplateHelper; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.dom4j.Attribute; -import org.dom4j.Element; - -import java.util.*; - -public class FilterParser { - protected final Condition root; - - public FilterParser(Element element) { - if (element.elements().isEmpty()) - throw new IllegalArgumentException("filter element is empty"); - Element rootElem = (Element) element.elements().get(0); - root = createCondition(rootElem); - parse(rootElem, root.getConditions()); - } - - public FilterParser(Condition root) { - this.root = root; - } - - public Condition getRoot() { - return root; - } - - protected Condition createCondition(Element conditionElement) { - Condition condition; - String conditionName; - - if (conditionElement.attributeValue("locCaption") == null) { - conditionName = conditionElement.attributeValue("name"); - } else { - conditionName = conditionElement.attributeValue("locCaption"); - } - - if ("c".equals(conditionElement.getName())) { - condition = new Clause(conditionName, conditionElement.getText(), - getJoinValue(conditionElement), - conditionElement.attributeValue("operatorType"), - conditionElement.attributeValue("type")); - // support unary conditions without parameters in text (e.g. "is null") - for (Element paramElem : Dom4j.elements(conditionElement, "param")) { - Set params = ParametersHelper.parseQuery(":" + paramElem.attributeValue("name")); - Attribute javaClass = paramElem.attribute("javaClass"); - if (javaClass != null) { - for (ParameterInfo param : params) { - try { - param.setJavaClass(Class.forName(javaClass.getValue())); - param.setConditionName(conditionName); - param.setValue(paramElem.getText()); - } catch (ClassNotFoundException e) { - //do not fail - } - - if (condition.getParameters().contains(param)) { - for (ParameterInfo parameterInfo : condition.getParameters()) { - if (parameterInfo.equals(param)) { - parameterInfo.setJavaClass(param.getJavaClass()); - parameterInfo.setConditionName(param.getConditionName()); - parameterInfo.setValue(param.getValue()); - } - } - } - } - } - - condition.getParameters().addAll(params); - } - } else { - condition = new LogicalCondition(conditionName, LogicalOp.fromString(conditionElement.getName())); - } - - return condition; - } - - protected String getJoinValue(Element conditionElement) { - Element joinElement = conditionElement.element("join"); - String join; - if (joinElement != null) { - join = joinElement.getText(); - } else { - //for backward compatibility - join = conditionElement.attributeValue("join"); - } - return join; - } - - protected void parse(Element parentElem, List conditions) { - for (Element element : Dom4j.elements(parentElem)) { - if ("param".equals(element.getName()) || "join".equals(element.getName())) - continue; - - Condition condition = createCondition(element); - conditions.add(condition); - parse(element, condition.getConditions()); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.cuba.core.global.QueryTransformer; +import com.haulmont.cuba.core.global.QueryTransformerFactory; +import com.haulmont.cuba.core.global.TemplateHelper; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.dom4j.Attribute; +import org.dom4j.Element; + +import java.util.*; + +public class FilterParser { + protected final Condition root; + + public FilterParser(Element element) { + if (element.elements().isEmpty()) + throw new IllegalArgumentException("filter element is empty"); + Element rootElem = (Element) element.elements().get(0); + root = createCondition(rootElem); + parse(rootElem, root.getConditions()); + } + + public FilterParser(Condition root) { + this.root = root; + } + + public Condition getRoot() { + return root; + } + + protected Condition createCondition(Element conditionElement) { + Condition condition; + String conditionName; + + if (conditionElement.attributeValue("locCaption") == null) { + conditionName = conditionElement.attributeValue("name"); + } else { + conditionName = conditionElement.attributeValue("locCaption"); + } + + if ("c".equals(conditionElement.getName())) { + condition = new Clause(conditionName, conditionElement.getText(), + getJoinValue(conditionElement), + conditionElement.attributeValue("operatorType"), + conditionElement.attributeValue("type")); + // support unary conditions without parameters in text (e.g. "is null") + for (Element paramElem : Dom4j.elements(conditionElement, "param")) { + Set params = ParametersHelper.parseQuery(":" + paramElem.attributeValue("name")); + Attribute javaClass = paramElem.attribute("javaClass"); + if (javaClass != null) { + for (ParameterInfo param : params) { + try { + param.setJavaClass(Class.forName(javaClass.getValue())); + param.setConditionName(conditionName); + param.setValue(paramElem.getText()); + } catch (ClassNotFoundException e) { + //do not fail + } + + if (condition.getParameters().contains(param)) { + for (ParameterInfo parameterInfo : condition.getParameters()) { + if (parameterInfo.equals(param)) { + parameterInfo.setJavaClass(param.getJavaClass()); + parameterInfo.setConditionName(param.getConditionName()); + parameterInfo.setValue(param.getValue()); + } + } + } + } + } + + condition.getParameters().addAll(params); + } + } else { + condition = new LogicalCondition(conditionName, LogicalOp.fromString(conditionElement.getName())); + } + + return condition; + } + + protected String getJoinValue(Element conditionElement) { + Element joinElement = conditionElement.element("join"); + String join; + if (joinElement != null) { + join = joinElement.getText(); + } else { + //for backward compatibility + join = conditionElement.attributeValue("join"); + } + return join; + } + + protected void parse(Element parentElem, List conditions) { + for (Element element : Dom4j.elements(parentElem)) { + if ("param".equals(element.getName()) || "join".equals(element.getName())) + continue; + + Condition condition = createCondition(element); + conditions.add(condition); + parse(element, condition.getConditions()); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/GroovyGenerator.java b/modules/global/src/com/haulmont/cuba/core/global/filter/GroovyGenerator.java index 62f264c5fb..f6d45402c8 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/GroovyGenerator.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/GroovyGenerator.java @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -import static java.lang.String.format; - -public class GroovyGenerator { - protected final EnumSet METHOD_OPS = EnumSet.of(Op.CONTAINS, Op.STARTS_WITH, Op.ENDS_WITH, Op.DOES_NOT_CONTAIN); - protected final EnumSet NEGATIVE_OPS = EnumSet.of(Op.DOES_NOT_CONTAIN, Op.NOT_IN); - - public String generateGroovy(Condition condition) { - if (condition instanceof LogicalCondition) { - LogicalOp operation = ((LogicalCondition) condition).getOperation(); - List conditions = condition.getConditions(); - if (conditions.isEmpty()) { - return ""; - } else { - StringBuilder sb = new StringBuilder(); - - if (conditions.size() > 1) - sb.append("("); - - for (Iterator it = conditions.iterator(); it.hasNext(); ) { - Condition child = it.next(); - sb.append(generateGroovy(child)); - if (it.hasNext()) - sb.append(" ").append(operation.forGroovy()).append(" "); - } - - if (conditions.size() > 1) - sb.append(")"); - - return sb.toString(); - } - } else if (condition instanceof Clause) { - ParameterInfo parameterInfo = condition.getParameters().iterator().next(); - Class javaClass = parameterInfo.getJavaClass(); - if (javaClass == null) { - throw new UnsupportedOperationException(); - } - - Op operator = ((Clause) condition).getOperator(); - String groovyOperator = operator.forGroovy(); - String parameterInfoValue = parameterInfo.getValue(); - - if (parameterInfoValue != null && (operator == Op.IN || operator == Op.NOT_IN)) { - if (parameterInfoValue.startsWith("[") || parameterInfoValue.startsWith("(")) { - parameterInfoValue = parameterInfoValue.replaceAll("[\\[\\]()]", ""); - } - - String[] splittedValues = parameterInfoValue.split(","); - String convertedValue = Arrays.stream(splittedValues) - .map(String::trim) - .map(v -> valueToString(javaClass, v, Op.EQUAL)) - .collect(Collectors.joining(", ", "[", "]")); - parameterInfoValue = convertedValue; - } - - String valueToString = valueToString(javaClass, parameterInfoValue, operator); - - String resultingClause; - if (operator.isUnary()) { - resultingClause = format("{E}.%s %s", condition.getName(), groovyOperator); - } else if (METHOD_OPS.contains(operator)) { - resultingClause = format("{E}.%s.%s(%s)", condition.getName(), groovyOperator, valueToString); - } else { - resultingClause = format("{E}.%s %s %s", condition.getName(), groovyOperator, valueToString); - } - - if (NEGATIVE_OPS.contains(operator)) { - resultingClause = "!(" + resultingClause + ")"; - } - - return resultingClause; - } - - throw new UnsupportedOperationException(); - } - - protected String valueToString(Class javaClass, String value, Op operator) { - if (value == null) { - return "null"; - } else if (Number.class.isAssignableFrom(javaClass) - || Boolean.class.isAssignableFrom(javaClass) - || operator == Op.IN || operator == Op.NOT_IN) { - return value; - } else if (String.class.isAssignableFrom(javaClass)) { - return "'" + value + "'"; - } else { - //the following method should match com.haulmont.cuba.core.sys.SecurityImpl.parseValue() - return format("parse(%s.class, '%s')", javaClass.getCanonicalName(), value); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import static java.lang.String.format; + +public class GroovyGenerator { + protected final EnumSet METHOD_OPS = EnumSet.of(Op.CONTAINS, Op.STARTS_WITH, Op.ENDS_WITH, Op.DOES_NOT_CONTAIN); + protected final EnumSet NEGATIVE_OPS = EnumSet.of(Op.DOES_NOT_CONTAIN, Op.NOT_IN); + + public String generateGroovy(Condition condition) { + if (condition instanceof LogicalCondition) { + LogicalOp operation = ((LogicalCondition) condition).getOperation(); + List conditions = condition.getConditions(); + if (conditions.isEmpty()) { + return ""; + } else { + StringBuilder sb = new StringBuilder(); + + if (conditions.size() > 1) + sb.append("("); + + for (Iterator it = conditions.iterator(); it.hasNext(); ) { + Condition child = it.next(); + sb.append(generateGroovy(child)); + if (it.hasNext()) + sb.append(" ").append(operation.forGroovy()).append(" "); + } + + if (conditions.size() > 1) + sb.append(")"); + + return sb.toString(); + } + } else if (condition instanceof Clause) { + ParameterInfo parameterInfo = condition.getParameters().iterator().next(); + Class javaClass = parameterInfo.getJavaClass(); + if (javaClass == null) { + throw new UnsupportedOperationException(); + } + + Op operator = ((Clause) condition).getOperator(); + String groovyOperator = operator.forGroovy(); + String parameterInfoValue = parameterInfo.getValue(); + + if (parameterInfoValue != null && (operator == Op.IN || operator == Op.NOT_IN)) { + if (parameterInfoValue.startsWith("[") || parameterInfoValue.startsWith("(")) { + parameterInfoValue = parameterInfoValue.replaceAll("[\\[\\]()]", ""); + } + + String[] splittedValues = parameterInfoValue.split(","); + String convertedValue = Arrays.stream(splittedValues) + .map(String::trim) + .map(v -> valueToString(javaClass, v, Op.EQUAL)) + .collect(Collectors.joining(", ", "[", "]")); + parameterInfoValue = convertedValue; + } + + String valueToString = valueToString(javaClass, parameterInfoValue, operator); + + String resultingClause; + if (operator.isUnary()) { + resultingClause = format("{E}.%s %s", condition.getName(), groovyOperator); + } else if (METHOD_OPS.contains(operator)) { + resultingClause = format("{E}.%s.%s(%s)", condition.getName(), groovyOperator, valueToString); + } else { + resultingClause = format("{E}.%s %s %s", condition.getName(), groovyOperator, valueToString); + } + + if (NEGATIVE_OPS.contains(operator)) { + resultingClause = "!(" + resultingClause + ")"; + } + + return resultingClause; + } + + throw new UnsupportedOperationException(); + } + + protected String valueToString(Class javaClass, String value, Op operator) { + if (value == null) { + return "null"; + } else if (Number.class.isAssignableFrom(javaClass) + || Boolean.class.isAssignableFrom(javaClass) + || operator == Op.IN || operator == Op.NOT_IN) { + return value; + } else if (String.class.isAssignableFrom(javaClass)) { + return "'" + value + "'"; + } else { + //the following method should match com.haulmont.cuba.core.sys.SecurityImpl.parseValue() + return format("parse(%s.class, '%s')", javaClass.getCanonicalName(), value); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalCondition.java b/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalCondition.java index f4730ec2e5..7a2878249d 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalCondition.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalCondition.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import java.util.*; - -public class LogicalCondition extends Condition { - private final LogicalOp operation; - - private List conditions = new ArrayList<>(); - - public LogicalCondition(String name, LogicalOp operation) { - super(name); - this.operation = operation; - } - - public LogicalOp getOperation() { - return operation; - } - - @Override - public List getConditions() { - return conditions; - } - - @Override - public void setConditions(List conditions) { - this.conditions = conditions; - } - - @Override - public Set getParameters() { - Set set = new HashSet<>(); - for (Condition condition : conditions) { - set.addAll(condition.getParameters()); - } - return set; - } - - @Override - public Set getJoins() { - Set set = new LinkedHashSet<>(); - for (Condition condition : conditions) { - set.addAll(condition.getJoins()); - } - return set; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import java.util.*; + +public class LogicalCondition extends Condition { + private final LogicalOp operation; + + private List conditions = new ArrayList<>(); + + public LogicalCondition(String name, LogicalOp operation) { + super(name); + this.operation = operation; + } + + public LogicalOp getOperation() { + return operation; + } + + @Override + public List getConditions() { + return conditions; + } + + @Override + public void setConditions(List conditions) { + this.conditions = conditions; + } + + @Override + public Set getParameters() { + Set set = new HashSet<>(); + for (Condition condition : conditions) { + set.addAll(condition.getParameters()); + } + return set; + } + + @Override + public Set getJoins() { + Set set = new LinkedHashSet<>(); + for (Condition condition : conditions) { + set.addAll(condition.getJoins()); + } + return set; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalOp.java b/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalOp.java index 73df68992d..0ae7a1d10d 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalOp.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/LogicalOp.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -public enum LogicalOp { - AND("and", "&&"), - OR("or", "||"); - - private final String forJpql; - private final String forGroovy; - - LogicalOp(String forJpql, String forGroovy) { - this.forJpql = forJpql; - this.forGroovy = forGroovy; - } - - public String forJpql() { - return forJpql; - } - - public String forGroovy() { - return forGroovy; - } - - public static LogicalOp fromString(String str) { - if (AND.forJpql().equals(str)) - return AND; - else if (OR.forJpql().equals(str)) - return OR; - else - throw new IllegalArgumentException("Invalid LogicalOp: " + str); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +public enum LogicalOp { + AND("and", "&&"), + OR("or", "||"); + + private final String forJpql; + private final String forGroovy; + + LogicalOp(String forJpql, String forGroovy) { + this.forJpql = forJpql; + this.forGroovy = forGroovy; + } + + public String forJpql() { + return forJpql; + } + + public String forGroovy() { + return forGroovy; + } + + public static LogicalOp fromString(String str) { + if (AND.forJpql().equals(str)) + return AND; + else if (OR.forJpql().equals(str)) + return OR; + else + throw new IllegalArgumentException("Invalid LogicalOp: " + str); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/Op.java b/modules/global/src/com/haulmont/cuba/core/global/filter/Op.java index b0a72e7e83..bfdbc9fbb2 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/Op.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/Op.java @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; - -public enum Op { - EQUAL("=", "==", false), - IN("in", "in", false), - NOT_IN("not in", "in", false), - NOT_EQUAL("<>", "!=", false), - GREATER(">", ">", false), - GREATER_OR_EQUAL(">=", ">=", false), - LESSER("<", "<", false), - LESSER_OR_EQUAL("<=", "<=", false), - CONTAINS("like", "contains", false), - DOES_NOT_CONTAIN("not like", "contains", false), - NOT_EMPTY("is not null", "!= null", true), - STARTS_WITH("like", "startsWith", false), - DATE_INTERVAL("", "", false), - ENDS_WITH("like", "endsWith", false); - - private String forJpql; - private String forGroovy; - private boolean unary; - - Op(String forJpql,String forGroovy, boolean unary) { - this.forGroovy = forGroovy; - this.unary = unary; - this.forJpql = forJpql; - } - - public String forJpql() { - return forJpql; - } - - public String forGroovy() { - return forGroovy; - } - - public boolean isUnary() { - return unary; - } - - public static Op fromJpqlString(String str) { - for (Op op : values()) { - if (op.forJpql.equals(str)) - return op; - } - throw new UnsupportedOperationException("Unsupported operation: " + str); - } - - public static Op fromGroovyString(String str) { - for (Op op : values()) { - if (op.forGroovy != null && op.forGroovy.equals(str)) - return op; - } - throw new UnsupportedOperationException("Unsupported operation: " + str); - } - - public String getLocCaption() { - return AppBeans.get(Messages.class).getMainMessage("Op." + this.name()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; + +public enum Op { + EQUAL("=", "==", false), + IN("in", "in", false), + NOT_IN("not in", "in", false), + NOT_EQUAL("<>", "!=", false), + GREATER(">", ">", false), + GREATER_OR_EQUAL(">=", ">=", false), + LESSER("<", "<", false), + LESSER_OR_EQUAL("<=", "<=", false), + CONTAINS("like", "contains", false), + DOES_NOT_CONTAIN("not like", "contains", false), + NOT_EMPTY("is not null", "!= null", true), + STARTS_WITH("like", "startsWith", false), + DATE_INTERVAL("", "", false), + ENDS_WITH("like", "endsWith", false); + + private String forJpql; + private String forGroovy; + private boolean unary; + + Op(String forJpql,String forGroovy, boolean unary) { + this.forGroovy = forGroovy; + this.unary = unary; + this.forJpql = forJpql; + } + + public String forJpql() { + return forJpql; + } + + public String forGroovy() { + return forGroovy; + } + + public boolean isUnary() { + return unary; + } + + public static Op fromJpqlString(String str) { + for (Op op : values()) { + if (op.forJpql.equals(str)) + return op; + } + throw new UnsupportedOperationException("Unsupported operation: " + str); + } + + public static Op fromGroovyString(String str) { + for (Op op : values()) { + if (op.forGroovy != null && op.forGroovy.equals(str)) + return op; + } + throw new UnsupportedOperationException("Unsupported operation: " + str); + } + + public String getLocCaption() { + return AppBeans.get(Messages.class).getMainMessage("Op." + this.name()); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/ParameterInfo.java b/modules/global/src/com/haulmont/cuba/core/global/filter/ParameterInfo.java index 12ae3edc3c..7742a111c2 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/ParameterInfo.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/ParameterInfo.java @@ -1,121 +1,121 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import javax.annotation.Nullable; - -public class ParameterInfo { - - public enum Type { - DATASOURCE("ds"), - COMPONENT("component"), - PARAM("param"), - SESSION("session"), - CUSTOM("custom"); - - private String prefix; - - Type(String prefix) { - this.prefix = prefix; - } - - public String getPrefix() { - return prefix; - } - } - - protected Type type; - protected String path; - protected Class javaClass; - protected String conditionName; - protected boolean caseInsensitive; - protected String value; - - ParameterInfo(String name, Type type, boolean caseInsensitive) { - this.path = name; - this.type = type; - this.caseInsensitive = caseInsensitive; - } - - public Type getType() { - return type; - } - - public String getPath() { - return path; - } - - public String getName() { - return (type.getPrefix() + "$" + path); - } - - public String getFlatName() { - return (type.getPrefix() + "." + path).replaceAll("\\.", "_"); - } - - public boolean isCaseInsensitive() { - return caseInsensitive; - } - - @Nullable - public Class getJavaClass() { - return javaClass; - } - - public void setJavaClass(Class javaClass) { - this.javaClass = javaClass; - } - - @Nullable - public String getConditionName() { - return conditionName; - } - - public void setConditionName(String conditionName) { - this.conditionName = conditionName; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ParameterInfo that = (ParameterInfo) o; - - return path.equals(that.path) && type == that.type; - } - - @Override - public int hashCode() { - int result = type.hashCode(); - result = 31 * result + path.hashCode(); - return result; - } - - @Override - public String toString() { - return type + " : " + path; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import javax.annotation.Nullable; + +public class ParameterInfo { + + public enum Type { + DATASOURCE("ds"), + COMPONENT("component"), + PARAM("param"), + SESSION("session"), + CUSTOM("custom"); + + private String prefix; + + Type(String prefix) { + this.prefix = prefix; + } + + public String getPrefix() { + return prefix; + } + } + + protected Type type; + protected String path; + protected Class javaClass; + protected String conditionName; + protected boolean caseInsensitive; + protected String value; + + ParameterInfo(String name, Type type, boolean caseInsensitive) { + this.path = name; + this.type = type; + this.caseInsensitive = caseInsensitive; + } + + public Type getType() { + return type; + } + + public String getPath() { + return path; + } + + public String getName() { + return (type.getPrefix() + "$" + path); + } + + public String getFlatName() { + return (type.getPrefix() + "." + path).replaceAll("\\.", "_"); + } + + public boolean isCaseInsensitive() { + return caseInsensitive; + } + + @Nullable + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + } + + @Nullable + public String getConditionName() { + return conditionName; + } + + public void setConditionName(String conditionName) { + this.conditionName = conditionName; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ParameterInfo that = (ParameterInfo) o; + + return path.equals(that.path) && type == that.type; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + path.hashCode(); + return result; + } + + @Override + public String toString() { + return type + " : " + path; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/ParametersHelper.java b/modules/global/src/com/haulmont/cuba/core/global/filter/ParametersHelper.java index d21166cb64..51e7ed7f68 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/ParametersHelper.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/ParametersHelper.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class ParametersHelper { - - public static final String QUERY_PARAMETERS_RE = ":(\\(\\?i\\))?([\\w\\.\\$]+)"; - public static final Pattern QUERY_PARAMETERS_PATTERN = Pattern.compile(QUERY_PARAMETERS_RE); - public static final String CASE_INSENSITIVE_MARKER = "(?i)"; - - public static final Pattern TEMPL_CLAUSE_PATTERN = Pattern.compile("<#[^>]*>"); - - public static final Pattern TEMPL_PARAM_PATTERN; // "((component)|(param)|(ds)|(session)|(custom))\\$[\\w\\.]+" - - static { - StringBuilder sb = new StringBuilder("("); - ParameterInfo.Type[] values = ParameterInfo.Type.values(); - for (int i = 0, valuesLength = values.length; i < valuesLength; i++) { - sb.append("(").append(values[i].getPrefix()).append(")"); - if (i < valuesLength - 1) { - sb.append("|"); - } - } - sb.append(")").append("\\$[\\w\\.]+"); - TEMPL_PARAM_PATTERN = Pattern.compile(sb.toString()); - } - - private ParametersHelper() { - } - - public static Set extractNames(String text) { - Set set = new HashSet<>(); - - Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(text); - while (matcher.find()) { - set.add(matcher.group(2)); - } - - return set; - } - - public static Set parseQuery(String query) { - Set infos = new HashSet<>(); - - Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(query); - while (matcher.find()) { - final ParameterInfo info = parse(matcher); - infos.add(info); - } - - return infos; - } - - public static ParameterInfo[] parseQuery(String query, @Nullable QueryFilter filter) { - Set infos = new HashSet<>(); - - Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(query); - while (matcher.find()) { - final ParameterInfo info = parse(matcher); - infos.add(info); - } - - // Add parameters used by freemarker clauses - Matcher templMatcher = TEMPL_CLAUSE_PATTERN.matcher(query); - while (templMatcher.find()) { - String templClause = templMatcher.group(); - - Matcher paramMatcher = TEMPL_PARAM_PATTERN.matcher(templClause); - while (paramMatcher.find()) { - String param = paramMatcher.group(); - infos.add(parse(param, false)); - } - } - - if (filter != null) { - infos.addAll(filter.getParameters()); - } - - return infos.toArray(new ParameterInfo[infos.size()]); - } - - private static ParameterInfo parse(Matcher matcher) { - boolean caseInsensitive = !StringUtils.isBlank(matcher.group(1)); - final String param = matcher.group(2); - - return parse(param, caseInsensitive); - } - - private static ParameterInfo parse(String param, boolean caseInsensitive) { - final String[] strings = param.split("\\$"); - if (strings.length != 2) { - throw new IllegalStateException(String.format("Illegal parameter info '%s'", param)); - } - final String source = strings[0]; - final String name = strings[1]; - - for (ParameterInfo.Type type : ParameterInfo.Type.values()) { - if (type.getPrefix().equals(source)) { - return new ParameterInfo(name, type, caseInsensitive); - } - } - throw new IllegalStateException(String.format("Illegal parameter info '%s'", param)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class ParametersHelper { + + public static final String QUERY_PARAMETERS_RE = ":(\\(\\?i\\))?([\\w\\.\\$]+)"; + public static final Pattern QUERY_PARAMETERS_PATTERN = Pattern.compile(QUERY_PARAMETERS_RE); + public static final String CASE_INSENSITIVE_MARKER = "(?i)"; + + public static final Pattern TEMPL_CLAUSE_PATTERN = Pattern.compile("<#[^>]*>"); + + public static final Pattern TEMPL_PARAM_PATTERN; // "((component)|(param)|(ds)|(session)|(custom))\\$[\\w\\.]+" + + static { + StringBuilder sb = new StringBuilder("("); + ParameterInfo.Type[] values = ParameterInfo.Type.values(); + for (int i = 0, valuesLength = values.length; i < valuesLength; i++) { + sb.append("(").append(values[i].getPrefix()).append(")"); + if (i < valuesLength - 1) { + sb.append("|"); + } + } + sb.append(")").append("\\$[\\w\\.]+"); + TEMPL_PARAM_PATTERN = Pattern.compile(sb.toString()); + } + + private ParametersHelper() { + } + + public static Set extractNames(String text) { + Set set = new HashSet<>(); + + Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(text); + while (matcher.find()) { + set.add(matcher.group(2)); + } + + return set; + } + + public static Set parseQuery(String query) { + Set infos = new HashSet<>(); + + Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(query); + while (matcher.find()) { + final ParameterInfo info = parse(matcher); + infos.add(info); + } + + return infos; + } + + public static ParameterInfo[] parseQuery(String query, @Nullable QueryFilter filter) { + Set infos = new HashSet<>(); + + Matcher matcher = QUERY_PARAMETERS_PATTERN.matcher(query); + while (matcher.find()) { + final ParameterInfo info = parse(matcher); + infos.add(info); + } + + // Add parameters used by freemarker clauses + Matcher templMatcher = TEMPL_CLAUSE_PATTERN.matcher(query); + while (templMatcher.find()) { + String templClause = templMatcher.group(); + + Matcher paramMatcher = TEMPL_PARAM_PATTERN.matcher(templClause); + while (paramMatcher.find()) { + String param = paramMatcher.group(); + infos.add(parse(param, false)); + } + } + + if (filter != null) { + infos.addAll(filter.getParameters()); + } + + return infos.toArray(new ParameterInfo[infos.size()]); + } + + private static ParameterInfo parse(Matcher matcher) { + boolean caseInsensitive = !StringUtils.isBlank(matcher.group(1)); + final String param = matcher.group(2); + + return parse(param, caseInsensitive); + } + + private static ParameterInfo parse(String param, boolean caseInsensitive) { + final String[] strings = param.split("\\$"); + if (strings.length != 2) { + throw new IllegalStateException(String.format("Illegal parameter info '%s'", param)); + } + final String source = strings[0]; + final String name = strings[1]; + + for (ParameterInfo.Type type : ParameterInfo.Type.values()) { + if (type.getPrefix().equals(source)) { + return new ParameterInfo(name, type, caseInsensitive); + } + } + throw new IllegalStateException(String.format("Illegal parameter info '%s'", param)); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/QueryFilter.java b/modules/global/src/com/haulmont/cuba/core/global/filter/QueryFilter.java index 4a0bebf11e..1fb261d019 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/QueryFilter.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/QueryFilter.java @@ -1,130 +1,130 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.cuba.core.global.*; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.dom4j.Element; - -import java.util.*; -import java.util.function.Predicate; - -public class QueryFilter extends FilterParser { - - protected boolean enableSessionParams = AppBeans.get(Configuration.class) - .getConfig(GlobalConfig.class).getEnableSessionParamsInQueryFilter(); - - public QueryFilter(Condition condition) { - super(condition); - } - - public QueryFilter(Element element) { - super(element); - } - - public static QueryFilter merge(QueryFilter src1, QueryFilter src2) { - if (src1 == null || src2 == null) - throw new IllegalArgumentException("Source query filter is null"); - - Condition root = new LogicalCondition("root", LogicalOp.AND); - root.getConditions().add(src1.getRoot()); - root.getConditions().add(src2.getRoot()); - - QueryFilter queryFilter = new QueryFilter(root); - return queryFilter; - } - - public Collection getParameters() { - return root.getParameters(); - } - - public String processQuery(String query, Map paramValues) { - Set params = new HashSet<>(); - for (Map.Entry entry : paramValues.entrySet()) { - if (paramValueIsOk(entry.getValue())) - params.add(entry.getKey()); - } - - query = TemplateHelper.processTemplate(query, paramValues); - QueryTransformer transformer = QueryTransformerFactory.createTransformer(query); - - if (isActual(root, params)) { - Condition refined = refine(root, params); - String where = new FilterJpqlGenerator().generateJpql(refined); - - if (!StringUtils.isBlank(where)) { - Set joins = refined.getJoins(); - if (!joins.isEmpty()) { - String joinsStr = new StrBuilder().appendWithSeparators(joins, " ").toString(); - transformer.addJoinAndWhere(joinsStr, where); - } else { - transformer.addWhere(where); - } - } - } - return transformer.getResult(); - } - - protected boolean paramValueIsOk(Object value) { - if (value instanceof String) - return !StringUtils.isBlank((String) value); - else return value != null; - } - - protected Condition refine(Condition src, Set params) { - Condition copy = src.copy(); - List list = new ArrayList<>(); - for (Condition condition : src.getConditions()) { - if (isActual(condition, params)) { - list.add(refine(condition, params)); - } - } - copy.setConditions(list.isEmpty() ? Collections.EMPTY_LIST : list); - return copy; - } - - protected boolean isActual(Condition condition, Set params) { - Set declaredParams = condition.getParameters(); - - if (declaredParams.isEmpty()) - return true; - if (enableSessionParams) { - Predicate paramHasValue = paramInfo -> params.contains(paramInfo.getName()); - if (condition.getConditions().isEmpty()) { - // for leaf condition all parameters must have values - return declaredParams.stream().allMatch(paramHasValue); - } else { - // for branch conditions at least some parameters must have values - return declaredParams.stream().anyMatch(paramHasValue); - } - } else { - // Return true only if declared params have values and there is at least one non-session parameter among them. - // This is necessary to exclude generic filter conditions that contain only session parameters. Otherwise - // there is no way to handle exclusion. Unfortunately this imposes the restriction on custom filters design: - // condition with session-only parameters must be avoided, they must be coded as part of main query body or as - // part of another condition. - boolean found = false; - for (ParameterInfo paramInfo : declaredParams) { - if (params.contains(paramInfo.getName())) { - found = found || !paramInfo.getType().equals(ParameterInfo.Type.SESSION); - } - } - return found; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.cuba.core.global.*; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.dom4j.Element; + +import java.util.*; +import java.util.function.Predicate; + +public class QueryFilter extends FilterParser { + + protected boolean enableSessionParams = AppBeans.get(Configuration.class) + .getConfig(GlobalConfig.class).getEnableSessionParamsInQueryFilter(); + + public QueryFilter(Condition condition) { + super(condition); + } + + public QueryFilter(Element element) { + super(element); + } + + public static QueryFilter merge(QueryFilter src1, QueryFilter src2) { + if (src1 == null || src2 == null) + throw new IllegalArgumentException("Source query filter is null"); + + Condition root = new LogicalCondition("root", LogicalOp.AND); + root.getConditions().add(src1.getRoot()); + root.getConditions().add(src2.getRoot()); + + QueryFilter queryFilter = new QueryFilter(root); + return queryFilter; + } + + public Collection getParameters() { + return root.getParameters(); + } + + public String processQuery(String query, Map paramValues) { + Set params = new HashSet<>(); + for (Map.Entry entry : paramValues.entrySet()) { + if (paramValueIsOk(entry.getValue())) + params.add(entry.getKey()); + } + + query = TemplateHelper.processTemplate(query, paramValues); + QueryTransformer transformer = QueryTransformerFactory.createTransformer(query); + + if (isActual(root, params)) { + Condition refined = refine(root, params); + String where = new FilterJpqlGenerator().generateJpql(refined); + + if (!StringUtils.isBlank(where)) { + Set joins = refined.getJoins(); + if (!joins.isEmpty()) { + String joinsStr = new StrBuilder().appendWithSeparators(joins, " ").toString(); + transformer.addJoinAndWhere(joinsStr, where); + } else { + transformer.addWhere(where); + } + } + } + return transformer.getResult(); + } + + protected boolean paramValueIsOk(Object value) { + if (value instanceof String) + return !StringUtils.isBlank((String) value); + else return value != null; + } + + protected Condition refine(Condition src, Set params) { + Condition copy = src.copy(); + List list = new ArrayList<>(); + for (Condition condition : src.getConditions()) { + if (isActual(condition, params)) { + list.add(refine(condition, params)); + } + } + copy.setConditions(list.isEmpty() ? Collections.EMPTY_LIST : list); + return copy; + } + + protected boolean isActual(Condition condition, Set params) { + Set declaredParams = condition.getParameters(); + + if (declaredParams.isEmpty()) + return true; + if (enableSessionParams) { + Predicate paramHasValue = paramInfo -> params.contains(paramInfo.getName()); + if (condition.getConditions().isEmpty()) { + // for leaf condition all parameters must have values + return declaredParams.stream().allMatch(paramHasValue); + } else { + // for branch conditions at least some parameters must have values + return declaredParams.stream().anyMatch(paramHasValue); + } + } else { + // Return true only if declared params have values and there is at least one non-session parameter among them. + // This is necessary to exclude generic filter conditions that contain only session parameters. Otherwise + // there is no way to handle exclusion. Unfortunately this imposes the restriction on custom filters design: + // condition with session-only parameters must be avoided, they must be coded as part of main query body or as + // part of another condition. + boolean found = false; + for (ParameterInfo paramInfo : declaredParams) { + if (params.contains(paramInfo.getName())) { + found = found || !paramInfo.getType().equals(ParameterInfo.Type.SESSION); + } + } + return found; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/filter/SecurityJpqlGenerator.java b/modules/global/src/com/haulmont/cuba/core/global/filter/SecurityJpqlGenerator.java index a1c053525d..b732cacb69 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/filter/SecurityJpqlGenerator.java +++ b/modules/global/src/com/haulmont/cuba/core/global/filter/SecurityJpqlGenerator.java @@ -1,97 +1,97 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global.filter; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.cuba.core.entity.*; - -import java.util.Arrays; -import java.util.UUID; -import java.util.stream.Collectors; - -import static java.lang.String.format; - -public class SecurityJpqlGenerator extends AbstractJpqlGenerator { - @Override - protected String generateClauseText(Clause condition) { - ParameterInfo parameterInfo = condition.getParameters().iterator().next(); - Class javaClass = parameterInfo.getJavaClass(); - if (javaClass == null) { - throw new UnsupportedOperationException(); - } - - Op operator = condition.getOperator(); - String jpqlOperator = operator.forJpql(); - String parameterInfoValue = parameterInfo.getValue(); - - String valueToString = valueToString(javaClass, parameterInfoValue, operator); - - if (condition.getType() == ConditionType.RUNTIME_PROPERTY) { - return condition.getContent().replace(":" + parameterInfo.getName(), valueToString); - } else if (operator.isUnary()) { - return format("{E}.%s %s", condition.getName(), jpqlOperator); - } else if (Entity.class.isAssignableFrom(javaClass)) { - return String.format("{E}.%s.id %s %s", condition.getName(), jpqlOperator, valueToString); - } else { - return String.format("{E}.%s %s %s", condition.getName(), jpqlOperator, valueToString); - } - } - - protected String valueToString(Class javaClass, String value, Op operator) { - if (value == null) { - return "null"; - } else if (operator == Op.IN || operator == Op.NOT_IN) { - // IN operator has its own logic, because we have to convert string with default values to the right form - if (value.startsWith("[") || value.startsWith("(")) { - value = value.replaceAll("[\\[\\]()]", ""); - } - - String[] splittedValues = value.split(","); - String convertedValue = Arrays.stream(splittedValues) - .map(String::trim) - .map(v -> valueToString(javaClass, v, Op.EQUAL)) - .collect(Collectors.joining(", ", "(", ")")); - return convertedValue; - } else if (Number.class.isAssignableFrom(javaClass) - || Boolean.class.isAssignableFrom(javaClass)) { - return value; - } else if (EnumClass.class.isAssignableFrom(javaClass)) { - //noinspection unchecked - Enum enumValue = Enum.valueOf(javaClass, value); - Object enumId = ((EnumClass) enumValue).getId(); - return (enumId instanceof Number) ? enumId.toString() : "'" + enumId + "'"; - } else if (Entity.class.isAssignableFrom(javaClass)) { - if (BaseIntegerIdEntity.class.isAssignableFrom(javaClass) - || BaseLongIdEntity.class.isAssignableFrom(javaClass) - || BaseDbGeneratedIdEntity.class.isAssignableFrom(javaClass)) { - return value; - } else { - return "'" + value + "'"; - } - } else { - if (operator == Op.CONTAINS || operator == Op.DOES_NOT_CONTAIN) { - return "'%" + value + "%'"; - } else if (operator == Op.STARTS_WITH) { - return "'" + value + "%'"; - } else if (operator == Op.ENDS_WITH) { - return "'%" + value + "'"; - } - return "'" + value + "'"; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global.filter; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.cuba.core.entity.*; + +import java.util.Arrays; +import java.util.UUID; +import java.util.stream.Collectors; + +import static java.lang.String.format; + +public class SecurityJpqlGenerator extends AbstractJpqlGenerator { + @Override + protected String generateClauseText(Clause condition) { + ParameterInfo parameterInfo = condition.getParameters().iterator().next(); + Class javaClass = parameterInfo.getJavaClass(); + if (javaClass == null) { + throw new UnsupportedOperationException(); + } + + Op operator = condition.getOperator(); + String jpqlOperator = operator.forJpql(); + String parameterInfoValue = parameterInfo.getValue(); + + String valueToString = valueToString(javaClass, parameterInfoValue, operator); + + if (condition.getType() == ConditionType.RUNTIME_PROPERTY) { + return condition.getContent().replace(":" + parameterInfo.getName(), valueToString); + } else if (operator.isUnary()) { + return format("{E}.%s %s", condition.getName(), jpqlOperator); + } else if (Entity.class.isAssignableFrom(javaClass)) { + return String.format("{E}.%s.id %s %s", condition.getName(), jpqlOperator, valueToString); + } else { + return String.format("{E}.%s %s %s", condition.getName(), jpqlOperator, valueToString); + } + } + + protected String valueToString(Class javaClass, String value, Op operator) { + if (value == null) { + return "null"; + } else if (operator == Op.IN || operator == Op.NOT_IN) { + // IN operator has its own logic, because we have to convert string with default values to the right form + if (value.startsWith("[") || value.startsWith("(")) { + value = value.replaceAll("[\\[\\]()]", ""); + } + + String[] splittedValues = value.split(","); + String convertedValue = Arrays.stream(splittedValues) + .map(String::trim) + .map(v -> valueToString(javaClass, v, Op.EQUAL)) + .collect(Collectors.joining(", ", "(", ")")); + return convertedValue; + } else if (Number.class.isAssignableFrom(javaClass) + || Boolean.class.isAssignableFrom(javaClass)) { + return value; + } else if (EnumClass.class.isAssignableFrom(javaClass)) { + //noinspection unchecked + Enum enumValue = Enum.valueOf(javaClass, value); + Object enumId = ((EnumClass) enumValue).getId(); + return (enumId instanceof Number) ? enumId.toString() : "'" + enumId + "'"; + } else if (Entity.class.isAssignableFrom(javaClass)) { + if (BaseIntegerIdEntity.class.isAssignableFrom(javaClass) + || BaseLongIdEntity.class.isAssignableFrom(javaClass) + || BaseDbGeneratedIdEntity.class.isAssignableFrom(javaClass)) { + return value; + } else { + return "'" + value + "'"; + } + } else { + if (operator == Op.CONTAINS || operator == Op.DOES_NOT_CONTAIN) { + return "'%" + value + "%'"; + } else if (operator == Op.STARTS_WITH) { + return "'" + value + "%'"; + } else if (operator == Op.ENDS_WITH) { + return "'%" + value + "'"; + } + return "'" + value + "'"; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/global/messages.properties b/modules/global/src/com/haulmont/cuba/core/global/messages.properties index ca73751f62..42b6025f8c 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/messages.properties +++ b/modules/global/src/com/haulmont/cuba/core/global/messages.properties @@ -1,38 +1,38 @@ - -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -ClientType.WEB = Web -ClientType.DESKTOP = Desktop -ClientType.PORTAL = Portal - -DeletePolicy.DENY = Deny -DeletePolicy.CASCADE = Cascade -DeletePolicy.UNLINK = Unlink - -LockInfo = Lock Info -LockInfo.entityId = Entity Id -LockInfo.entityName = Entity Name -LockInfo.since = Since -LockInfo.user = User - -SendingStatus.QUEUE = Queue -SendingStatus.SENDING = Sending -SendingStatus.SENT = Sent -SendingStatus.NOTSENT = Not sent - -onBehalfOf=%s on behalf of %s + +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +ClientType.WEB = Web +ClientType.DESKTOP = Desktop +ClientType.PORTAL = Portal + +DeletePolicy.DENY = Deny +DeletePolicy.CASCADE = Cascade +DeletePolicy.UNLINK = Unlink + +LockInfo = Lock Info +LockInfo.entityId = Entity Id +LockInfo.entityName = Entity Name +LockInfo.since = Since +LockInfo.user = User + +SendingStatus.QUEUE = Queue +SendingStatus.SENDING = Sending +SendingStatus.SENT = Sent +SendingStatus.NOTSENT = Not sent + +onBehalfOf=%s on behalf of %s diff --git a/modules/global/src/com/haulmont/cuba/core/global/messages_ru.properties b/modules/global/src/com/haulmont/cuba/core/global/messages_ru.properties index af4d06ccf5..deda75414d 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/messages_ru.properties +++ b/modules/global/src/com/haulmont/cuba/core/global/messages_ru.properties @@ -1,38 +1,38 @@ - -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -ClientType.WEB = Web -ClientType.DESKTOP = Desktop -ClientType.PORTAL = Portal - -DeletePolicy.DENY = Deny -DeletePolicy.CASCADE = Cascade -DeletePolicy.UNLINK = Unlink - -LockInfo = Lock Info -LockInfo.entityId = Entity Id -LockInfo.entityName = Entity Name -LockInfo.since = Since -LockInfo.user = User - -SendingStatus.QUEUE = Поставлено на отправку -SendingStatus.SENDING = Отправляется -SendingStatus.SENT = Отправлено -SendingStatus.NOTSENT = Отправка не удалась - -onBehalfOf=%s от имени %s + +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +ClientType.WEB = Web +ClientType.DESKTOP = Desktop +ClientType.PORTAL = Portal + +DeletePolicy.DENY = Deny +DeletePolicy.CASCADE = Cascade +DeletePolicy.UNLINK = Unlink + +LockInfo = Lock Info +LockInfo.entityId = Entity Id +LockInfo.entityName = Entity Name +LockInfo.since = Since +LockInfo.user = User + +SendingStatus.QUEUE = Поставлено на отправку +SendingStatus.SENDING = Отправляется +SendingStatus.SENT = Отправлено +SendingStatus.NOTSENT = Отправка не удалась + +onBehalfOf=%s от имени %s diff --git a/modules/global/src/com/haulmont/cuba/core/global/view.xsd b/modules/global/src/com/haulmont/cuba/core/global/view.xsd index fb1c8aecc4..93378b86e0 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/view.xsd +++ b/modules/global/src/com/haulmont/cuba/core/global/view.xsd @@ -1,69 +1,69 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/global/src/com/haulmont/cuba/core/sys/AbstractViewRepository.java b/modules/global/src/com/haulmont/cuba/core/sys/AbstractViewRepository.java index 003f8c9bc5..9d19053b22 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/AbstractViewRepository.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/AbstractViewRepository.java @@ -1,747 +1,747 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.Range; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Base implementation of the {@link ViewRepository}. Contains methods to store {@link View} objects and deploy - * them from XML.
- *
Don't replace this class completely, because the framework uses it directly. - */ -public class AbstractViewRepository implements ViewRepository { - - private final Logger log = LoggerFactory.getLogger(AbstractViewRepository.class); - - protected List readFileNames = new LinkedList<>(); - - protected Map> storage = new ConcurrentHashMap<>(); - - @Inject - protected Metadata metadata; - - @Inject - protected Resources resources; - - protected volatile boolean initialized; - - protected ReadWriteLock lock = new ReentrantReadWriteLock(); - - protected void checkInitialized() { - if (!initialized) { - lock.readLock().unlock(); - lock.writeLock().lock(); - try { - if (!initialized) { - log.info("Initializing views"); - init(); - initialized = true; - } - } finally { - lock.readLock().lock(); - lock.writeLock().unlock(); - } - } - } - - protected void init() { - StopWatch initTiming = new Log4JStopWatch("ViewRepository.init." + getClass().getSimpleName()); - - storage.clear(); - readFileNames.clear(); - - String configName = AppContext.getProperty("cuba.viewsConfig"); - if (!StringUtils.isBlank(configName)) { - Element rootElem = DocumentHelper.createDocument().addElement("views"); - - StrTokenizer tokenizer = new StrTokenizer(configName); - for (String fileName : tokenizer.getTokenArray()) { - addFile(rootElem, fileName); - } - - checkDuplicates(rootElem); - - for (Element viewElem : Dom4j.elements(rootElem, "view")) { - deployView(rootElem, viewElem, new HashSet<>()); - } - } - - initTiming.stop(); - } - - protected void checkDuplicates(Element rootElem) { - Set checked = new HashSet<>(); - for (Element viewElem : Dom4j.elements(rootElem, "view")) { - String viewName = getViewName(viewElem); - String key = getMetaClass(viewElem) + "/" + viewName; - if (!Boolean.parseBoolean(viewElem.attributeValue("overwrite"))) { - String extend = viewElem.attributeValue("extends"); - if (!StringUtils.equals(extend, viewName) && checked.contains(key)) { - log.warn("Duplicate view definition without 'overwrite' attribute and not extending parent view: " + key); - } - } - checked.add(key); - } - } - - protected void addFile(Element commonRootElem, String fileName) { - if (readFileNames.contains(fileName)) - return; - - log.debug("Deploying views config: " + fileName); - readFileNames.add(fileName); - - InputStream stream = null; - try { - stream = resources.getResourceAsStream(fileName); - if (stream == null) { - throw new IllegalStateException("Resource is not found: " + fileName); - } - - SAXReader reader = new SAXReader(); - Document doc; - try { - doc = reader.read(new InputStreamReader(stream, StandardCharsets.UTF_8)); - } catch (DocumentException e) { - throw new RuntimeException("Unable to parse view file " + fileName, e); - } - Element rootElem = doc.getRootElement(); - - for (Element includeElem : Dom4j.elements(rootElem, "include")) { - String incFile = includeElem.attributeValue("file"); - if (!StringUtils.isBlank(incFile)) - addFile(commonRootElem, incFile); - } - - for (Element viewElem : Dom4j.elements(rootElem, "view")) { - commonRootElem.add(viewElem.createCopy()); - } - } finally { - IOUtils.closeQuietly(stream); - } - } - - public void reset() { - initialized = false; - } - - /** - * Get View for an entity. - * - * @param entityClass entity class - * @param name view name - * @return view instance. Throws {@link com.haulmont.cuba.core.global.ViewNotFoundException} if not found. - */ - @Override - public View getView(Class entityClass, String name) { - return getView(metadata.getClassNN(entityClass), name); - } - - /** - * Get View for an entity. - * - * @param metaClass entity class - * @param name view name - * @return view instance. Throws {@link com.haulmont.cuba.core.global.ViewNotFoundException} if not found. - */ - @Override - public View getView(MetaClass metaClass, String name) { - Preconditions.checkNotNullArgument(metaClass, "MetaClass is null"); - - View view = findView(metaClass, name); - - if (view == null) { - throw new ViewNotFoundException(String.format("View %s/%s not found", metaClass.getName(), name)); - } - return view; - } - - /** - * Searches for a View for an entity - * - * @param metaClass entity class - * @param name view name - * @return view instance or null if no view found - */ - @Override - @Nullable - public View findView(MetaClass metaClass, @Nullable String name) { - if (metaClass == null) { - throw new IllegalArgumentException("Passed metaClass should not be null"); - } - - if (name == null) { - return null; - } - - lock.readLock().lock(); - try { - checkInitialized(); - - View view = retrieveView(metaClass, name, new HashSet<>()); - return copyView(view); - } finally { - lock.readLock().unlock(); - } - } - - protected View copyView(@Nullable View view) { - if (view == null) { - return null; - } - - View.ViewParams viewParams = new View.ViewParams() - .entityClass(view.getEntityClass()) - .name(view.getName()); - View copy = new View(viewParams); - for (ViewProperty property : view.getProperties()) { - copy.addProperty(property.getName(), copyView(property.getView()), property.getFetchMode()); - } - - return copy; - } - - @Override - public Collection getViewNames(MetaClass metaClass) { - Preconditions.checkNotNullArgument(metaClass, "MetaClass is null"); - lock.readLock().lock(); - try { - checkInitialized(); - Map viewMap = storage.get(metaClass); - if (viewMap != null && !viewMap.isEmpty()) { - Set keySet = new HashSet<>(viewMap.keySet()); - keySet.remove(View.LOCAL); - keySet.remove(View.MINIMAL); - return keySet; - } else { - return Collections.emptyList(); - } - } finally { - lock.readLock().unlock(); - } - } - - @Override - public Collection getViewNames(Class entityClass) { - Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); - MetaClass metaClass = metadata.getClassNN(entityClass); - return getViewNames(metaClass); - } - - @SuppressWarnings("unchecked") - protected View deployDefaultView(MetaClass metaClass, String name, Set visited) { - Class javaClass = metaClass.getJavaClass(); - - ViewInfo info = new ViewInfo(javaClass, name); - if (visited.contains(info)) { - throw new DevelopmentException(String.format("Views cannot have cyclic references. View %s for class %s", - name, metaClass.getName())); - } - - View view; - if (View.LOCAL.equals(name)) { - view = new View(javaClass, name, false); - addAttributesToLocalView(metaClass, view); - } else if (View.MINIMAL.equals(name)) { - view = new View(javaClass, name, false); - addAttributesToMinimalView(metaClass, view, info, visited); - } else if (View.BASE.equals(name)) { - view = new View(javaClass, name, false); - addAttributesToMinimalView(metaClass, view, info, visited); - addAttributesToLocalView(metaClass, view); - } else { - throw new UnsupportedOperationException("Unsupported default view: " + name); - } - - storeView(metaClass, view); - - return view; - } - - protected void addAttributesToLocalView(MetaClass metaClass, View view) { - for (MetaProperty property : metaClass.getProperties()) { - if (!property.getRange().isClass() - && !metadata.getTools().isSystem(property) - && metadata.getTools().isPersistent(property)) { - view.addProperty(property.getName()); - } - } - } - - protected void addAttributesToMinimalView(MetaClass metaClass, View view, ViewInfo info, Set visited) { - Collection metaProperties = metadata.getTools().getNamePatternProperties(metaClass, true); - for (MetaProperty metaProperty : metaProperties) { - if (metadata.getTools().isPersistent(metaProperty)) { - addPersistentAttributeToMinimalView(metaClass, visited, info, view, metaProperty); - } else { - List relatedProperties = metadata.getTools().getRelatedProperties(metaProperty); - for (String relatedPropertyName : relatedProperties) { - MetaProperty relatedProperty = metaClass.getPropertyNN(relatedPropertyName); - if (metadata.getTools().isPersistent(relatedProperty)) { - addPersistentAttributeToMinimalView(metaClass, visited, info, view, relatedProperty); - } else { - log.warn("Transient attribute '" + relatedPropertyName - + "' is listed in 'related' properties of another transient attribute '" + metaProperty.getName() + "'"); - } - } - } - } - } - - protected void addPersistentAttributeToMinimalView(MetaClass metaClass, Set visited, ViewInfo info, View view, MetaProperty metaProperty) { - if (metaProperty.getRange().isClass() - && !metaProperty.getRange().getCardinality().isMany()) { - - Map views = storage.get(metaProperty.getRange().asClass()); - View refMinimalView = (views == null ? null : views.get(View.MINIMAL)); - - if (refMinimalView != null) { - view.addProperty(metaProperty.getName(), refMinimalView); - } else { - visited.add(info); - View referenceMinimalView = deployDefaultView(metaProperty.getRange().asClass(), View.MINIMAL, visited); - visited.remove(info); - - view.addProperty(metaProperty.getName(), referenceMinimalView); - } - } else { - view.addProperty(metaProperty.getName()); - } - } - - public void deployViews(String resourceUrl) { - lock.readLock().lock(); - try { - checkInitialized(); - } finally { - lock.readLock().unlock(); - } - - Element rootElem = DocumentHelper.createDocument().addElement("views"); - - lock.writeLock().lock(); - try { - addFile(rootElem, resourceUrl); - - for (Element viewElem : Dom4j.elements(rootElem, "view")) { - deployView(rootElem, viewElem, new HashSet<>()); - } - } finally { - lock.writeLock().unlock(); - } - } - - public void deployViews(InputStream xml) { - deployViews(new InputStreamReader(xml, StandardCharsets.UTF_8)); - } - - public void deployViews(Reader xml) { - lock.readLock().lock(); - try { - checkInitialized(); - } finally { - lock.readLock().unlock(); - } - - SAXReader reader = new SAXReader(); - Document doc; - try { - doc = reader.read(xml); - } catch (DocumentException e) { - throw new RuntimeException("Unable to read views xml", e); - } - Element rootElem = doc.getRootElement(); - - for (Element includeElem : Dom4j.elements(rootElem, "include")) { - String file = includeElem.attributeValue("file"); - if (!StringUtils.isBlank(file)) - deployViews(file); - } - - for (Element viewElem : Dom4j.elements(rootElem, "view")) { - deployView(rootElem, viewElem); - } - } - - protected View retrieveView(MetaClass metaClass, String name, Set visited) { - Map views = storage.get(metaClass); - View view = (views == null ? null : views.get(name)); - if (view == null && (name.equals(View.LOCAL) || name.equals(View.MINIMAL) || name.equals(View.BASE))) { - view = deployDefaultView(metaClass, name, visited); - } - return view; - } - - public View deployView(Element rootElem, Element viewElem) { - lock.writeLock().lock(); - try { - return deployView(rootElem, viewElem, new HashSet<>()); - } finally { - lock.writeLock().unlock(); - } - } - - protected View deployView(Element rootElem, Element viewElem, Set visited) { - String viewName = getViewName(viewElem); - MetaClass metaClass = getMetaClass(viewElem); - - ViewInfo info = new ViewInfo(metaClass.getJavaClass(), viewName); - if (visited.contains(info)) { - throw new DevelopmentException(String.format("Views cannot have cyclic references. View %s for class %s", - viewName, metaClass.getName())); - } - - View v = retrieveView(metaClass, viewName, visited); - boolean overwrite = Boolean.parseBoolean(viewElem.attributeValue("overwrite")); - - String ancestor = viewElem.attributeValue("extends"); - if (!overwrite) { - overwrite = StringUtils.equals(ancestor, viewName); - } - - if (v != null && !overwrite) { - return v; - } - - boolean systemProperties = Boolean.valueOf(viewElem.attributeValue("systemProperties")); - - View.ViewParams viewParam = new View.ViewParams().entityClass(metaClass.getJavaClass()).name(viewName); - if (ancestor != null) { - View ancestorView = getAncestorView(metaClass, ancestor, visited); - viewParam.src(ancestorView); - } - viewParam.includeSystemProperties(systemProperties); - View view = new View(viewParam); - - visited.add(info); - loadView(rootElem, viewElem, view, systemProperties, visited); - visited.remove(info); - - storeView(metaClass, view); - - if (overwrite) { - replaceOverridden(view); - } - - return view; - } - - protected void replaceOverridden(View replacementView) { - Log4JStopWatch replaceTiming = new Log4JStopWatch("ViewRepository.replaceOverridden"); - - HashSet checked = new HashSet<>(); - - for (View view : getAllInitialized()) { - if (!checked.contains(view)) { - replaceOverridden(view, replacementView, checked); - } - } - - replaceTiming.stop(); - } - - protected void replaceOverridden(View root, View replacementView, HashSet checked) { - checked.add(root); - - List replacements = null; - - for (ViewProperty property : root.getProperties()) { - View propertyView = property.getView(); - - if (propertyView != null) { - if (StringUtils.equals(propertyView.getName(), replacementView.getName()) - && replacementView.getEntityClass() == propertyView.getEntityClass()) { - if (replacements == null) { - replacements = new LinkedList<>(); - } - replacements.add(new ViewProperty(property.getName(), replacementView, property.getFetchMode())); - } else if (propertyView.getEntityClass() != null && !checked.contains(propertyView)) { - replaceOverridden(propertyView, replacementView, checked); - } - } - } - - if (replacements != null) { - for (ViewProperty replacement : replacements) { - root.addProperty(replacement.getName(), replacement.getView(), replacement.getFetchMode()); - } - } - } - - protected View getAncestorView(MetaClass metaClass, String ancestor, Set visited) { - View ancestorView = retrieveView(metaClass, ancestor, visited); - if (ancestorView == null) { - ExtendedEntities extendedEntities = metadata.getExtendedEntities(); - MetaClass originalMetaClass = extendedEntities.getOriginalMetaClass(metaClass); - if (originalMetaClass != null) { - ancestorView = retrieveView(originalMetaClass, ancestor, visited); - } - if (ancestorView == null) { - // Last resort - search for all ancestors - for (MetaClass ancestorMetaClass : metaClass.getAncestors()) { - if (ancestorMetaClass.equals(metaClass)) { - ancestorView = retrieveView(ancestorMetaClass, ancestor, visited); - if (ancestorView != null) - break; - } - } - } - if (ancestorView == null) { - throw new DevelopmentException("No ancestor view found: " + ancestor + " for " + metaClass.getName()); - } - } - return ancestorView; - } - - protected void loadView(Element rootElem, Element viewElem, View view, boolean systemProperties, Set visited) { - final MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); - final String viewName = view.getName(); - - Set propertyNames = new HashSet<>(); - - for (Element propElem : (List) viewElem.elements("property")) { - String propertyName = propElem.attributeValue("name"); - - if (propertyNames.contains(propertyName)) { - throw new DevelopmentException(String.format("View %s/%s definition error: view declared property %s twice", - metaClass.getName(), viewName, propertyName)); - } - propertyNames.add(propertyName); - - MetaProperty metaProperty = metaClass.getProperty(propertyName); - if (metaProperty == null) { - throw new DevelopmentException(String.format("View %s/%s definition error: property %s doesn't exists", - metaClass.getName(), viewName, propertyName)); - } - - View refView = null; - String refViewName = propElem.attributeValue("view"); - - MetaClass refMetaClass; - Range range = metaProperty.getRange(); - if (range == null) { - throw new RuntimeException("cannot find range for meta property: " + metaProperty); - } - - final List propertyElements = Dom4j.elements(propElem, "property"); - boolean inlineView = !propertyElements.isEmpty(); - - if (!range.isClass() && (refViewName != null || inlineView)) { - throw new DevelopmentException(String.format("View %s/%s definition error: property %s is not an entity", - metaClass.getName(), viewName, propertyName)); - } - - if (refViewName != null) { - refMetaClass = getMetaClass(propElem, range); - - refView = retrieveView(refMetaClass, refViewName, visited); - if (refView == null) { - for (Element e : Dom4j.elements(rootElem, "view")) { - if (refMetaClass.equals(getMetaClass(e.attributeValue("entity"), e.attributeValue("class"))) - && refViewName.equals(e.attributeValue("name"))) { - refView = deployView(rootElem, e, visited); - break; - } - } - - if (refView == null) { - MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(refMetaClass); - if (originalMetaClass != null) { - refView = retrieveView(originalMetaClass, refViewName, visited); - } - } - - if (refView == null) { - throw new DevelopmentException( - String.format("View %s/%s definition error: unable to find/deploy referenced view %s/%s", - metaClass.getName(), viewName, range.asClass().getName(), refViewName)); - } - } - } - - if (inlineView) { - // try to import anonymous views - Class rangeClass = range.asClass().getJavaClass(); - - if (refView != null) { - refView = new View(refView, rangeClass, "", false); // system properties are already in the source view - } else { - ViewProperty existingProperty = view.getProperty(propertyName); - if (existingProperty != null && existingProperty.getView() != null) { - refView = new View(existingProperty.getView(), rangeClass, "", systemProperties); - } else { - refView = new View(rangeClass, systemProperties); - } - } - loadView(rootElem, propElem, refView, systemProperties, visited); - } - - FetchMode fetchMode = FetchMode.AUTO; - String fetch = propElem.attributeValue("fetch"); - if (fetch != null) - fetchMode = FetchMode.valueOf(fetch); - - view.addProperty(propertyName, refView, fetchMode); - } - } - - protected String getViewName(Element viewElem) { - String viewName = viewElem.attributeValue("name"); - if (StringUtils.isBlank(viewName)) - throw new DevelopmentException("Invalid view definition: no 'name' attribute present"); - return viewName; - } - - protected MetaClass getMetaClass(Element viewElem) { - MetaClass metaClass; - String entity = viewElem.attributeValue("entity"); - if (StringUtils.isBlank(entity)) { - String className = viewElem.attributeValue("class"); - if (StringUtils.isBlank(className)) - throw new DevelopmentException("Invalid view definition: no 'entity' or 'class' attribute present"); - Class entityClass = ReflectionHelper.getClass(className); - metaClass = metadata.getClassNN(entityClass); - } else { - metaClass = metadata.getClassNN(entity); - } - return metaClass; - } - - protected MetaClass getMetaClass(String entityName, String entityClass) { - if (entityName != null) { - return metadata.getClassNN(entityName); - } else { - return metadata.getClassNN(ReflectionHelper.getClass(entityClass)); - } - } - - protected MetaClass getMetaClass(Element propElem, Range range) { - MetaClass refMetaClass; - String refEntityName = propElem.attributeValue("entity"); // this attribute is deprecated - if (refEntityName == null) { - refMetaClass = range.asClass(); - } else { - refMetaClass = metadata.getClassNN(refEntityName); - } - return refMetaClass; - } - - protected void storeView(MetaClass metaClass, View view) { - Map views = storage.get(metaClass); - if (views == null) { - views = new ConcurrentHashMap<>(); - } - - views.put(view.getName(), view); - storage.put(metaClass, views); - } - - protected List getAllInitialized() { - List list = new ArrayList<>(); - for (Map viewMap : storage.values()) { - list.addAll(viewMap.values()); - } - return list; - } - - public List getAll() { - lock.readLock().lock(); - try { - checkInitialized(); - List list = new ArrayList<>(); - for (Map viewMap : storage.values()) { - list.addAll(viewMap.values()); - } - return list; - } finally { - lock.readLock().unlock(); - } - } - - protected static class ViewInfo { - protected Class javaClass; - protected String name; - - public ViewInfo(Class javaClass, String name) { - this.javaClass = javaClass; - this.name = name; - } - - public Class getJavaClass() { - return javaClass; - } - - public void setJavaClass(Class javaClass) { - this.javaClass = javaClass; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ViewInfo)) { - return false; - } - - ViewInfo that = (ViewInfo) obj; - return this.javaClass == that.javaClass && Objects.equals(this.name, that.name); - } - - @Override - public int hashCode() { - int result = javaClass.hashCode(); - result = 31 * result + name.hashCode(); - return result; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.Range; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Base implementation of the {@link ViewRepository}. Contains methods to store {@link View} objects and deploy + * them from XML.
+ *
Don't replace this class completely, because the framework uses it directly. + */ +public class AbstractViewRepository implements ViewRepository { + + private final Logger log = LoggerFactory.getLogger(AbstractViewRepository.class); + + protected List readFileNames = new LinkedList<>(); + + protected Map> storage = new ConcurrentHashMap<>(); + + @Inject + protected Metadata metadata; + + @Inject + protected Resources resources; + + protected volatile boolean initialized; + + protected ReadWriteLock lock = new ReentrantReadWriteLock(); + + protected void checkInitialized() { + if (!initialized) { + lock.readLock().unlock(); + lock.writeLock().lock(); + try { + if (!initialized) { + log.info("Initializing views"); + init(); + initialized = true; + } + } finally { + lock.readLock().lock(); + lock.writeLock().unlock(); + } + } + } + + protected void init() { + StopWatch initTiming = new Log4JStopWatch("ViewRepository.init." + getClass().getSimpleName()); + + storage.clear(); + readFileNames.clear(); + + String configName = AppContext.getProperty("cuba.viewsConfig"); + if (!StringUtils.isBlank(configName)) { + Element rootElem = DocumentHelper.createDocument().addElement("views"); + + StrTokenizer tokenizer = new StrTokenizer(configName); + for (String fileName : tokenizer.getTokenArray()) { + addFile(rootElem, fileName); + } + + checkDuplicates(rootElem); + + for (Element viewElem : Dom4j.elements(rootElem, "view")) { + deployView(rootElem, viewElem, new HashSet<>()); + } + } + + initTiming.stop(); + } + + protected void checkDuplicates(Element rootElem) { + Set checked = new HashSet<>(); + for (Element viewElem : Dom4j.elements(rootElem, "view")) { + String viewName = getViewName(viewElem); + String key = getMetaClass(viewElem) + "/" + viewName; + if (!Boolean.parseBoolean(viewElem.attributeValue("overwrite"))) { + String extend = viewElem.attributeValue("extends"); + if (!StringUtils.equals(extend, viewName) && checked.contains(key)) { + log.warn("Duplicate view definition without 'overwrite' attribute and not extending parent view: " + key); + } + } + checked.add(key); + } + } + + protected void addFile(Element commonRootElem, String fileName) { + if (readFileNames.contains(fileName)) + return; + + log.debug("Deploying views config: " + fileName); + readFileNames.add(fileName); + + InputStream stream = null; + try { + stream = resources.getResourceAsStream(fileName); + if (stream == null) { + throw new IllegalStateException("Resource is not found: " + fileName); + } + + SAXReader reader = new SAXReader(); + Document doc; + try { + doc = reader.read(new InputStreamReader(stream, StandardCharsets.UTF_8)); + } catch (DocumentException e) { + throw new RuntimeException("Unable to parse view file " + fileName, e); + } + Element rootElem = doc.getRootElement(); + + for (Element includeElem : Dom4j.elements(rootElem, "include")) { + String incFile = includeElem.attributeValue("file"); + if (!StringUtils.isBlank(incFile)) + addFile(commonRootElem, incFile); + } + + for (Element viewElem : Dom4j.elements(rootElem, "view")) { + commonRootElem.add(viewElem.createCopy()); + } + } finally { + IOUtils.closeQuietly(stream); + } + } + + public void reset() { + initialized = false; + } + + /** + * Get View for an entity. + * + * @param entityClass entity class + * @param name view name + * @return view instance. Throws {@link com.haulmont.cuba.core.global.ViewNotFoundException} if not found. + */ + @Override + public View getView(Class entityClass, String name) { + return getView(metadata.getClassNN(entityClass), name); + } + + /** + * Get View for an entity. + * + * @param metaClass entity class + * @param name view name + * @return view instance. Throws {@link com.haulmont.cuba.core.global.ViewNotFoundException} if not found. + */ + @Override + public View getView(MetaClass metaClass, String name) { + Preconditions.checkNotNullArgument(metaClass, "MetaClass is null"); + + View view = findView(metaClass, name); + + if (view == null) { + throw new ViewNotFoundException(String.format("View %s/%s not found", metaClass.getName(), name)); + } + return view; + } + + /** + * Searches for a View for an entity + * + * @param metaClass entity class + * @param name view name + * @return view instance or null if no view found + */ + @Override + @Nullable + public View findView(MetaClass metaClass, @Nullable String name) { + if (metaClass == null) { + throw new IllegalArgumentException("Passed metaClass should not be null"); + } + + if (name == null) { + return null; + } + + lock.readLock().lock(); + try { + checkInitialized(); + + View view = retrieveView(metaClass, name, new HashSet<>()); + return copyView(view); + } finally { + lock.readLock().unlock(); + } + } + + protected View copyView(@Nullable View view) { + if (view == null) { + return null; + } + + View.ViewParams viewParams = new View.ViewParams() + .entityClass(view.getEntityClass()) + .name(view.getName()); + View copy = new View(viewParams); + for (ViewProperty property : view.getProperties()) { + copy.addProperty(property.getName(), copyView(property.getView()), property.getFetchMode()); + } + + return copy; + } + + @Override + public Collection getViewNames(MetaClass metaClass) { + Preconditions.checkNotNullArgument(metaClass, "MetaClass is null"); + lock.readLock().lock(); + try { + checkInitialized(); + Map viewMap = storage.get(metaClass); + if (viewMap != null && !viewMap.isEmpty()) { + Set keySet = new HashSet<>(viewMap.keySet()); + keySet.remove(View.LOCAL); + keySet.remove(View.MINIMAL); + return keySet; + } else { + return Collections.emptyList(); + } + } finally { + lock.readLock().unlock(); + } + } + + @Override + public Collection getViewNames(Class entityClass) { + Preconditions.checkNotNullArgument(entityClass, "entityClass is null"); + MetaClass metaClass = metadata.getClassNN(entityClass); + return getViewNames(metaClass); + } + + @SuppressWarnings("unchecked") + protected View deployDefaultView(MetaClass metaClass, String name, Set visited) { + Class javaClass = metaClass.getJavaClass(); + + ViewInfo info = new ViewInfo(javaClass, name); + if (visited.contains(info)) { + throw new DevelopmentException(String.format("Views cannot have cyclic references. View %s for class %s", + name, metaClass.getName())); + } + + View view; + if (View.LOCAL.equals(name)) { + view = new View(javaClass, name, false); + addAttributesToLocalView(metaClass, view); + } else if (View.MINIMAL.equals(name)) { + view = new View(javaClass, name, false); + addAttributesToMinimalView(metaClass, view, info, visited); + } else if (View.BASE.equals(name)) { + view = new View(javaClass, name, false); + addAttributesToMinimalView(metaClass, view, info, visited); + addAttributesToLocalView(metaClass, view); + } else { + throw new UnsupportedOperationException("Unsupported default view: " + name); + } + + storeView(metaClass, view); + + return view; + } + + protected void addAttributesToLocalView(MetaClass metaClass, View view) { + for (MetaProperty property : metaClass.getProperties()) { + if (!property.getRange().isClass() + && !metadata.getTools().isSystem(property) + && metadata.getTools().isPersistent(property)) { + view.addProperty(property.getName()); + } + } + } + + protected void addAttributesToMinimalView(MetaClass metaClass, View view, ViewInfo info, Set visited) { + Collection metaProperties = metadata.getTools().getNamePatternProperties(metaClass, true); + for (MetaProperty metaProperty : metaProperties) { + if (metadata.getTools().isPersistent(metaProperty)) { + addPersistentAttributeToMinimalView(metaClass, visited, info, view, metaProperty); + } else { + List relatedProperties = metadata.getTools().getRelatedProperties(metaProperty); + for (String relatedPropertyName : relatedProperties) { + MetaProperty relatedProperty = metaClass.getPropertyNN(relatedPropertyName); + if (metadata.getTools().isPersistent(relatedProperty)) { + addPersistentAttributeToMinimalView(metaClass, visited, info, view, relatedProperty); + } else { + log.warn("Transient attribute '" + relatedPropertyName + + "' is listed in 'related' properties of another transient attribute '" + metaProperty.getName() + "'"); + } + } + } + } + } + + protected void addPersistentAttributeToMinimalView(MetaClass metaClass, Set visited, ViewInfo info, View view, MetaProperty metaProperty) { + if (metaProperty.getRange().isClass() + && !metaProperty.getRange().getCardinality().isMany()) { + + Map views = storage.get(metaProperty.getRange().asClass()); + View refMinimalView = (views == null ? null : views.get(View.MINIMAL)); + + if (refMinimalView != null) { + view.addProperty(metaProperty.getName(), refMinimalView); + } else { + visited.add(info); + View referenceMinimalView = deployDefaultView(metaProperty.getRange().asClass(), View.MINIMAL, visited); + visited.remove(info); + + view.addProperty(metaProperty.getName(), referenceMinimalView); + } + } else { + view.addProperty(metaProperty.getName()); + } + } + + public void deployViews(String resourceUrl) { + lock.readLock().lock(); + try { + checkInitialized(); + } finally { + lock.readLock().unlock(); + } + + Element rootElem = DocumentHelper.createDocument().addElement("views"); + + lock.writeLock().lock(); + try { + addFile(rootElem, resourceUrl); + + for (Element viewElem : Dom4j.elements(rootElem, "view")) { + deployView(rootElem, viewElem, new HashSet<>()); + } + } finally { + lock.writeLock().unlock(); + } + } + + public void deployViews(InputStream xml) { + deployViews(new InputStreamReader(xml, StandardCharsets.UTF_8)); + } + + public void deployViews(Reader xml) { + lock.readLock().lock(); + try { + checkInitialized(); + } finally { + lock.readLock().unlock(); + } + + SAXReader reader = new SAXReader(); + Document doc; + try { + doc = reader.read(xml); + } catch (DocumentException e) { + throw new RuntimeException("Unable to read views xml", e); + } + Element rootElem = doc.getRootElement(); + + for (Element includeElem : Dom4j.elements(rootElem, "include")) { + String file = includeElem.attributeValue("file"); + if (!StringUtils.isBlank(file)) + deployViews(file); + } + + for (Element viewElem : Dom4j.elements(rootElem, "view")) { + deployView(rootElem, viewElem); + } + } + + protected View retrieveView(MetaClass metaClass, String name, Set visited) { + Map views = storage.get(metaClass); + View view = (views == null ? null : views.get(name)); + if (view == null && (name.equals(View.LOCAL) || name.equals(View.MINIMAL) || name.equals(View.BASE))) { + view = deployDefaultView(metaClass, name, visited); + } + return view; + } + + public View deployView(Element rootElem, Element viewElem) { + lock.writeLock().lock(); + try { + return deployView(rootElem, viewElem, new HashSet<>()); + } finally { + lock.writeLock().unlock(); + } + } + + protected View deployView(Element rootElem, Element viewElem, Set visited) { + String viewName = getViewName(viewElem); + MetaClass metaClass = getMetaClass(viewElem); + + ViewInfo info = new ViewInfo(metaClass.getJavaClass(), viewName); + if (visited.contains(info)) { + throw new DevelopmentException(String.format("Views cannot have cyclic references. View %s for class %s", + viewName, metaClass.getName())); + } + + View v = retrieveView(metaClass, viewName, visited); + boolean overwrite = Boolean.parseBoolean(viewElem.attributeValue("overwrite")); + + String ancestor = viewElem.attributeValue("extends"); + if (!overwrite) { + overwrite = StringUtils.equals(ancestor, viewName); + } + + if (v != null && !overwrite) { + return v; + } + + boolean systemProperties = Boolean.valueOf(viewElem.attributeValue("systemProperties")); + + View.ViewParams viewParam = new View.ViewParams().entityClass(metaClass.getJavaClass()).name(viewName); + if (ancestor != null) { + View ancestorView = getAncestorView(metaClass, ancestor, visited); + viewParam.src(ancestorView); + } + viewParam.includeSystemProperties(systemProperties); + View view = new View(viewParam); + + visited.add(info); + loadView(rootElem, viewElem, view, systemProperties, visited); + visited.remove(info); + + storeView(metaClass, view); + + if (overwrite) { + replaceOverridden(view); + } + + return view; + } + + protected void replaceOverridden(View replacementView) { + Log4JStopWatch replaceTiming = new Log4JStopWatch("ViewRepository.replaceOverridden"); + + HashSet checked = new HashSet<>(); + + for (View view : getAllInitialized()) { + if (!checked.contains(view)) { + replaceOverridden(view, replacementView, checked); + } + } + + replaceTiming.stop(); + } + + protected void replaceOverridden(View root, View replacementView, HashSet checked) { + checked.add(root); + + List replacements = null; + + for (ViewProperty property : root.getProperties()) { + View propertyView = property.getView(); + + if (propertyView != null) { + if (StringUtils.equals(propertyView.getName(), replacementView.getName()) + && replacementView.getEntityClass() == propertyView.getEntityClass()) { + if (replacements == null) { + replacements = new LinkedList<>(); + } + replacements.add(new ViewProperty(property.getName(), replacementView, property.getFetchMode())); + } else if (propertyView.getEntityClass() != null && !checked.contains(propertyView)) { + replaceOverridden(propertyView, replacementView, checked); + } + } + } + + if (replacements != null) { + for (ViewProperty replacement : replacements) { + root.addProperty(replacement.getName(), replacement.getView(), replacement.getFetchMode()); + } + } + } + + protected View getAncestorView(MetaClass metaClass, String ancestor, Set visited) { + View ancestorView = retrieveView(metaClass, ancestor, visited); + if (ancestorView == null) { + ExtendedEntities extendedEntities = metadata.getExtendedEntities(); + MetaClass originalMetaClass = extendedEntities.getOriginalMetaClass(metaClass); + if (originalMetaClass != null) { + ancestorView = retrieveView(originalMetaClass, ancestor, visited); + } + if (ancestorView == null) { + // Last resort - search for all ancestors + for (MetaClass ancestorMetaClass : metaClass.getAncestors()) { + if (ancestorMetaClass.equals(metaClass)) { + ancestorView = retrieveView(ancestorMetaClass, ancestor, visited); + if (ancestorView != null) + break; + } + } + } + if (ancestorView == null) { + throw new DevelopmentException("No ancestor view found: " + ancestor + " for " + metaClass.getName()); + } + } + return ancestorView; + } + + protected void loadView(Element rootElem, Element viewElem, View view, boolean systemProperties, Set visited) { + final MetaClass metaClass = metadata.getClassNN(view.getEntityClass()); + final String viewName = view.getName(); + + Set propertyNames = new HashSet<>(); + + for (Element propElem : (List) viewElem.elements("property")) { + String propertyName = propElem.attributeValue("name"); + + if (propertyNames.contains(propertyName)) { + throw new DevelopmentException(String.format("View %s/%s definition error: view declared property %s twice", + metaClass.getName(), viewName, propertyName)); + } + propertyNames.add(propertyName); + + MetaProperty metaProperty = metaClass.getProperty(propertyName); + if (metaProperty == null) { + throw new DevelopmentException(String.format("View %s/%s definition error: property %s doesn't exists", + metaClass.getName(), viewName, propertyName)); + } + + View refView = null; + String refViewName = propElem.attributeValue("view"); + + MetaClass refMetaClass; + Range range = metaProperty.getRange(); + if (range == null) { + throw new RuntimeException("cannot find range for meta property: " + metaProperty); + } + + final List propertyElements = Dom4j.elements(propElem, "property"); + boolean inlineView = !propertyElements.isEmpty(); + + if (!range.isClass() && (refViewName != null || inlineView)) { + throw new DevelopmentException(String.format("View %s/%s definition error: property %s is not an entity", + metaClass.getName(), viewName, propertyName)); + } + + if (refViewName != null) { + refMetaClass = getMetaClass(propElem, range); + + refView = retrieveView(refMetaClass, refViewName, visited); + if (refView == null) { + for (Element e : Dom4j.elements(rootElem, "view")) { + if (refMetaClass.equals(getMetaClass(e.attributeValue("entity"), e.attributeValue("class"))) + && refViewName.equals(e.attributeValue("name"))) { + refView = deployView(rootElem, e, visited); + break; + } + } + + if (refView == null) { + MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(refMetaClass); + if (originalMetaClass != null) { + refView = retrieveView(originalMetaClass, refViewName, visited); + } + } + + if (refView == null) { + throw new DevelopmentException( + String.format("View %s/%s definition error: unable to find/deploy referenced view %s/%s", + metaClass.getName(), viewName, range.asClass().getName(), refViewName)); + } + } + } + + if (inlineView) { + // try to import anonymous views + Class rangeClass = range.asClass().getJavaClass(); + + if (refView != null) { + refView = new View(refView, rangeClass, "", false); // system properties are already in the source view + } else { + ViewProperty existingProperty = view.getProperty(propertyName); + if (existingProperty != null && existingProperty.getView() != null) { + refView = new View(existingProperty.getView(), rangeClass, "", systemProperties); + } else { + refView = new View(rangeClass, systemProperties); + } + } + loadView(rootElem, propElem, refView, systemProperties, visited); + } + + FetchMode fetchMode = FetchMode.AUTO; + String fetch = propElem.attributeValue("fetch"); + if (fetch != null) + fetchMode = FetchMode.valueOf(fetch); + + view.addProperty(propertyName, refView, fetchMode); + } + } + + protected String getViewName(Element viewElem) { + String viewName = viewElem.attributeValue("name"); + if (StringUtils.isBlank(viewName)) + throw new DevelopmentException("Invalid view definition: no 'name' attribute present"); + return viewName; + } + + protected MetaClass getMetaClass(Element viewElem) { + MetaClass metaClass; + String entity = viewElem.attributeValue("entity"); + if (StringUtils.isBlank(entity)) { + String className = viewElem.attributeValue("class"); + if (StringUtils.isBlank(className)) + throw new DevelopmentException("Invalid view definition: no 'entity' or 'class' attribute present"); + Class entityClass = ReflectionHelper.getClass(className); + metaClass = metadata.getClassNN(entityClass); + } else { + metaClass = metadata.getClassNN(entity); + } + return metaClass; + } + + protected MetaClass getMetaClass(String entityName, String entityClass) { + if (entityName != null) { + return metadata.getClassNN(entityName); + } else { + return metadata.getClassNN(ReflectionHelper.getClass(entityClass)); + } + } + + protected MetaClass getMetaClass(Element propElem, Range range) { + MetaClass refMetaClass; + String refEntityName = propElem.attributeValue("entity"); // this attribute is deprecated + if (refEntityName == null) { + refMetaClass = range.asClass(); + } else { + refMetaClass = metadata.getClassNN(refEntityName); + } + return refMetaClass; + } + + protected void storeView(MetaClass metaClass, View view) { + Map views = storage.get(metaClass); + if (views == null) { + views = new ConcurrentHashMap<>(); + } + + views.put(view.getName(), view); + storage.put(metaClass, views); + } + + protected List getAllInitialized() { + List list = new ArrayList<>(); + for (Map viewMap : storage.values()) { + list.addAll(viewMap.values()); + } + return list; + } + + public List getAll() { + lock.readLock().lock(); + try { + checkInitialized(); + List list = new ArrayList<>(); + for (Map viewMap : storage.values()) { + list.addAll(viewMap.values()); + } + return list; + } finally { + lock.readLock().unlock(); + } + } + + protected static class ViewInfo { + protected Class javaClass; + protected String name; + + public ViewInfo(Class javaClass, String name) { + this.javaClass = javaClass; + this.name = name; + } + + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ViewInfo)) { + return false; + } + + ViewInfo that = (ViewInfo) obj; + return this.javaClass == that.javaClass && Objects.equals(this.name, that.name); + } + + @Override + public int hashCode() { + int result = javaClass.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/AppContext.java b/modules/global/src/com/haulmont/cuba/core/sys/AppContext.java index 9b14270718..534f3cfe0a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/AppContext.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/AppContext.java @@ -1,303 +1,303 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.sys.logging.LogMdc; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.OrderComparator; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * System-level class with static methods providing access to some central application structures: - *
    - *
  • Spring's {@link ApplicationContext}
  • - *
  • Application properties which were set in {@code app.properties} files
  • - *
  • Current thread's {@link SecurityContext}
  • - *
- * It also allows to register listeners which are triggered on the application start/stop, and provides the method - * {@link #isStarted()} to check whether the app is fully initialized at the moment. - */ -public class AppContext { - - private static final Logger log = LoggerFactory.getLogger(AppContext.class); - - /** - * Application startup/shutdown listener. - * Implementors should be passed to {@link AppContext#addListener(com.haulmont.cuba.core.sys.AppContext.Listener)} method. - */ - public interface Listener { - - /** - * Defines the highest precedence for {@link org.springframework.core.Ordered} listeners added by the platform. - */ - int HIGHEST_PLATFORM_PRECEDENCE = 100; - - /** - * Defines the lowest precedence for {@link org.springframework.core.Ordered} listeners added by the platform. - */ - int LOWEST_PLATFORM_PRECEDENCE = 1000; - - /** - * Called by {@link AppContext} after successful application startup and initialization. - */ - void applicationStarted(); - - /** - * Called by {@link AppContext} before application shutdown. - */ - void applicationStopped(); - } - - private static ApplicationContext context; - - private static SecurityContextHolder securityContextHolder = new ThreadLocalSecurityContextHolder(); - - private static AppComponents appComponents; - - private static AppProperties appProperties; - - private static final List listeners = new ArrayList<>(); - - private static volatile boolean started; - private static volatile boolean listenersNotified; - - public static final SecurityContext NO_USER_CONTEXT = - new SecurityContext(UUID.fromString("23dce942-d13f-11df-88cd-b3d32fd1e595"), "server"); - - /** - * INTERNAL. - * Used by other framework classes to get access Spring's context. - */ - public static ApplicationContext getApplicationContext() { - return context; - } - - /** - * @return all property names defined in the set of {@code app.properties} files - */ - public static String[] getPropertyNames() { - if (appProperties == null) - throw new IllegalStateException("appProperties not initialized"); - return appProperties.getPropertyNames(); - } - - /** - * Get property value defined in the set of {@code app.properties} files. - * @param key property key - * @return property value or null if the key is not found - */ - @Nullable - public static String getProperty(String key) { - if (appProperties == null) - throw new IllegalStateException("appProperties not initialized"); - return appProperties.getProperty(key); - } - - /** - * Set property value. The new value will be accessible at the runtime through {@link #getProperty(String)} and - * {@link #getPropertyNames()}, but will not be saved in any {@code app.properties} file and will be lost - * after the application restart. - * @param key property key - * @param value property value. If null, the property will be removed. - */ - public static void setProperty(String key, @Nullable String value) { - if (appProperties == null) - throw new IllegalStateException("appProperties not initialized"); - appProperties.setProperty(key, value); - } - - /** - * @return current thread's {@link SecurityContext} or null if there is no context bound - */ - @Nullable - public static SecurityContext getSecurityContext() { - if (started) - return securityContextHolder.get(); - else - return NO_USER_CONTEXT; - } - - /** - * @return current thread's {@link SecurityContext} - * @throws SecurityException if there is no context bound to the current thread - */ - public static SecurityContext getSecurityContextNN() { - SecurityContext securityContext = getSecurityContext(); - if (securityContext == null) - throw new SecurityException("No security context bound to the current thread"); - - return securityContext; - } - - /** - * Set current thread's {@link SecurityContext}. - * @param securityContext security context to be set for the current thread - */ - public static void setSecurityContext(@Nullable SecurityContext securityContext) { - log.trace("setSecurityContext {} for thread {}", securityContext, Thread.currentThread()); - - securityContextHolder.set(securityContext); - LogMdc.setup(securityContext); - } - - /** - * Sets current thread's {@link SecurityContext}, invokes runnable and sets previous security context back. - * - * @param securityContext security context to be set for the current thread - * @param runnable runnable - */ - public static void withSecurityContext(SecurityContext securityContext, Runnable runnable) { - SecurityContext previousSecurityContext = getSecurityContext(); - setSecurityContext(securityContext); - try { - runnable.run(); - } finally { - setSecurityContext(previousSecurityContext); - } - } - - /** - * Sets current thread's {@link SecurityContext}, calls operation and sets previous security context back. - * - * @param securityContext security context to be set for the current thread - * @param operation operation - * @return result of operation - */ - public static T withSecurityContext(SecurityContext securityContext, SecuredOperation operation) { - SecurityContext previousSecurityContext = getSecurityContext(); - setSecurityContext(securityContext); - try { - return operation.call(); - } finally { - setSecurityContext(previousSecurityContext); - } - } - - /** - * @return app components holder instance - */ - public static AppComponents getAppComponents() { - return appComponents; - } - - /** - * Register an application start/stop listener. - * @param listener listener implementation - */ - public static void addListener(Listener listener) { - if (!listeners.contains(listener)) - listeners.add(listener); - } - - /** - * @return true if the application context is initialized - */ - public static boolean isStarted() { - return started; - } - - /** - * @return true if the application context is initialized and all {@link Listener}s have been notified - */ - public static boolean isReady() { - return started && listenersNotified; - } - - static void startContext() { - if (started) - return; - - started = true; - listeners.sort(new OrderComparator()); - for (Listener listener : listeners) { - listener.applicationStarted(); - } - listenersNotified = true; - } - - /** - * Called by the framework right before the application shutdown. - */ - static void stopContext() { - if (!started) - return; - - started = false; - for (int i = listeners.size() - 1; i >= 0; i--) { - Listener listener = listeners.get(i); - listener.applicationStopped(); - } - if (context != null && context instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) context).close(); - } - } - - /** - * INTERNAL. - * Contains methods for setting up AppContext internals. - */ - public static class Internals { - - public static void setAppComponents(AppComponents appComponents) { - AppContext.appComponents = appComponents; - AppContext.appProperties = new AppProperties(appComponents); - } - - /** - * Called by the framework to set Spring's context. - * - * @param applicationContext initialized Spring's context - */ - public static void setApplicationContext(@Nullable ApplicationContext applicationContext) { - AppContext.context = applicationContext; - } - - /** - * Called by the framework to replace standard thread-local holder. - * - * @param holder a holder implementation - */ - public static void setSecurityContextHolder(SecurityContextHolder holder) { - AppContext.securityContextHolder = holder; - } - - /** - * Called by the framework after the application has been started and fully initialized. - */ - public static void startContext() { - AppContext.startContext(); - } - - /** - * Called by the framework right before the application shutdown. - */ - public static void stopContext() { - AppContext.stopContext(); - } - } - - public interface SecuredOperation { - T call(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.sys.logging.LogMdc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.OrderComparator; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * System-level class with static methods providing access to some central application structures: + *
    + *
  • Spring's {@link ApplicationContext}
  • + *
  • Application properties which were set in {@code app.properties} files
  • + *
  • Current thread's {@link SecurityContext}
  • + *
+ * It also allows to register listeners which are triggered on the application start/stop, and provides the method + * {@link #isStarted()} to check whether the app is fully initialized at the moment. + */ +public class AppContext { + + private static final Logger log = LoggerFactory.getLogger(AppContext.class); + + /** + * Application startup/shutdown listener. + * Implementors should be passed to {@link AppContext#addListener(com.haulmont.cuba.core.sys.AppContext.Listener)} method. + */ + public interface Listener { + + /** + * Defines the highest precedence for {@link org.springframework.core.Ordered} listeners added by the platform. + */ + int HIGHEST_PLATFORM_PRECEDENCE = 100; + + /** + * Defines the lowest precedence for {@link org.springframework.core.Ordered} listeners added by the platform. + */ + int LOWEST_PLATFORM_PRECEDENCE = 1000; + + /** + * Called by {@link AppContext} after successful application startup and initialization. + */ + void applicationStarted(); + + /** + * Called by {@link AppContext} before application shutdown. + */ + void applicationStopped(); + } + + private static ApplicationContext context; + + private static SecurityContextHolder securityContextHolder = new ThreadLocalSecurityContextHolder(); + + private static AppComponents appComponents; + + private static AppProperties appProperties; + + private static final List listeners = new ArrayList<>(); + + private static volatile boolean started; + private static volatile boolean listenersNotified; + + public static final SecurityContext NO_USER_CONTEXT = + new SecurityContext(UUID.fromString("23dce942-d13f-11df-88cd-b3d32fd1e595"), "server"); + + /** + * INTERNAL. + * Used by other framework classes to get access Spring's context. + */ + public static ApplicationContext getApplicationContext() { + return context; + } + + /** + * @return all property names defined in the set of {@code app.properties} files + */ + public static String[] getPropertyNames() { + if (appProperties == null) + throw new IllegalStateException("appProperties not initialized"); + return appProperties.getPropertyNames(); + } + + /** + * Get property value defined in the set of {@code app.properties} files. + * @param key property key + * @return property value or null if the key is not found + */ + @Nullable + public static String getProperty(String key) { + if (appProperties == null) + throw new IllegalStateException("appProperties not initialized"); + return appProperties.getProperty(key); + } + + /** + * Set property value. The new value will be accessible at the runtime through {@link #getProperty(String)} and + * {@link #getPropertyNames()}, but will not be saved in any {@code app.properties} file and will be lost + * after the application restart. + * @param key property key + * @param value property value. If null, the property will be removed. + */ + public static void setProperty(String key, @Nullable String value) { + if (appProperties == null) + throw new IllegalStateException("appProperties not initialized"); + appProperties.setProperty(key, value); + } + + /** + * @return current thread's {@link SecurityContext} or null if there is no context bound + */ + @Nullable + public static SecurityContext getSecurityContext() { + if (started) + return securityContextHolder.get(); + else + return NO_USER_CONTEXT; + } + + /** + * @return current thread's {@link SecurityContext} + * @throws SecurityException if there is no context bound to the current thread + */ + public static SecurityContext getSecurityContextNN() { + SecurityContext securityContext = getSecurityContext(); + if (securityContext == null) + throw new SecurityException("No security context bound to the current thread"); + + return securityContext; + } + + /** + * Set current thread's {@link SecurityContext}. + * @param securityContext security context to be set for the current thread + */ + public static void setSecurityContext(@Nullable SecurityContext securityContext) { + log.trace("setSecurityContext {} for thread {}", securityContext, Thread.currentThread()); + + securityContextHolder.set(securityContext); + LogMdc.setup(securityContext); + } + + /** + * Sets current thread's {@link SecurityContext}, invokes runnable and sets previous security context back. + * + * @param securityContext security context to be set for the current thread + * @param runnable runnable + */ + public static void withSecurityContext(SecurityContext securityContext, Runnable runnable) { + SecurityContext previousSecurityContext = getSecurityContext(); + setSecurityContext(securityContext); + try { + runnable.run(); + } finally { + setSecurityContext(previousSecurityContext); + } + } + + /** + * Sets current thread's {@link SecurityContext}, calls operation and sets previous security context back. + * + * @param securityContext security context to be set for the current thread + * @param operation operation + * @return result of operation + */ + public static T withSecurityContext(SecurityContext securityContext, SecuredOperation operation) { + SecurityContext previousSecurityContext = getSecurityContext(); + setSecurityContext(securityContext); + try { + return operation.call(); + } finally { + setSecurityContext(previousSecurityContext); + } + } + + /** + * @return app components holder instance + */ + public static AppComponents getAppComponents() { + return appComponents; + } + + /** + * Register an application start/stop listener. + * @param listener listener implementation + */ + public static void addListener(Listener listener) { + if (!listeners.contains(listener)) + listeners.add(listener); + } + + /** + * @return true if the application context is initialized + */ + public static boolean isStarted() { + return started; + } + + /** + * @return true if the application context is initialized and all {@link Listener}s have been notified + */ + public static boolean isReady() { + return started && listenersNotified; + } + + static void startContext() { + if (started) + return; + + started = true; + listeners.sort(new OrderComparator()); + for (Listener listener : listeners) { + listener.applicationStarted(); + } + listenersNotified = true; + } + + /** + * Called by the framework right before the application shutdown. + */ + static void stopContext() { + if (!started) + return; + + started = false; + for (int i = listeners.size() - 1; i >= 0; i--) { + Listener listener = listeners.get(i); + listener.applicationStopped(); + } + if (context != null && context instanceof ConfigurableApplicationContext) { + ((ConfigurableApplicationContext) context).close(); + } + } + + /** + * INTERNAL. + * Contains methods for setting up AppContext internals. + */ + public static class Internals { + + public static void setAppComponents(AppComponents appComponents) { + AppContext.appComponents = appComponents; + AppContext.appProperties = new AppProperties(appComponents); + } + + /** + * Called by the framework to set Spring's context. + * + * @param applicationContext initialized Spring's context + */ + public static void setApplicationContext(@Nullable ApplicationContext applicationContext) { + AppContext.context = applicationContext; + } + + /** + * Called by the framework to replace standard thread-local holder. + * + * @param holder a holder implementation + */ + public static void setSecurityContextHolder(SecurityContextHolder holder) { + AppContext.securityContextHolder = holder; + } + + /** + * Called by the framework after the application has been started and fully initialized. + */ + public static void startContext() { + AppContext.startContext(); + } + + /** + * Called by the framework right before the application shutdown. + */ + public static void stopContext() { + AppContext.stopContext(); + } + } + + public interface SecuredOperation { + T call(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/AvailableLocalesFactory.java b/modules/global/src/com/haulmont/cuba/core/sys/AvailableLocalesFactory.java index 20297e0d0a..4880ad6d4a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/AvailableLocalesFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/AvailableLocalesFactory.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.config.type.TypeFactory; -import org.apache.commons.lang.LocaleUtils; - -import java.util.Arrays; -import java.util.stream.Collectors; - -public class AvailableLocalesFactory extends TypeFactory { - - @Override - public Object build(String string) { - if (string == null) - return null; - - return Arrays.stream(string.split(";")) - .map(item -> item.split("\\|")) - .collect(Collectors.toMap( - parts -> parts[0], - parts -> LocaleUtils.toLocale(parts[1]) - )); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.config.type.TypeFactory; +import org.apache.commons.lang.LocaleUtils; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class AvailableLocalesFactory extends TypeFactory { + + @Override + public Object build(String string) { + if (string == null) + return null; + + return Arrays.stream(string.split(";")) + .map(item -> item.split("\\|")) + .collect(Collectors.toMap( + parts -> parts[0], + parts -> LocaleUtils.toLocale(parts[1]) + )); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/ConfigurationResourceLoader.java b/modules/global/src/com/haulmont/cuba/core/sys/ConfigurationResourceLoader.java index 756a3ed7ce..ba3535582f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/ConfigurationResourceLoader.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/ConfigurationResourceLoader.java @@ -1,90 +1,90 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; -import org.springframework.util.ResourceUtils; - -import java.io.File; - -/** - * System-level class for resource loading.
- * Should be used only in situations where {@link com.haulmont.cuba.core.global.Resources} bean is not available, - * e.g. before the {@link AppContext} is fully initialized. - */ -public class ConfigurationResourceLoader extends DefaultResourceLoader { - - protected File confDir; - - /** - * Constructor for standalone use. - */ - public ConfigurationResourceLoader() { - setConfDir(getDefaultConfDir()); - } - - public ConfigurationResourceLoader(ClassLoader classLoader) { - super(classLoader); - setConfDir(getDefaultConfDir()); - } - - public ConfigurationResourceLoader(ClassLoader classLoader, File confDir) { - super(classLoader); - this.confDir = confDir; - } - - public File getDefaultConfDir() { - return new File(AppContext.getProperty("cuba.confDir")); - } - - public void setConfDir(File confDir) { - this.confDir = confDir; - } - - /** - * Search for a resource according to the following rules: - *
    - *
  • If the location represents an URL, return a new {@link org.springframework.core.io.UrlResource} for - * this URL.
  • - *
  • Try to find a file below the {@code conf} directory using {@code location} as relative path. - * If found, return a new {@link org.springframework.core.io.UrlResource} for this file.
  • - *
  • Otherwise return a new {@link org.springframework.core.io.ClassPathResource} to retrieve content - * from classpath.
  • - *
- * - * @param location resource location - * @return resource reference - */ - @Override - public Resource getResource(String location) { - if (ResourceUtils.isUrl(location)) { - return super.getResource(location); - } else { - if (location.startsWith("/")) - location = location.substring(1); - File file = new File(confDir, location); - if (file.exists()) { - location = file.toURI().toString(); - } else { - location = "classpath:" + location; - } - return super.getResource(location); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.util.ResourceUtils; + +import java.io.File; + +/** + * System-level class for resource loading.
+ * Should be used only in situations where {@link com.haulmont.cuba.core.global.Resources} bean is not available, + * e.g. before the {@link AppContext} is fully initialized. + */ +public class ConfigurationResourceLoader extends DefaultResourceLoader { + + protected File confDir; + + /** + * Constructor for standalone use. + */ + public ConfigurationResourceLoader() { + setConfDir(getDefaultConfDir()); + } + + public ConfigurationResourceLoader(ClassLoader classLoader) { + super(classLoader); + setConfDir(getDefaultConfDir()); + } + + public ConfigurationResourceLoader(ClassLoader classLoader, File confDir) { + super(classLoader); + this.confDir = confDir; + } + + public File getDefaultConfDir() { + return new File(AppContext.getProperty("cuba.confDir")); + } + + public void setConfDir(File confDir) { + this.confDir = confDir; + } + + /** + * Search for a resource according to the following rules: + *
    + *
  • If the location represents an URL, return a new {@link org.springframework.core.io.UrlResource} for + * this URL.
  • + *
  • Try to find a file below the {@code conf} directory using {@code location} as relative path. + * If found, return a new {@link org.springframework.core.io.UrlResource} for this file.
  • + *
  • Otherwise return a new {@link org.springframework.core.io.ClassPathResource} to retrieve content + * from classpath.
  • + *
+ * + * @param location resource location + * @return resource reference + */ + @Override + public Resource getResource(String location) { + if (ResourceUtils.isUrl(location)) { + return super.getResource(location); + } else { + if (location.startsWith("/")) + location = location.substring(1); + File file = new File(confDir, location); + if (file.exists()) { + location = file.toURI().toString(); + } else { + location = "classpath:" + location; + } + return super.getResource(location); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhanced.java b/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhanced.java index 2217c814d7..139bf18b9d 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhanced.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhanced.java @@ -1,26 +1,26 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -/** - * Marker interface for enhanced entities - * - * - */ -public interface CubaEnhanced { -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +/** + * Marker interface for enhanced entities + * + * + */ +public interface CubaEnhanced { +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhancingDisabled.java b/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhancingDisabled.java index e06a6ee945..3942ddad55 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhancingDisabled.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/CubaEnhancingDisabled.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -/** - * Marker interface to be implemented by entities that should not be enhanced. - * - */ -public interface CubaEnhancingDisabled { -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +/** + * Marker interface to be implemented by entities that should not be enhanced. + * + */ +public interface CubaEnhancingDisabled { +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/CubaPropertyPlaceholderConfigurer.java b/modules/global/src/com/haulmont/cuba/core/sys/CubaPropertyPlaceholderConfigurer.java index 2d2a5fa7ff..0eb494e0dd 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/CubaPropertyPlaceholderConfigurer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/CubaPropertyPlaceholderConfigurer.java @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; - -import java.util.Properties; - -public class CubaPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { - - @Override - protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) { - String key = placeholder; - String defValue = null; - String[] parts = placeholder.split("\\?:"); - if (parts.length == 2) { - key = parts[0]; - defValue = parts[1]; - } - - String value = null; - if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) - value = super.resolvePlaceholder(key, props, systemPropertiesMode); - - if (value == null) - value = AppContext.getProperty(key); - - if (value == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) - value = super.resolvePlaceholder(key, props, systemPropertiesMode); - - if (value == null && defValue != null) { - value = defValue; - } - return value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; + +import java.util.Properties; + +public class CubaPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { + + @Override + protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) { + String key = placeholder; + String defValue = null; + String[] parts = placeholder.split("\\?:"); + if (parts.length == 2) { + key = parts[0]; + defValue = parts[1]; + } + + String value = null; + if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) + value = super.resolvePlaceholder(key, props, systemPropertiesMode); + + if (value == null) + value = AppContext.getProperty(key); + + if (value == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) + value = super.resolvePlaceholder(key, props, systemPropertiesMode); + + if (value == null && defValue != null) { + value = defValue; + } + return value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/DbUpdater.java b/modules/global/src/com/haulmont/cuba/core/sys/DbUpdater.java index 2c6481698a..1725930f2d 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/DbUpdater.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/DbUpdater.java @@ -1,29 +1,29 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import java.util.List; - -public interface DbUpdater { - String NAME = "cuba_DbUpdater"; - - boolean dbInitialized() throws DbInitializationException; - - void updateDatabase() throws DbInitializationException; - - List findUpdateDatabaseScripts() throws DbInitializationException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import java.util.List; + +public interface DbUpdater { + String NAME = "cuba_DbUpdater"; + + boolean dbInitialized() throws DbInitializationException; + + void updateDatabase() throws DbInitializationException; + + List findUpdateDatabaseScripts() throws DbInitializationException; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/MetadataBuildSupport.java b/modules/global/src/com/haulmont/cuba/core/sys/MetadataBuildSupport.java index 1bf97c77de..036f2002c1 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/MetadataBuildSupport.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/MetadataBuildSupport.java @@ -1,305 +1,305 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.bali.util.Dom4j; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.chile.core.datatypes.DatatypeRegistry; -import com.haulmont.cuba.core.global.Resources; -import com.haulmont.cuba.core.global.Stores; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrTokenizer; -import org.dom4j.Document; -import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Nullable; -import javax.inject.Inject; -import java.io.InputStream; -import java.lang.reflect.Array; -import java.text.ParseException; -import java.util.*; -import java.util.regex.Pattern; - -@Component("cuba_MetadataBuildSupport") -public class MetadataBuildSupport { - - public static class XmlAnnotation { - public final Object value; - public final Map attributes = new HashMap<>(); - - public XmlAnnotation(Object value) { - this.value = value; - } - } - - public static class XmlAnnotations { - public final String entityClass; - public final Map annotations = new HashMap<>(); - public final List attributeAnnotations = new ArrayList<>(); - - public XmlAnnotations(String entityClass) { - this.entityClass = entityClass; - } - } - - public static class XmlFile { - public final String name; - public final Element root; - - public XmlFile(String name, Element root) { - this.name = name; - this.root = root; - } - } - - private Logger log = LoggerFactory.getLogger(MetadataBuildSupport.class); - - public static final String PERSISTENCE_CONFIG = "cuba.persistenceConfig"; - public static final String METADATA_CONFIG = "cuba.metadataConfig"; - - @Inject - protected Resources resources; - - @Inject - protected DatatypeRegistry datatypes; - - private static final Pattern JAVA_CLASS_PATTERN = Pattern.compile("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*"); - - public List init() { - List metadataXmlList = new ArrayList<>(); - StrTokenizer metadataFilesTokenizer = new StrTokenizer(getMetadataConfig()); - for (String fileName : metadataFilesTokenizer.getTokenArray()) { - metadataXmlList.add(new XmlFile(fileName, readXml(fileName))); - } - return metadataXmlList; - } - - /** - * @param storeName data store name - * @return location of persistent entities descriptor or null if not defined - */ - @Nullable - public String getPersistenceConfig(String storeName) { - String propName = PERSISTENCE_CONFIG; - if (!Stores.isMain(storeName)) - propName = propName + "_" + storeName; - - String config = AppContext.getProperty(propName); - if (StringUtils.isBlank(config)) { - log.trace("Property {} is not set, assuming {} is not a RdbmsStore", propName, storeName); - return null; - } else - return config; - } - - /** - * @return location of metadata descriptor - */ - public String getMetadataConfig() { - String config = AppContext.getProperty(METADATA_CONFIG); - if (StringUtils.isBlank(config)) - throw new IllegalStateException(METADATA_CONFIG + " application property is not defined"); - return config; - } - - public List getDatatypeElements(List metadataXmlList) { - List list = new ArrayList<>(); - for (XmlFile xmlFile : metadataXmlList) { - Element datatypesEl = xmlFile.root.element("datatypes"); - if (datatypesEl != null) { - list.addAll(Dom4j.elements(datatypesEl, "datatype")); - } - } - return list; - } - - public Map> getEntityPackages(List metadataXmlList) { - Map> packages = new LinkedHashMap<>(); - - loadFromMetadataConfig(packages, metadataXmlList); - Stores.getAll().forEach(db -> loadFromPersistenceConfig(packages, db)); - - return packages; - } - - protected void loadFromMetadataConfig(Map> packages, List metadataXmlList) { - for (XmlFile xmlFile : metadataXmlList) { - for (Element element : Dom4j.elements(xmlFile.root, "metadata-model")) { - String rootPackage = element.attributeValue("root-package"); - if (StringUtils.isBlank(rootPackage)) - throw new IllegalStateException("metadata-model/@root-package is empty in " + xmlFile.name); - - List classNames = packages.get(rootPackage); - if (classNames == null) { - classNames = new ArrayList<>(); - packages.put(rootPackage, classNames); - } - for (Element classEl : Dom4j.elements(element, "class")) { - classNames.add(new EntityClassInfo(classEl.attributeValue("store"), classEl.getText().trim(), false)); - } - } - } - } - - protected void loadFromPersistenceConfig(Map> packages, String db) { - String persistenceConfig = getPersistenceConfig(db); - if (persistenceConfig == null) - return; - StrTokenizer persistenceFilesTokenizer = new StrTokenizer(persistenceConfig); - for (String fileName : persistenceFilesTokenizer.getTokenArray()) { - Element root = readXml(fileName); - Element puEl = root.element("persistence-unit"); - if (puEl == null) - throw new IllegalStateException("File " + fileName + " has no persistence-unit element"); - - for (Element classEl : Dom4j.elements(puEl, "class")) { - String className = classEl.getText().trim(); - boolean included = false; - for (String rootPackage : packages.keySet()) { - if (className.startsWith(rootPackage + ".")) { - List classNames = packages.get(rootPackage); - if (classNames == null) { - classNames = new ArrayList<>(); - packages.put(rootPackage, classNames); - } - classNames.add(new EntityClassInfo(db, className, true)); - included = true; - break; - } - } - if (!included) - throw new IllegalStateException("Can not find a model for class " + className - + ". The class's package must be inside of some model's root package."); - } - } - } - - protected Element readXml(String path) { - InputStream stream = resources.getResourceAsStream(path); - try { - stream = resources.getResourceAsStream(path); - if (stream == null) - throw new IllegalStateException("Resource not found: " + path); - Document document = Dom4j.readDocument(stream); - return document.getRootElement(); - } finally { - IOUtils.closeQuietly(stream); - } - } - - public List getEntityAnnotations(List metadataXmlList) { - List result = new ArrayList<>(); - - for (XmlFile xmlFile : metadataXmlList) { - Element annotationsEl = xmlFile.root.element("annotations"); - if (annotationsEl != null) { - for (Element entityEl : Dom4j.elements(annotationsEl, "entity")) { - String className = entityEl.attributeValue("class"); - XmlAnnotations entityAnnotations = new XmlAnnotations(className); - for (Element annotEl : Dom4j.elements(entityEl, "annotation")) { - XmlAnnotation xmlAnnotation = new XmlAnnotation(inferMetaAnnotationType(annotEl.attributeValue("value"))); - for (Element attrEl : Dom4j.elements(annotEl, "attribute")) { - Object value = getXmlAnnotationAttributeValue(attrEl); - xmlAnnotation.attributes.put(attrEl.attributeValue("name"), value); - } - entityAnnotations.annotations.put(annotEl.attributeValue("name"), xmlAnnotation); - } - for (Element propEl : Dom4j.elements(entityEl, "property")) { - XmlAnnotations attributeAnnotations = new XmlAnnotations(propEl.attributeValue("name")); - for (Element annotEl : Dom4j.elements(propEl, "annotation")) { - XmlAnnotation xmlAnnotation = new XmlAnnotation(inferMetaAnnotationType(annotEl.attributeValue("value"))); - for (Element attrEl : Dom4j.elements(annotEl, "attribute")) { - Object value = getXmlAnnotationAttributeValue(attrEl); - xmlAnnotation.attributes.put(attrEl.attributeValue("name"), value); - } - attributeAnnotations.annotations.put(annotEl.attributeValue("name"), xmlAnnotation); - } - entityAnnotations.attributeAnnotations.add(attributeAnnotations); - } - result.add(entityAnnotations); - } - } - } - return result; - } - - private Object getXmlAnnotationAttributeValue(Element attributeEl) { - String value = attributeEl.attributeValue("value"); - String className = attributeEl.attributeValue("class"); - String datatypeName = attributeEl.attributeValue("datatype"); - - List values = Dom4j.elements(attributeEl, "value"); - if (StringUtils.isNotBlank(value)) { - if (!values.isEmpty()) - throw new IllegalStateException("Both 'value' attribute and 'value' element(s) are specified for attribute " + attributeEl.attributeValue("name")); - return getXmlAnnotationAttributeValue(value, className, datatypeName); - } - if (!values.isEmpty()) { - Object val0 = getXmlAnnotationAttributeValue(values.get(0).getTextTrim(), className, datatypeName); - Object array = Array.newInstance(val0.getClass(), values.size()); - Array.set(array, 0, val0); - for (int i = 1; i < values.size(); i++) { - Object val = getXmlAnnotationAttributeValue(values.get(i).getTextTrim(), className, datatypeName); - Array.set(array, i, val); - } - return array; - } - return null; - } - - private Object getXmlAnnotationAttributeValue(String value, String className, String datatypeName) { - if (className == null && datatypeName == null) - return inferMetaAnnotationType(value); - if (className != null) { - Class aClass = ReflectionHelper.getClass(className); - if (aClass.isEnum()) { - //noinspection unchecked - return Enum.valueOf(aClass, value); - } else { - throw new UnsupportedOperationException("Class " + className + " is not Enum"); - } - } else { - try { - return datatypes.get(datatypeName).parse(value); - } catch (ParseException e) { - throw new RuntimeException("Unable to parse XML meta-annotation value", e); - } - } - } - - protected Object inferMetaAnnotationType(String str) { - Object val; - if (str != null && (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false"))) - val = Boolean.valueOf(str); - else if (str != null && JAVA_CLASS_PATTERN.matcher(str).matches()) { - try { - val = ReflectionHelper.loadClass(str); - } catch (ClassNotFoundException e) { - val = str; - } - } else if (!"".equals(str) && StringUtils.isNumeric(str)) { - val = Integer.valueOf(str); - } else - val = str; - return val; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.bali.util.Dom4j; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.chile.core.datatypes.DatatypeRegistry; +import com.haulmont.cuba.core.global.Resources; +import com.haulmont.cuba.core.global.Stores; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrTokenizer; +import org.dom4j.Document; +import org.dom4j.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.text.ParseException; +import java.util.*; +import java.util.regex.Pattern; + +@Component("cuba_MetadataBuildSupport") +public class MetadataBuildSupport { + + public static class XmlAnnotation { + public final Object value; + public final Map attributes = new HashMap<>(); + + public XmlAnnotation(Object value) { + this.value = value; + } + } + + public static class XmlAnnotations { + public final String entityClass; + public final Map annotations = new HashMap<>(); + public final List attributeAnnotations = new ArrayList<>(); + + public XmlAnnotations(String entityClass) { + this.entityClass = entityClass; + } + } + + public static class XmlFile { + public final String name; + public final Element root; + + public XmlFile(String name, Element root) { + this.name = name; + this.root = root; + } + } + + private Logger log = LoggerFactory.getLogger(MetadataBuildSupport.class); + + public static final String PERSISTENCE_CONFIG = "cuba.persistenceConfig"; + public static final String METADATA_CONFIG = "cuba.metadataConfig"; + + @Inject + protected Resources resources; + + @Inject + protected DatatypeRegistry datatypes; + + private static final Pattern JAVA_CLASS_PATTERN = Pattern.compile("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*"); + + public List init() { + List metadataXmlList = new ArrayList<>(); + StrTokenizer metadataFilesTokenizer = new StrTokenizer(getMetadataConfig()); + for (String fileName : metadataFilesTokenizer.getTokenArray()) { + metadataXmlList.add(new XmlFile(fileName, readXml(fileName))); + } + return metadataXmlList; + } + + /** + * @param storeName data store name + * @return location of persistent entities descriptor or null if not defined + */ + @Nullable + public String getPersistenceConfig(String storeName) { + String propName = PERSISTENCE_CONFIG; + if (!Stores.isMain(storeName)) + propName = propName + "_" + storeName; + + String config = AppContext.getProperty(propName); + if (StringUtils.isBlank(config)) { + log.trace("Property {} is not set, assuming {} is not a RdbmsStore", propName, storeName); + return null; + } else + return config; + } + + /** + * @return location of metadata descriptor + */ + public String getMetadataConfig() { + String config = AppContext.getProperty(METADATA_CONFIG); + if (StringUtils.isBlank(config)) + throw new IllegalStateException(METADATA_CONFIG + " application property is not defined"); + return config; + } + + public List getDatatypeElements(List metadataXmlList) { + List list = new ArrayList<>(); + for (XmlFile xmlFile : metadataXmlList) { + Element datatypesEl = xmlFile.root.element("datatypes"); + if (datatypesEl != null) { + list.addAll(Dom4j.elements(datatypesEl, "datatype")); + } + } + return list; + } + + public Map> getEntityPackages(List metadataXmlList) { + Map> packages = new LinkedHashMap<>(); + + loadFromMetadataConfig(packages, metadataXmlList); + Stores.getAll().forEach(db -> loadFromPersistenceConfig(packages, db)); + + return packages; + } + + protected void loadFromMetadataConfig(Map> packages, List metadataXmlList) { + for (XmlFile xmlFile : metadataXmlList) { + for (Element element : Dom4j.elements(xmlFile.root, "metadata-model")) { + String rootPackage = element.attributeValue("root-package"); + if (StringUtils.isBlank(rootPackage)) + throw new IllegalStateException("metadata-model/@root-package is empty in " + xmlFile.name); + + List classNames = packages.get(rootPackage); + if (classNames == null) { + classNames = new ArrayList<>(); + packages.put(rootPackage, classNames); + } + for (Element classEl : Dom4j.elements(element, "class")) { + classNames.add(new EntityClassInfo(classEl.attributeValue("store"), classEl.getText().trim(), false)); + } + } + } + } + + protected void loadFromPersistenceConfig(Map> packages, String db) { + String persistenceConfig = getPersistenceConfig(db); + if (persistenceConfig == null) + return; + StrTokenizer persistenceFilesTokenizer = new StrTokenizer(persistenceConfig); + for (String fileName : persistenceFilesTokenizer.getTokenArray()) { + Element root = readXml(fileName); + Element puEl = root.element("persistence-unit"); + if (puEl == null) + throw new IllegalStateException("File " + fileName + " has no persistence-unit element"); + + for (Element classEl : Dom4j.elements(puEl, "class")) { + String className = classEl.getText().trim(); + boolean included = false; + for (String rootPackage : packages.keySet()) { + if (className.startsWith(rootPackage + ".")) { + List classNames = packages.get(rootPackage); + if (classNames == null) { + classNames = new ArrayList<>(); + packages.put(rootPackage, classNames); + } + classNames.add(new EntityClassInfo(db, className, true)); + included = true; + break; + } + } + if (!included) + throw new IllegalStateException("Can not find a model for class " + className + + ". The class's package must be inside of some model's root package."); + } + } + } + + protected Element readXml(String path) { + InputStream stream = resources.getResourceAsStream(path); + try { + stream = resources.getResourceAsStream(path); + if (stream == null) + throw new IllegalStateException("Resource not found: " + path); + Document document = Dom4j.readDocument(stream); + return document.getRootElement(); + } finally { + IOUtils.closeQuietly(stream); + } + } + + public List getEntityAnnotations(List metadataXmlList) { + List result = new ArrayList<>(); + + for (XmlFile xmlFile : metadataXmlList) { + Element annotationsEl = xmlFile.root.element("annotations"); + if (annotationsEl != null) { + for (Element entityEl : Dom4j.elements(annotationsEl, "entity")) { + String className = entityEl.attributeValue("class"); + XmlAnnotations entityAnnotations = new XmlAnnotations(className); + for (Element annotEl : Dom4j.elements(entityEl, "annotation")) { + XmlAnnotation xmlAnnotation = new XmlAnnotation(inferMetaAnnotationType(annotEl.attributeValue("value"))); + for (Element attrEl : Dom4j.elements(annotEl, "attribute")) { + Object value = getXmlAnnotationAttributeValue(attrEl); + xmlAnnotation.attributes.put(attrEl.attributeValue("name"), value); + } + entityAnnotations.annotations.put(annotEl.attributeValue("name"), xmlAnnotation); + } + for (Element propEl : Dom4j.elements(entityEl, "property")) { + XmlAnnotations attributeAnnotations = new XmlAnnotations(propEl.attributeValue("name")); + for (Element annotEl : Dom4j.elements(propEl, "annotation")) { + XmlAnnotation xmlAnnotation = new XmlAnnotation(inferMetaAnnotationType(annotEl.attributeValue("value"))); + for (Element attrEl : Dom4j.elements(annotEl, "attribute")) { + Object value = getXmlAnnotationAttributeValue(attrEl); + xmlAnnotation.attributes.put(attrEl.attributeValue("name"), value); + } + attributeAnnotations.annotations.put(annotEl.attributeValue("name"), xmlAnnotation); + } + entityAnnotations.attributeAnnotations.add(attributeAnnotations); + } + result.add(entityAnnotations); + } + } + } + return result; + } + + private Object getXmlAnnotationAttributeValue(Element attributeEl) { + String value = attributeEl.attributeValue("value"); + String className = attributeEl.attributeValue("class"); + String datatypeName = attributeEl.attributeValue("datatype"); + + List values = Dom4j.elements(attributeEl, "value"); + if (StringUtils.isNotBlank(value)) { + if (!values.isEmpty()) + throw new IllegalStateException("Both 'value' attribute and 'value' element(s) are specified for attribute " + attributeEl.attributeValue("name")); + return getXmlAnnotationAttributeValue(value, className, datatypeName); + } + if (!values.isEmpty()) { + Object val0 = getXmlAnnotationAttributeValue(values.get(0).getTextTrim(), className, datatypeName); + Object array = Array.newInstance(val0.getClass(), values.size()); + Array.set(array, 0, val0); + for (int i = 1; i < values.size(); i++) { + Object val = getXmlAnnotationAttributeValue(values.get(i).getTextTrim(), className, datatypeName); + Array.set(array, i, val); + } + return array; + } + return null; + } + + private Object getXmlAnnotationAttributeValue(String value, String className, String datatypeName) { + if (className == null && datatypeName == null) + return inferMetaAnnotationType(value); + if (className != null) { + Class aClass = ReflectionHelper.getClass(className); + if (aClass.isEnum()) { + //noinspection unchecked + return Enum.valueOf(aClass, value); + } else { + throw new UnsupportedOperationException("Class " + className + " is not Enum"); + } + } else { + try { + return datatypes.get(datatypeName).parse(value); + } catch (ParseException e) { + throw new RuntimeException("Unable to parse XML meta-annotation value", e); + } + } + } + + protected Object inferMetaAnnotationType(String str) { + Object val; + if (str != null && (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false"))) + val = Boolean.valueOf(str); + else if (str != null && JAVA_CLASS_PATTERN.matcher(str).matches()) { + try { + val = ReflectionHelper.loadClass(str); + } catch (ClassNotFoundException e) { + val = str; + } + } else if (!"".equals(str) && StringUtils.isNumeric(str)) { + val = Integer.valueOf(str); + } else + val = str; + return val; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/NodeIdentifierImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/NodeIdentifierImpl.java index 11b4eb5c19..7f33f487fb 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/NodeIdentifierImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/NodeIdentifierImpl.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.NodeIdentifier; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; - -import org.springframework.stereotype.Component; - -@Component(NodeIdentifier.NAME) -public class NodeIdentifierImpl implements NodeIdentifier { - @Override - public String getNodeName() { - Configuration configuration = AppBeans.get(Configuration.NAME); - GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); - return globalConfig.getWebHostName() + ":" + globalConfig.getWebPort(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.NodeIdentifier; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; + +import org.springframework.stereotype.Component; + +@Component(NodeIdentifier.NAME) +public class NodeIdentifierImpl implements NodeIdentifier { + @Override + public String getNodeName() { + Configuration configuration = AppBeans.get(Configuration.NAME); + GlobalConfig globalConfig = configuration.getConfig(GlobalConfig.class); + return globalConfig.getWebHostName() + ":" + globalConfig.getWebPort(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/PasswordEncryptionImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/PasswordEncryptionImpl.java index 6f2d1732a9..200ac782d5 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/PasswordEncryptionImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/PasswordEncryptionImpl.java @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.global.HashDescriptor; -import com.haulmont.cuba.core.global.PasswordEncryption; -import com.haulmont.cuba.core.sys.encryption.EncryptionModule; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.codec.binary.Base64; - -import org.springframework.stereotype.Component; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.UUID; - -import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; - -@Component(PasswordEncryption.NAME) -public class PasswordEncryptionImpl implements PasswordEncryption { - - private EncryptionModule encryptionModule; - - public void setEncryptionModule(EncryptionModule encryptionModule) { - this.encryptionModule = encryptionModule; - } - - @Override - public String generateRandomPassword() { - SecureRandom random; - try { - random = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Unable to load SHA1PRNG", e); - } - byte[] passwordBytes = new byte[6]; - random.nextBytes(passwordBytes); - return new String(Base64.encodeBase64(passwordBytes), StandardCharsets.UTF_8).replace("=", ""); - } - - @Override - public String getHashMethod() { - return encryptionModule.getHashMethod(); - } - - @Override - public HashDescriptor getHash(String content) { - checkNotNullArgument(content); - - return encryptionModule.getHash(content); - } - - @Override - public String getPasswordHash(UUID userId, String password) { - checkNotNullArgument(userId); - checkNotNullArgument(password); - - return encryptionModule.getPasswordHash(userId, password); - } - - @Override - public String getHash(String content, String salt) { - checkNotNullArgument(content); - checkNotNullArgument(salt); - - return encryptionModule.getHash(content, salt); - } - - @Override - public String getPlainHash(String content) { - checkNotNullArgument(content); - - return encryptionModule.getPlainHash(content); - } - - @Override - public boolean checkPassword(User user, String password) { - checkNotNullArgument(user); - checkNotNullArgument(password); - - return encryptionModule.checkPassword(user, password); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.global.HashDescriptor; +import com.haulmont.cuba.core.global.PasswordEncryption; +import com.haulmont.cuba.core.sys.encryption.EncryptionModule; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.codec.binary.Base64; + +import org.springframework.stereotype.Component; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.UUID; + +import static com.haulmont.bali.util.Preconditions.checkNotNullArgument; + +@Component(PasswordEncryption.NAME) +public class PasswordEncryptionImpl implements PasswordEncryption { + + private EncryptionModule encryptionModule; + + public void setEncryptionModule(EncryptionModule encryptionModule) { + this.encryptionModule = encryptionModule; + } + + @Override + public String generateRandomPassword() { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Unable to load SHA1PRNG", e); + } + byte[] passwordBytes = new byte[6]; + random.nextBytes(passwordBytes); + return new String(Base64.encodeBase64(passwordBytes), StandardCharsets.UTF_8).replace("=", ""); + } + + @Override + public String getHashMethod() { + return encryptionModule.getHashMethod(); + } + + @Override + public HashDescriptor getHash(String content) { + checkNotNullArgument(content); + + return encryptionModule.getHash(content); + } + + @Override + public String getPasswordHash(UUID userId, String password) { + checkNotNullArgument(userId); + checkNotNullArgument(password); + + return encryptionModule.getPasswordHash(userId, password); + } + + @Override + public String getHash(String content, String salt) { + checkNotNullArgument(content); + checkNotNullArgument(salt); + + return encryptionModule.getHash(content, salt); + } + + @Override + public String getPlainHash(String content) { + checkNotNullArgument(content); + + return encryptionModule.getPlainHash(content); + } + + @Override + public boolean checkPassword(User user, String password) { + checkNotNullArgument(user); + checkNotNullArgument(password); + + return encryptionModule.checkPassword(user, password); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/PerformanceLog.java b/modules/global/src/com/haulmont/cuba/core/sys/PerformanceLog.java index e80e963bc9..edd51792f3 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/PerformanceLog.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/PerformanceLog.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Target({java.lang.annotation.ElementType.METHOD, ElementType.TYPE}) -@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) -public @interface PerformanceLog { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({java.lang.annotation.ElementType.METHOD, ElementType.TYPE}) +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +public @interface PerformanceLog { } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/QueryHolder.java b/modules/global/src/com/haulmont/cuba/core/sys/QueryHolder.java index 6b81aaff67..7f28bd2ce0 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/QueryHolder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/QueryHolder.java @@ -1,57 +1,57 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.core.global.LoadContext; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.builder.HashCodeBuilder; - -import java.io.Serializable; - -public class QueryHolder implements Serializable { - - private static final long serialVersionUID = -6055610488135337366L; - - public final LoadContext.Query query; - - public QueryHolder(LoadContext.Query query) { - this.query = query; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - QueryHolder that = (QueryHolder) o; - - if (query == null || that.query == null) return false; - if (!ObjectUtils.equals(query.getQueryString(), that.query.getQueryString())) return false; - if (!ObjectUtils.equals(query.getParameters(), that.query.getParameters())) return false; - - return true; - } - - @Override - public int hashCode() { - if (query != null) { - return query.hashCode(); - } - return super.hashCode(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.core.global.LoadContext; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import java.io.Serializable; + +public class QueryHolder implements Serializable { + + private static final long serialVersionUID = -6055610488135337366L; + + public final LoadContext.Query query; + + public QueryHolder(LoadContext.Query query) { + this.query = query; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + QueryHolder that = (QueryHolder) o; + + if (query == null || that.query == null) return false; + if (!ObjectUtils.equals(query.getQueryString(), that.query.getQueryString())) return false; + if (!ObjectUtils.equals(query.getParameters(), that.query.getParameters())) return false; + + return true; + } + + @Override + public int hashCode() { + if (query != null) { + return query.hashCode(); + } + return super.hashCode(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/SecurityContext.java b/modules/global/src/com/haulmont/cuba/core/sys/SecurityContext.java index 5b67afe2b0..4cdb8ed2e7 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/SecurityContext.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/SecurityContext.java @@ -1,151 +1,151 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.security.global.UserSession; - -import javax.annotation.Nullable; -import java.util.Objects; -import java.util.UUID; - -/** - * Holds information about the current user session. - *
- * Instances of this class are normally set in {@link AppContext} by the framework, but also have to be - * passed to it in case of manually running new threads. Here is the sample code for an asynchronous execution: - *
{@code
- *     final SecurityContext securityContext = AppContext.getSecurityContext();
- *     executor.submit(new Runnable() {
- *         public void run() {
- *             AppContext.setSecurityContext(securityContext);
- *             // business logic here
- *         }
- *     });
- * }
- *
- * The same can be done using {@link SecurityContextAwareRunnable} or {@link SecurityContextAwareCallable} - * wrappers, for example: - *
{@code
- *     executor.submit(new SecurityContextAwareRunnable<>(() -> {
- *         // business logic here
- *     }));
- * }
- * or - *
{@code
- *     Future future = executor.submit(new SecurityContextAwareCallable<>(() -> {
- *         // business logic here
- *         return some_string;
- *     }));
- * }
- */ -public class SecurityContext { - - private final UUID sessionId; - private UserSession session; - private String user; - private int serviceInvocationCount; - - private boolean authorizationRequired; - - public SecurityContext(UUID sessionId) { - Objects.requireNonNull(sessionId, "sessionId is null"); - this.sessionId = sessionId; - } - - public SecurityContext(UUID sessionId, String user) { - this(sessionId); - this.user = user; - } - - public SecurityContext(UserSession session) { - Objects.requireNonNull(session, "session is null"); - this.session = session; - this.sessionId = session.getId(); - this.user = session.getUser().getLogin(); - } - - /** - * @return Current {@link UserSession} ID. This is the only required value for the {@link SecurityContext}. - */ - public UUID getSessionId() { - return sessionId; - } - - /** - * @return current user session. Can be null, so don't rely on this method in application code - use - * {@link com.haulmont.cuba.core.global.UserSessionSource} - */ - @Nullable - public UserSession getSession() { - return session; - } - - /** - * @return current user login. Can be null, so don't rely on this method in application code - use - * {@link com.haulmont.cuba.core.global.UserSessionSource} - */ - @Nullable - public String getUser() { - return user; - } - - /** - * @return Whether the security check is required for standard mechanisms ({@code DataManager} in particular) on - * the middleware - */ - public boolean isAuthorizationRequired() { - return authorizationRequired; - } - - /** - * Whether the security check is required for standard mechanisms ({@code DataManager} in particular) on - * the middleware. Example usage: - *
{@code
-     * boolean saved = AppContext.getSecurityContext().isAuthorizationRequired();
-     * AppContext.getSecurityContext().setAuthorizationRequired(true);
-     * try {
-     *     // all calls to DataManager will apply security restrictions
-     * } finally {
-     *     AppContext.getSecurityContext().setAuthorizationRequired(saved);
-     * }
-     * }
- */ - public void setAuthorizationRequired(boolean authorizationRequired) { - this.authorizationRequired = authorizationRequired; - } - - /** - * INTERNAL. Increment service invocation counter. - */ - int incServiceInvocation() { - return serviceInvocationCount++; - } - - /** - * INTERNAL. Decrement service invocation counter. - */ - int decServiceInvocation() { - return serviceInvocationCount--; - } - - @Override - public String toString() { - return "SecurityContext{" + - "sessionId=" + sessionId + - '}'; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.security.global.UserSession; + +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.UUID; + +/** + * Holds information about the current user session. + *
+ * Instances of this class are normally set in {@link AppContext} by the framework, but also have to be + * passed to it in case of manually running new threads. Here is the sample code for an asynchronous execution: + *
{@code
+ *     final SecurityContext securityContext = AppContext.getSecurityContext();
+ *     executor.submit(new Runnable() {
+ *         public void run() {
+ *             AppContext.setSecurityContext(securityContext);
+ *             // business logic here
+ *         }
+ *     });
+ * }
+ *
+ * The same can be done using {@link SecurityContextAwareRunnable} or {@link SecurityContextAwareCallable} + * wrappers, for example: + *
{@code
+ *     executor.submit(new SecurityContextAwareRunnable<>(() -> {
+ *         // business logic here
+ *     }));
+ * }
+ * or + *
{@code
+ *     Future future = executor.submit(new SecurityContextAwareCallable<>(() -> {
+ *         // business logic here
+ *         return some_string;
+ *     }));
+ * }
+ */ +public class SecurityContext { + + private final UUID sessionId; + private UserSession session; + private String user; + private int serviceInvocationCount; + + private boolean authorizationRequired; + + public SecurityContext(UUID sessionId) { + Objects.requireNonNull(sessionId, "sessionId is null"); + this.sessionId = sessionId; + } + + public SecurityContext(UUID sessionId, String user) { + this(sessionId); + this.user = user; + } + + public SecurityContext(UserSession session) { + Objects.requireNonNull(session, "session is null"); + this.session = session; + this.sessionId = session.getId(); + this.user = session.getUser().getLogin(); + } + + /** + * @return Current {@link UserSession} ID. This is the only required value for the {@link SecurityContext}. + */ + public UUID getSessionId() { + return sessionId; + } + + /** + * @return current user session. Can be null, so don't rely on this method in application code - use + * {@link com.haulmont.cuba.core.global.UserSessionSource} + */ + @Nullable + public UserSession getSession() { + return session; + } + + /** + * @return current user login. Can be null, so don't rely on this method in application code - use + * {@link com.haulmont.cuba.core.global.UserSessionSource} + */ + @Nullable + public String getUser() { + return user; + } + + /** + * @return Whether the security check is required for standard mechanisms ({@code DataManager} in particular) on + * the middleware + */ + public boolean isAuthorizationRequired() { + return authorizationRequired; + } + + /** + * Whether the security check is required for standard mechanisms ({@code DataManager} in particular) on + * the middleware. Example usage: + *
{@code
+     * boolean saved = AppContext.getSecurityContext().isAuthorizationRequired();
+     * AppContext.getSecurityContext().setAuthorizationRequired(true);
+     * try {
+     *     // all calls to DataManager will apply security restrictions
+     * } finally {
+     *     AppContext.getSecurityContext().setAuthorizationRequired(saved);
+     * }
+     * }
+ */ + public void setAuthorizationRequired(boolean authorizationRequired) { + this.authorizationRequired = authorizationRequired; + } + + /** + * INTERNAL. Increment service invocation counter. + */ + int incServiceInvocation() { + return serviceInvocationCount++; + } + + /** + * INTERNAL. Decrement service invocation counter. + */ + int decServiceInvocation() { + return serviceInvocationCount--; + } + + @Override + public String toString() { + return "SecurityContext{" + + "sessionId=" + sessionId + + '}'; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/SecurityContextHolder.java b/modules/global/src/com/haulmont/cuba/core/sys/SecurityContextHolder.java index a3a2ebc8c1..d937f63ae1 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/SecurityContextHolder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/SecurityContextHolder.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -public interface SecurityContextHolder { - - SecurityContext get(); - - void set(SecurityContext securityContext); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +public interface SecurityContextHolder { + + SecurityContext get(); + + void set(SecurityContext securityContext); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/SingleSecurityContextHolder.java b/modules/global/src/com/haulmont/cuba/core/sys/SingleSecurityContextHolder.java index f1564e933b..86ed773fab 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/SingleSecurityContextHolder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/SingleSecurityContextHolder.java @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -public class SingleSecurityContextHolder implements SecurityContextHolder { - - private SecurityContext ctx; - - @Override - public SecurityContext get() { - return ctx; - } - - @Override - public void set(SecurityContext value) { - ctx = value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +public class SingleSecurityContextHolder implements SecurityContextHolder { + + private SecurityContext ctx; + + @Override + public SecurityContext get() { + return ctx; + } + + @Override + public void set(SecurityContext value) { + ctx = value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/ThreadLocalSecurityContextHolder.java b/modules/global/src/com/haulmont/cuba/core/sys/ThreadLocalSecurityContextHolder.java index df1f510f1b..6d5a240e50 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/ThreadLocalSecurityContextHolder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/ThreadLocalSecurityContextHolder.java @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -public class ThreadLocalSecurityContextHolder extends ThreadLocal implements SecurityContextHolder { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +public class ThreadLocalSecurityContextHolder extends ThreadLocal implements SecurityContextHolder { } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/UserSessionFinder.java b/modules/global/src/com/haulmont/cuba/core/sys/UserSessionFinder.java index 3631e707af..c30f476bd6 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/UserSessionFinder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/UserSessionFinder.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys; - -import com.haulmont.cuba.security.global.UserSession; - -import java.util.UUID; - -public interface UserSessionFinder { - - UserSession findSession(UUID sessionId); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys; + +import com.haulmont.cuba.security.global.UserSession; + +import java.util.UUID; + +public interface UserSessionFinder { + + UserSession findSession(UUID sessionId); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/encryption/EncryptionModule.java b/modules/global/src/com/haulmont/cuba/core/sys/encryption/EncryptionModule.java index f4c0a2e9bc..0a7d2a1967 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/encryption/EncryptionModule.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/encryption/EncryptionModule.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.encryption; - -import com.haulmont.cuba.core.global.HashDescriptor; -import com.haulmont.cuba.security.entity.User; - -import java.util.UUID; - -/** - * Encryption algorithm - * - */ -public interface EncryptionModule { - - String getHashMethod(); - - HashDescriptor getHash(String content); - - String getPasswordHash(UUID userId, String password); - - String getHash(String content, String salt); - - String getPlainHash(String content); - - boolean checkPassword(User user, String givenPassword); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.encryption; + +import com.haulmont.cuba.core.global.HashDescriptor; +import com.haulmont.cuba.security.entity.User; + +import java.util.UUID; + +/** + * Encryption algorithm + * + */ +public interface EncryptionModule { + + String getHashMethod(); + + HashDescriptor getHash(String content); + + String getPasswordHash(UUID userId, String password); + + String getHash(String content, String salt); + + String getPlainHash(String content); + + boolean checkPassword(User user, String givenPassword); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/encryption/Md5EncryptionModule.java b/modules/global/src/com/haulmont/cuba/core/sys/encryption/Md5EncryptionModule.java index b57e2fe533..03a6ff7f58 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/encryption/Md5EncryptionModule.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/encryption/Md5EncryptionModule.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.encryption; - -import com.haulmont.cuba.core.global.HashDescriptor; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang.StringUtils; - -import org.springframework.stereotype.Component; -import java.util.UUID; - -@Component("cuba_Md5EncryptionModule") -public class Md5EncryptionModule implements EncryptionModule { - - @Override - public String getHashMethod() { - return "md5"; - } - - @Override - public HashDescriptor getHash(String content) { - return new HashDescriptor(DigestUtils.md5Hex(content), null); - } - - @Override - public String getHash(String content, String salt) { - return getPlainHash(content); - } - - @Override - public String getPlainHash(String content) { - return DigestUtils.md5Hex(content); - } - - @Override - public String getPasswordHash(UUID userId, String password) { - return getPlainHash(password); - } - - @Override - public boolean checkPassword(User user, String password) { - return StringUtils.equals(user.getPassword(), password); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.encryption; + +import com.haulmont.cuba.core.global.HashDescriptor; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang.StringUtils; + +import org.springframework.stereotype.Component; +import java.util.UUID; + +@Component("cuba_Md5EncryptionModule") +public class Md5EncryptionModule implements EncryptionModule { + + @Override + public String getHashMethod() { + return "md5"; + } + + @Override + public HashDescriptor getHash(String content) { + return new HashDescriptor(DigestUtils.md5Hex(content), null); + } + + @Override + public String getHash(String content, String salt) { + return getPlainHash(content); + } + + @Override + public String getPlainHash(String content) { + return DigestUtils.md5Hex(content); + } + + @Override + public String getPasswordHash(UUID userId, String password) { + return getPlainHash(password); + } + + @Override + public boolean checkPassword(User user, String password) { + return StringUtils.equals(user.getPassword(), password); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/encryption/Sha1EncryptionModule.java b/modules/global/src/com/haulmont/cuba/core/sys/encryption/Sha1EncryptionModule.java index a2637de565..63e694ea5f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/encryption/Sha1EncryptionModule.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/encryption/Sha1EncryptionModule.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.encryption; - -import com.haulmont.cuba.core.global.HashDescriptor; -import com.haulmont.cuba.security.entity.User; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.lang.StringUtils; - -import org.springframework.stereotype.Component; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.util.UUID; - -@Component("cuba_Sha1EncryptionModule") -public class Sha1EncryptionModule implements EncryptionModule { - - protected static final String ALGORITHM = "PBKDF2WithHmacSHA1"; - - protected static final String RANDOMIZE_ALGORITHM = "SHA1PRNG"; - protected static final int DERIVED_KEY_LENGTH_BITS = 160; - - protected static final int SALT_LENGTH_BYTES = 8; - - protected static final int ITERATIONS = 20000; - - protected static final String STATIC_SALT = "bae5b072f23b2417"; - - @Override - public String getHashMethod() { - return "sha1"; - } - - @Override - public HashDescriptor getHash(String content) { - String salt; - String result; - try { - salt = generateSalt(); - result = apply(content, salt.getBytes(StandardCharsets.UTF_8)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return new HashDescriptor(result, salt); - } - - @Override - public String getPasswordHash(UUID userId, String password) { - String plainHash = getPlainHash(password); - return getHash(plainHash, userId.toString()); - } - - @Override - public String getHash(String content, String salt) { - if (StringUtils.isEmpty(salt)) - salt = STATIC_SALT; - String result; - try { - result = apply(content, salt.getBytes(StandardCharsets.UTF_8)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return result; - } - - @Override - public String getPlainHash(String content) { - return getHash(content, STATIC_SALT); - } - - @Override - public boolean checkPassword(User user, String password) { - String hashedPassword = getHash(password, user.getId().toString()); - return StringUtils.equals(hashedPassword, user.getPassword()); - } - - protected String generateSalt() throws NoSuchAlgorithmException { - SecureRandom random = SecureRandom.getInstance(RANDOMIZE_ALGORITHM); - byte[] salt = new byte[SALT_LENGTH_BYTES]; - random.nextBytes(salt); - return new String(Hex.encodeHex(salt)); - } - - protected KeySpec getKeySpec(String content, byte[] salt) { - return new PBEKeySpec(content.toCharArray(), salt, ITERATIONS, DERIVED_KEY_LENGTH_BITS); - } - - protected String apply(String content, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { - KeySpec keySpec = getKeySpec(content, salt); - - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); - - byte[] encoded = keyFactory.generateSecret(keySpec).getEncoded(); - return new String(Hex.encodeHex(encoded)); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.encryption; + +import com.haulmont.cuba.core.global.HashDescriptor; +import com.haulmont.cuba.security.entity.User; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang.StringUtils; + +import org.springframework.stereotype.Component; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.UUID; + +@Component("cuba_Sha1EncryptionModule") +public class Sha1EncryptionModule implements EncryptionModule { + + protected static final String ALGORITHM = "PBKDF2WithHmacSHA1"; + + protected static final String RANDOMIZE_ALGORITHM = "SHA1PRNG"; + protected static final int DERIVED_KEY_LENGTH_BITS = 160; + + protected static final int SALT_LENGTH_BYTES = 8; + + protected static final int ITERATIONS = 20000; + + protected static final String STATIC_SALT = "bae5b072f23b2417"; + + @Override + public String getHashMethod() { + return "sha1"; + } + + @Override + public HashDescriptor getHash(String content) { + String salt; + String result; + try { + salt = generateSalt(); + result = apply(content, salt.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return new HashDescriptor(result, salt); + } + + @Override + public String getPasswordHash(UUID userId, String password) { + String plainHash = getPlainHash(password); + return getHash(plainHash, userId.toString()); + } + + @Override + public String getHash(String content, String salt) { + if (StringUtils.isEmpty(salt)) + salt = STATIC_SALT; + String result; + try { + result = apply(content, salt.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return result; + } + + @Override + public String getPlainHash(String content) { + return getHash(content, STATIC_SALT); + } + + @Override + public boolean checkPassword(User user, String password) { + String hashedPassword = getHash(password, user.getId().toString()); + return StringUtils.equals(hashedPassword, user.getPassword()); + } + + protected String generateSalt() throws NoSuchAlgorithmException { + SecureRandom random = SecureRandom.getInstance(RANDOMIZE_ALGORITHM); + byte[] salt = new byte[SALT_LENGTH_BYTES]; + random.nextBytes(salt); + return new String(Hex.encodeHex(salt)); + } + + protected KeySpec getKeySpec(String content, byte[] salt) { + return new PBEKeySpec(content.toCharArray(), salt, ITERATIONS, DERIVED_KEY_LENGTH_BITS); + } + + protected String apply(String content, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { + KeySpec keySpec = getKeySpec(content, salt); + + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); + + byte[] encoded = keyFactory.generateSecret(keySpec).getEncoded(); + return new String(Hex.encodeHex(encoded)); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/encryption/UnsupportedHashMethodException.java b/modules/global/src/com/haulmont/cuba/core/sys/encryption/UnsupportedHashMethodException.java index 3cd3e8cea6..192bbc7523 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/encryption/UnsupportedHashMethodException.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/encryption/UnsupportedHashMethodException.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.encryption; - -import com.haulmont.cuba.core.global.SupportedByClient; - -@SupportedByClient -public class UnsupportedHashMethodException extends RuntimeException { +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.encryption; + +import com.haulmont.cuba.core.global.SupportedByClient; + +@SupportedByClient +public class UnsupportedHashMethodException extends RuntimeException { } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/CompilationScope.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/CompilationScope.java index 5dc5107f48..4ac79c068e 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/CompilationScope.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/CompilationScope.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.HashSet; - -class CompilationScope { - final HashSet compilationNeeded = new HashSet<>(); - - private final HashSet processed = new HashSet<>(); - private final JavaClassLoader javaClassLoader; - private final String rootClassName; - private final SourceProvider sourceProvider; - - public CompilationScope(JavaClassLoader javaClassLoader, String rootClassName) { - this.javaClassLoader = javaClassLoader; - this.sourceProvider = javaClassLoader.sourceProvider; - this.rootClassName = rootClassName; - } - - public boolean compilationNeeded() throws ClassNotFoundException { - collectInformation(rootClassName); - return !CollectionUtils.isEmpty(compilationNeeded); - } - - private void collectInformation(String rootClassName) throws ClassNotFoundException { - if (processed.contains(rootClassName)) { - return; - } - - File srcFile = sourceProvider.getSourceFile(rootClassName); - processed.add(rootClassName); - - TimestampClass timeStampClazz = javaClassLoader.getTimestampClass(rootClassName); - if (timeStampClazz != null) { - if (FileUtils.isFileNewer(srcFile, timeStampClazz.timestamp)) { - compilationNeeded.add(rootClassName); - } else if (!srcFile.exists()) { - throw new ClassNotFoundException( - String.format("Class %s not found. No sources found in file system.", rootClassName)); - } - - for (String dependencyName : timeStampClazz.dependencies) { - collectInformation(dependencyName); - } - } else { - compilationNeeded.add(rootClassName); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.HashSet; + +class CompilationScope { + final HashSet compilationNeeded = new HashSet<>(); + + private final HashSet processed = new HashSet<>(); + private final JavaClassLoader javaClassLoader; + private final String rootClassName; + private final SourceProvider sourceProvider; + + public CompilationScope(JavaClassLoader javaClassLoader, String rootClassName) { + this.javaClassLoader = javaClassLoader; + this.sourceProvider = javaClassLoader.sourceProvider; + this.rootClassName = rootClassName; + } + + public boolean compilationNeeded() throws ClassNotFoundException { + collectInformation(rootClassName); + return !CollectionUtils.isEmpty(compilationNeeded); + } + + private void collectInformation(String rootClassName) throws ClassNotFoundException { + if (processed.contains(rootClassName)) { + return; + } + + File srcFile = sourceProvider.getSourceFile(rootClassName); + processed.add(rootClassName); + + TimestampClass timeStampClazz = javaClassLoader.getTimestampClass(rootClassName); + if (timeStampClazz != null) { + if (FileUtils.isFileNewer(srcFile, timeStampClazz.timestamp)) { + compilationNeeded.add(rootClassName); + } else if (!srcFile.exists()) { + throw new ClassNotFoundException( + String.format("Class %s not found. No sources found in file system.", rootClassName)); + } + + for (String dependencyName : timeStampClazz.dependencies) { + collectInformation(dependencyName); + } + } else { + compilationNeeded.add(rootClassName); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/JavaClassLoader.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/JavaClassLoader.java index 63bb4d03a1..aafc5fabd7 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/JavaClassLoader.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/JavaClassLoader.java @@ -1,297 +1,297 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Multimap; -import com.haulmont.cuba.core.global.Configuration; -import com.haulmont.cuba.core.global.GlobalConfig; -import com.haulmont.cuba.core.global.TimeSource; -import com.haulmont.cuba.core.sys.SpringBeanLoader; -import com.haulmont.cuba.core.sys.javacl.compiler.CharSequenceCompiler; -import org.apache.commons.lang.StringUtils; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -@Component("cuba_JavaClassLoader") -public class JavaClassLoader extends URLClassLoader { - private static final String JAVA_CLASSPATH = System.getProperty("java.class.path"); - private static final String PATH_SEPARATOR = System.getProperty("path.separator"); - private static final String JAR_EXT = ".jar"; - - private static Logger log = LoggerFactory.getLogger(JavaClassLoader.class); - - protected final String cubaClassPath; - protected final String classPath; - - protected final String rootDir; - - protected final Map compiled = new ConcurrentHashMap<>(); - protected final ConcurrentHashMap locks = new ConcurrentHashMap<>(); - - protected final ProxyClassLoader proxyClassLoader; - protected final SourceProvider sourceProvider; - - @Inject - protected TimeSource timeSource; - @Inject - protected SpringBeanLoader springBeanLoader; - - @Inject - public JavaClassLoader(Configuration configuration) { - super(new URL[0], Thread.currentThread().getContextClassLoader()); - - this.proxyClassLoader = new ProxyClassLoader(Thread.currentThread().getContextClassLoader(), compiled); - GlobalConfig config = configuration.getConfig(GlobalConfig.class); - this.rootDir = config.getConfDir() + "/"; - this.cubaClassPath = config.getCubaClasspathDirectories(); - this.classPath = buildClasspath(); - this.sourceProvider = new SourceProvider(rootDir); - } - - //Please use this constructor only in tests - JavaClassLoader(ClassLoader parent, String rootDir, String cubaClassPath, SpringBeanLoader springBeanLoader) { - super(new URL[0], parent); - - Preconditions.checkNotNull(rootDir); - Preconditions.checkNotNull(cubaClassPath); - - this.proxyClassLoader = new ProxyClassLoader(parent, compiled); - this.springBeanLoader = springBeanLoader; - this.rootDir = rootDir; - this.cubaClassPath = cubaClassPath; - this.classPath = buildClasspath(); - this.sourceProvider = new SourceProvider(rootDir); - } - - public void clearCache() { - compiled.clear(); - } - - @Override - public Class loadClass(final String fullClassName, boolean resolve) throws ClassNotFoundException { - String containerClassName = StringUtils.substringBefore(fullClassName, "$"); - - Log4JStopWatch loadingWatch = new Log4JStopWatch("LoadClass"); - try { - lock(containerClassName); - Class clazz; - - if (!sourceProvider.getSourceFile(containerClassName).exists()) { - clazz = super.loadClass(fullClassName, resolve); - return clazz; - } - - CompilationScope compilationScope = new CompilationScope(this, containerClassName); - if (!compilationScope.compilationNeeded()) { - TimestampClass timestampClass = getTimestampClass(fullClassName); - if (timestampClass == null) { - throw new ClassNotFoundException(fullClassName); - } - return timestampClass.clazz; - } - - String src; - try { - src = sourceProvider.getSourceString(containerClassName); - } catch (IOException e) { - throw new ClassNotFoundException("Could not load java sources for class " + containerClassName); - } - - try { - log.debug("Compiling " + containerClassName); - final DiagnosticCollector errs = new DiagnosticCollector<>(); - - SourcesAndDependencies sourcesAndDependencies = new SourcesAndDependencies(rootDir, this); - sourcesAndDependencies.putSource(containerClassName, src); - sourcesAndDependencies.collectDependencies(containerClassName); - Map sourcesForCompilation = sourcesAndDependencies.collectSourcesForCompilation(containerClassName); - - @SuppressWarnings("unchecked") - Map compiledClasses = createCompiler().compile(sourcesForCompilation, errs); - - Map compiledTimestampClasses = wrapCompiledClasses(compiledClasses); - compiled.putAll(compiledTimestampClasses); - linkDependencies(compiledTimestampClasses, sourcesAndDependencies.dependencies); - - clazz = compiledClasses.get(fullClassName); - - springBeanLoader.updateContext(compiledClasses.values()); - - return clazz; - } catch (Exception e) { - proxyClassLoader.restoreRemoved(); - throw new RuntimeException(e); - } finally { - proxyClassLoader.cleanupRemoved(); - } - } finally { - unlock(containerClassName); - loadingWatch.stop(); - } - } - - public boolean removeClass(String className) { - TimestampClass removed = compiled.remove(className); - if (removed != null) { - for (String dependent : removed.dependent) { - removeClass(dependent); - } - } - return removed != null; - } - - public boolean isLoadedClass(String className) { - return compiled.containsKey(className); - } - - public Collection getClassDependencies(String className) { - TimestampClass timestampClass = compiled.get(className); - if (timestampClass != null) { - return timestampClass.dependencies; - } - return Collections.emptyList(); - } - - public Collection getClassDependent(String className) { - TimestampClass timestampClass = compiled.get(className); - if (timestampClass != null) { - return timestampClass.dependent; - } - return Collections.emptyList(); - } - - @Override - public URL findResource(String name) { - if (name.startsWith("/")) - name = name.substring(1); - File file = new File(rootDir, name); - if (file.exists()) { - try { - return file.toURI().toURL(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } else - return null; - } - - @Override - public URL getResource(String name) { - URL resource = findResource(name); - if (resource != null) - return resource; - else - return super.getResource(name); - } - - protected Date getCurrentTimestamp() { - return timeSource.currentTimestamp(); - } - - TimestampClass getTimestampClass(String name) { - return compiled.get(name); - } - - /** - * Wrap each compiled class with TimestampClass - */ - private Map wrapCompiledClasses(Map compiledClasses) { - Map compiledTimestampClasses = new HashMap<>(); - - for (Map.Entry entry : compiledClasses.entrySet()) { - compiledTimestampClasses.put(entry.getKey(), new TimestampClass(entry.getValue(), getCurrentTimestamp())); - } - - return compiledTimestampClasses; - } - - /** - * Add dependencies for each class and ALSO add each class to dependent for each dependency - */ - private void linkDependencies(Map compiledTimestampClasses, - Multimap dependencies) { - for (Map.Entry entry : compiledTimestampClasses.entrySet()) { - String className = entry.getKey(); - TimestampClass timestampClass = entry.getValue(); - - Collection dependencyClasses = dependencies.get(className); - timestampClass.dependencies.addAll(dependencyClasses); - - for (String dependencyClassName : timestampClass.dependencies) { - TimestampClass dependencyClass = compiled.get(dependencyClassName); - if (dependencyClass != null) { - dependencyClass.dependent.add(className); - } - } - } - } - - private CharSequenceCompiler createCompiler() { - return new CharSequenceCompiler( - proxyClassLoader, - Arrays.asList("-classpath", classPath, "-g") - ); - } - - private void unlock(String name) { - locks.get(name).unlock(); - } - - private void lock(String name) {//not sure it's right, but we can not use synchronization here - locks.putIfAbsent(name, new ReentrantLock()); - locks.get(name).lock(); - } - - private String buildClasspath() { - StringBuilder classpathBuilder = new StringBuilder(JAVA_CLASSPATH).append(PATH_SEPARATOR); - - if (cubaClassPath != null) { - String[] directories = cubaClassPath.split(";"); - for (String directoryPath : directories) { - if (StringUtils.isNotBlank(directoryPath)) { - classpathBuilder.append(directoryPath).append(PATH_SEPARATOR); - File directory = new File(directoryPath); - File[] directoryFiles = directory.listFiles(); - if (directoryFiles != null) { - for (File file : directoryFiles) { - if (file.getName().endsWith(JAR_EXT)) { - classpathBuilder.append(file.getAbsolutePath()).append(PATH_SEPARATOR); - } - } - } - } - } - } - return classpathBuilder.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Multimap; +import com.haulmont.cuba.core.global.Configuration; +import com.haulmont.cuba.core.global.GlobalConfig; +import com.haulmont.cuba.core.global.TimeSource; +import com.haulmont.cuba.core.sys.SpringBeanLoader; +import com.haulmont.cuba.core.sys.javacl.compiler.CharSequenceCompiler; +import org.apache.commons.lang.StringUtils; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Component("cuba_JavaClassLoader") +public class JavaClassLoader extends URLClassLoader { + private static final String JAVA_CLASSPATH = System.getProperty("java.class.path"); + private static final String PATH_SEPARATOR = System.getProperty("path.separator"); + private static final String JAR_EXT = ".jar"; + + private static Logger log = LoggerFactory.getLogger(JavaClassLoader.class); + + protected final String cubaClassPath; + protected final String classPath; + + protected final String rootDir; + + protected final Map compiled = new ConcurrentHashMap<>(); + protected final ConcurrentHashMap locks = new ConcurrentHashMap<>(); + + protected final ProxyClassLoader proxyClassLoader; + protected final SourceProvider sourceProvider; + + @Inject + protected TimeSource timeSource; + @Inject + protected SpringBeanLoader springBeanLoader; + + @Inject + public JavaClassLoader(Configuration configuration) { + super(new URL[0], Thread.currentThread().getContextClassLoader()); + + this.proxyClassLoader = new ProxyClassLoader(Thread.currentThread().getContextClassLoader(), compiled); + GlobalConfig config = configuration.getConfig(GlobalConfig.class); + this.rootDir = config.getConfDir() + "/"; + this.cubaClassPath = config.getCubaClasspathDirectories(); + this.classPath = buildClasspath(); + this.sourceProvider = new SourceProvider(rootDir); + } + + //Please use this constructor only in tests + JavaClassLoader(ClassLoader parent, String rootDir, String cubaClassPath, SpringBeanLoader springBeanLoader) { + super(new URL[0], parent); + + Preconditions.checkNotNull(rootDir); + Preconditions.checkNotNull(cubaClassPath); + + this.proxyClassLoader = new ProxyClassLoader(parent, compiled); + this.springBeanLoader = springBeanLoader; + this.rootDir = rootDir; + this.cubaClassPath = cubaClassPath; + this.classPath = buildClasspath(); + this.sourceProvider = new SourceProvider(rootDir); + } + + public void clearCache() { + compiled.clear(); + } + + @Override + public Class loadClass(final String fullClassName, boolean resolve) throws ClassNotFoundException { + String containerClassName = StringUtils.substringBefore(fullClassName, "$"); + + Log4JStopWatch loadingWatch = new Log4JStopWatch("LoadClass"); + try { + lock(containerClassName); + Class clazz; + + if (!sourceProvider.getSourceFile(containerClassName).exists()) { + clazz = super.loadClass(fullClassName, resolve); + return clazz; + } + + CompilationScope compilationScope = new CompilationScope(this, containerClassName); + if (!compilationScope.compilationNeeded()) { + TimestampClass timestampClass = getTimestampClass(fullClassName); + if (timestampClass == null) { + throw new ClassNotFoundException(fullClassName); + } + return timestampClass.clazz; + } + + String src; + try { + src = sourceProvider.getSourceString(containerClassName); + } catch (IOException e) { + throw new ClassNotFoundException("Could not load java sources for class " + containerClassName); + } + + try { + log.debug("Compiling " + containerClassName); + final DiagnosticCollector errs = new DiagnosticCollector<>(); + + SourcesAndDependencies sourcesAndDependencies = new SourcesAndDependencies(rootDir, this); + sourcesAndDependencies.putSource(containerClassName, src); + sourcesAndDependencies.collectDependencies(containerClassName); + Map sourcesForCompilation = sourcesAndDependencies.collectSourcesForCompilation(containerClassName); + + @SuppressWarnings("unchecked") + Map compiledClasses = createCompiler().compile(sourcesForCompilation, errs); + + Map compiledTimestampClasses = wrapCompiledClasses(compiledClasses); + compiled.putAll(compiledTimestampClasses); + linkDependencies(compiledTimestampClasses, sourcesAndDependencies.dependencies); + + clazz = compiledClasses.get(fullClassName); + + springBeanLoader.updateContext(compiledClasses.values()); + + return clazz; + } catch (Exception e) { + proxyClassLoader.restoreRemoved(); + throw new RuntimeException(e); + } finally { + proxyClassLoader.cleanupRemoved(); + } + } finally { + unlock(containerClassName); + loadingWatch.stop(); + } + } + + public boolean removeClass(String className) { + TimestampClass removed = compiled.remove(className); + if (removed != null) { + for (String dependent : removed.dependent) { + removeClass(dependent); + } + } + return removed != null; + } + + public boolean isLoadedClass(String className) { + return compiled.containsKey(className); + } + + public Collection getClassDependencies(String className) { + TimestampClass timestampClass = compiled.get(className); + if (timestampClass != null) { + return timestampClass.dependencies; + } + return Collections.emptyList(); + } + + public Collection getClassDependent(String className) { + TimestampClass timestampClass = compiled.get(className); + if (timestampClass != null) { + return timestampClass.dependent; + } + return Collections.emptyList(); + } + + @Override + public URL findResource(String name) { + if (name.startsWith("/")) + name = name.substring(1); + File file = new File(rootDir, name); + if (file.exists()) { + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } else + return null; + } + + @Override + public URL getResource(String name) { + URL resource = findResource(name); + if (resource != null) + return resource; + else + return super.getResource(name); + } + + protected Date getCurrentTimestamp() { + return timeSource.currentTimestamp(); + } + + TimestampClass getTimestampClass(String name) { + return compiled.get(name); + } + + /** + * Wrap each compiled class with TimestampClass + */ + private Map wrapCompiledClasses(Map compiledClasses) { + Map compiledTimestampClasses = new HashMap<>(); + + for (Map.Entry entry : compiledClasses.entrySet()) { + compiledTimestampClasses.put(entry.getKey(), new TimestampClass(entry.getValue(), getCurrentTimestamp())); + } + + return compiledTimestampClasses; + } + + /** + * Add dependencies for each class and ALSO add each class to dependent for each dependency + */ + private void linkDependencies(Map compiledTimestampClasses, + Multimap dependencies) { + for (Map.Entry entry : compiledTimestampClasses.entrySet()) { + String className = entry.getKey(); + TimestampClass timestampClass = entry.getValue(); + + Collection dependencyClasses = dependencies.get(className); + timestampClass.dependencies.addAll(dependencyClasses); + + for (String dependencyClassName : timestampClass.dependencies) { + TimestampClass dependencyClass = compiled.get(dependencyClassName); + if (dependencyClass != null) { + dependencyClass.dependent.add(className); + } + } + } + } + + private CharSequenceCompiler createCompiler() { + return new CharSequenceCompiler( + proxyClassLoader, + Arrays.asList("-classpath", classPath, "-g") + ); + } + + private void unlock(String name) { + locks.get(name).unlock(); + } + + private void lock(String name) {//not sure it's right, but we can not use synchronization here + locks.putIfAbsent(name, new ReentrantLock()); + locks.get(name).lock(); + } + + private String buildClasspath() { + StringBuilder classpathBuilder = new StringBuilder(JAVA_CLASSPATH).append(PATH_SEPARATOR); + + if (cubaClassPath != null) { + String[] directories = cubaClassPath.split(";"); + for (String directoryPath : directories) { + if (StringUtils.isNotBlank(directoryPath)) { + classpathBuilder.append(directoryPath).append(PATH_SEPARATOR); + File directory = new File(directoryPath); + File[] directoryFiles = directory.listFiles(); + if (directoryFiles != null) { + for (File file : directoryFiles) { + if (file.getName().endsWith(JAR_EXT)) { + classpathBuilder.append(file.getAbsolutePath()).append(PATH_SEPARATOR); + } + } + } + } + } + } + return classpathBuilder.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/ProxyClassLoader.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/ProxyClassLoader.java index a6a43b0803..254f4df950 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/ProxyClassLoader.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/ProxyClassLoader.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import java.util.HashMap; -import java.util.Map; - -public class ProxyClassLoader extends ClassLoader { - Map compiled; - ThreadLocal> removedFromCompilation = new ThreadLocal<>(); - - ProxyClassLoader(ClassLoader parent, Map compiled) { - super(parent); - this.compiled = compiled; - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - TimestampClass tsClass = compiled.get(name); - if (tsClass != null) { - return tsClass.clazz; - } else { - return super.loadClass(name, resolve); - } - } - - public TimestampClass removeFromCache(String className) { - Map removedFromCompilationMap = removedFromCompilation.get(); - if (removedFromCompilationMap == null) { - removedFromCompilationMap = new HashMap<>(); - removedFromCompilation.set(removedFromCompilationMap); - } - - TimestampClass timestampClass = compiled.get(className); - if (timestampClass != null) { - removedFromCompilationMap.put(className, timestampClass); - compiled.remove(className); - return timestampClass; - } - - return null; - } - - public void restoreRemoved() { - Map map = removedFromCompilation.get(); - if (map != null) { - compiled.putAll(map); - } - removedFromCompilation.remove(); - } - - public void cleanupRemoved() { - removedFromCompilation.remove(); - } - - public boolean contains(String className) { - return compiled.containsKey(className); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import java.util.HashMap; +import java.util.Map; + +public class ProxyClassLoader extends ClassLoader { + Map compiled; + ThreadLocal> removedFromCompilation = new ThreadLocal<>(); + + ProxyClassLoader(ClassLoader parent, Map compiled) { + super(parent); + this.compiled = compiled; + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + TimestampClass tsClass = compiled.get(name); + if (tsClass != null) { + return tsClass.clazz; + } else { + return super.loadClass(name, resolve); + } + } + + public TimestampClass removeFromCache(String className) { + Map removedFromCompilationMap = removedFromCompilation.get(); + if (removedFromCompilationMap == null) { + removedFromCompilationMap = new HashMap<>(); + removedFromCompilation.set(removedFromCompilationMap); + } + + TimestampClass timestampClass = compiled.get(className); + if (timestampClass != null) { + removedFromCompilationMap.put(className, timestampClass); + compiled.remove(className); + return timestampClass; + } + + return null; + } + + public void restoreRemoved() { + Map map = removedFromCompilation.get(); + if (map != null) { + compiled.putAll(map); + } + removedFromCompilation.remove(); + } + + public void cleanupRemoved() { + removedFromCompilation.remove(); + } + + public boolean contains(String className) { + return compiled.containsKey(className); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourceProvider.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourceProvider.java index fc79ce0e6c..35d8ee218d 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourceProvider.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourceProvider.java @@ -1,78 +1,78 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import org.apache.commons.io.FileUtils; - -import javax.annotation.Nullable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -class SourceProvider { - public static final String JAVA_EXT = ".java"; - private String rootDir; - - public SourceProvider(String rootDir) { - this.rootDir = rootDir; - } - - public String getSourceString(String name) throws IOException { - File srcFile = getSourceFile(name); - if (!srcFile.exists()) { - throw new FileNotFoundException(String.format("Java source for %s not found", name)); - } - return FileUtils.readFileToString(srcFile, StandardCharsets.UTF_8); - } - - public File getSourceFile(String name) { - String path = name.replace(".", "/"); - return new File(rootDir, path + JAVA_EXT); - } - - public boolean sourceExistsInFileSystem(String className) { - String path = className.replace('.', '/'); - File file = new File(rootDir, path + JAVA_EXT); - return file.exists(); - } - - public boolean directoryExistsInFileSystem(String packageName) { - String path = packageName.replace('.', '/'); - File dir = new File(rootDir, path); - return dir.exists(); - } - - public List getAllClassesFromPackage(@Nullable String packageName) { - String path = packageName != null ? packageName.replace(".", "/") : null; - File srcDir = path != null ? new File(rootDir, path) : new File(rootDir); - String[] fileNames = srcDir.list(); - List classNames = new ArrayList<>(); - if (fileNames != null) { - for (String fileName : fileNames) { - if (fileName.endsWith(JAVA_EXT)) { - String className = fileName.replace(JAVA_EXT, ""); - String fullClassName = packageName != null ? packageName + "." + className : className; - classNames.add(fullClassName); - } - } - } - return classNames; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import org.apache.commons.io.FileUtils; + +import javax.annotation.Nullable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +class SourceProvider { + public static final String JAVA_EXT = ".java"; + private String rootDir; + + public SourceProvider(String rootDir) { + this.rootDir = rootDir; + } + + public String getSourceString(String name) throws IOException { + File srcFile = getSourceFile(name); + if (!srcFile.exists()) { + throw new FileNotFoundException(String.format("Java source for %s not found", name)); + } + return FileUtils.readFileToString(srcFile, StandardCharsets.UTF_8); + } + + public File getSourceFile(String name) { + String path = name.replace(".", "/"); + return new File(rootDir, path + JAVA_EXT); + } + + public boolean sourceExistsInFileSystem(String className) { + String path = className.replace('.', '/'); + File file = new File(rootDir, path + JAVA_EXT); + return file.exists(); + } + + public boolean directoryExistsInFileSystem(String packageName) { + String path = packageName.replace('.', '/'); + File dir = new File(rootDir, path); + return dir.exists(); + } + + public List getAllClassesFromPackage(@Nullable String packageName) { + String path = packageName != null ? packageName.replace(".", "/") : null; + File srcDir = path != null ? new File(rootDir, path) : new File(rootDir); + String[] fileNames = srcDir.list(); + List classNames = new ArrayList<>(); + if (fileNames != null) { + for (String fileName : fileNames) { + if (fileName.endsWith(JAVA_EXT)) { + String className = fileName.replace(JAVA_EXT, ""); + String fullClassName = packageName != null ? packageName + "." + className : className; + classNames.add(fullClassName); + } + } + } + return classNames; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourcesAndDependencies.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourcesAndDependencies.java index 588163dcdf..2ccfa6a312 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourcesAndDependencies.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/SourcesAndDependencies.java @@ -1,159 +1,159 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class SourcesAndDependencies { - private static final String IMPORT_PATTERN = "import (.+?);"; - private static final String IMPORT_STATIC_PATTERN = "import static (.+)\\..+?;"; - public static final String WHOLE_PACKAGE_PLACEHOLDER = ".*"; - - final Map sources = new HashMap<>(); - final Multimap dependencies = HashMultimap.create(); - - private final SourceProvider sourceProvider; - private final JavaClassLoader javaClassLoader; - - SourcesAndDependencies(String rootDir, JavaClassLoader javaClassLoader) { - this.sourceProvider = new SourceProvider(rootDir); - this.javaClassLoader = javaClassLoader; - } - - public void putSource(String name, CharSequence sourceCode) { - sources.put(name, sourceCode); - } - - /** - * Recursively collects all dependencies for class using imports - * - * @throws IOException - */ - public void collectDependencies(String className) throws IOException { - CharSequence src = sources.get(className); - List importedClassesNames = getDynamicallyLoadedImports(src); - String currentPackageName = extractPackageFromClassname(className); - importedClassesNames.addAll(sourceProvider.getAllClassesFromPackage(currentPackageName)); - for (String importedClassName : importedClassesNames) { - if (!sources.containsKey(importedClassName)) { - addSource(importedClassName); - addDependency(className, importedClassName); - collectDependencies(importedClassName); - } else { - addDependency(className, importedClassName); - } - } - } - - - /** - * Decides what to compile using CompilationScope (hierarchical search) - * Find all classes dependent from those we are going to compile and add them to compilation as well - */ - public Map collectSourcesForCompilation(String rootClassName) throws ClassNotFoundException, IOException { - Map dependentSources = new HashMap<>(); - - collectDependent(rootClassName, dependentSources); - for (String dependencyClassName : sources.keySet()) { - CompilationScope dependencyCompilationScope = new CompilationScope(javaClassLoader, dependencyClassName); - if (dependencyCompilationScope.compilationNeeded()) { - collectDependent(dependencyClassName, dependentSources); - } - } - sources.putAll(dependentSources); - return sources; - } - - /** - * Find all dependent classes (hierarchical search) - */ - protected void collectDependent(String dependencyClassName, Map dependentSources) throws IOException { - TimestampClass removedClass = javaClassLoader.proxyClassLoader.removeFromCache(dependencyClassName); - if (removedClass != null) { - for (String dependentName : removedClass.dependent) { - dependentSources.put(dependentName, sourceProvider.getSourceString(dependentName)); - addDependency(dependentName, dependencyClassName); - collectDependent(dependentName, dependentSources); - } - } - } - - protected void addDependency(String dependent, String dependency) { - if (!dependent.equals(dependency)) { - dependencies.put(dependent, dependency); - } - } - - private void addSource(String importedClassName) throws IOException { - sources.put(importedClassName, sourceProvider.getSourceString(importedClassName)); - } - - protected List unwrapImportValue(String importValue) { - if (importValue.endsWith(WHOLE_PACKAGE_PLACEHOLDER)) { - String packageName = importValue.replace(WHOLE_PACKAGE_PLACEHOLDER, ""); - if (sourceProvider.directoryExistsInFileSystem(packageName)) { - return sourceProvider.getAllClassesFromPackage(packageName); - } - } else if (sourceProvider.sourceExistsInFileSystem(importValue)) { - return Collections.singletonList(importValue); - } - - return Collections.emptyList(); - } - - protected List getDynamicallyLoadedImports(CharSequence src) { - List importedClassNames = new ArrayList<>(); - - List importValues = getMatchedStrings(src, IMPORT_PATTERN, 1); - for (String importValue : importValues) { - importedClassNames.addAll(unwrapImportValue(importValue)); - } - - importValues = getMatchedStrings(src, IMPORT_STATIC_PATTERN, 1); - for (String importValue : importValues) { - importedClassNames.addAll(unwrapImportValue(importValue)); - } - return importedClassNames; - } - - protected List getMatchedStrings(CharSequence source, String pattern, int groupNumber) { - ArrayList result = new ArrayList<>(); - Pattern importPattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); - Matcher matcher = importPattern.matcher(source); - while (matcher.find()) { - result.add(matcher.group(groupNumber)); - } - return result; - } - - @Nullable - protected String extractPackageFromClassname(String className) { - int endOfPackageName = className.lastIndexOf('.'); - if (endOfPackageName != -1) { - return className.substring(0, endOfPackageName); - } else { - return null; - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class SourcesAndDependencies { + private static final String IMPORT_PATTERN = "import (.+?);"; + private static final String IMPORT_STATIC_PATTERN = "import static (.+)\\..+?;"; + public static final String WHOLE_PACKAGE_PLACEHOLDER = ".*"; + + final Map sources = new HashMap<>(); + final Multimap dependencies = HashMultimap.create(); + + private final SourceProvider sourceProvider; + private final JavaClassLoader javaClassLoader; + + SourcesAndDependencies(String rootDir, JavaClassLoader javaClassLoader) { + this.sourceProvider = new SourceProvider(rootDir); + this.javaClassLoader = javaClassLoader; + } + + public void putSource(String name, CharSequence sourceCode) { + sources.put(name, sourceCode); + } + + /** + * Recursively collects all dependencies for class using imports + * + * @throws IOException + */ + public void collectDependencies(String className) throws IOException { + CharSequence src = sources.get(className); + List importedClassesNames = getDynamicallyLoadedImports(src); + String currentPackageName = extractPackageFromClassname(className); + importedClassesNames.addAll(sourceProvider.getAllClassesFromPackage(currentPackageName)); + for (String importedClassName : importedClassesNames) { + if (!sources.containsKey(importedClassName)) { + addSource(importedClassName); + addDependency(className, importedClassName); + collectDependencies(importedClassName); + } else { + addDependency(className, importedClassName); + } + } + } + + + /** + * Decides what to compile using CompilationScope (hierarchical search) + * Find all classes dependent from those we are going to compile and add them to compilation as well + */ + public Map collectSourcesForCompilation(String rootClassName) throws ClassNotFoundException, IOException { + Map dependentSources = new HashMap<>(); + + collectDependent(rootClassName, dependentSources); + for (String dependencyClassName : sources.keySet()) { + CompilationScope dependencyCompilationScope = new CompilationScope(javaClassLoader, dependencyClassName); + if (dependencyCompilationScope.compilationNeeded()) { + collectDependent(dependencyClassName, dependentSources); + } + } + sources.putAll(dependentSources); + return sources; + } + + /** + * Find all dependent classes (hierarchical search) + */ + protected void collectDependent(String dependencyClassName, Map dependentSources) throws IOException { + TimestampClass removedClass = javaClassLoader.proxyClassLoader.removeFromCache(dependencyClassName); + if (removedClass != null) { + for (String dependentName : removedClass.dependent) { + dependentSources.put(dependentName, sourceProvider.getSourceString(dependentName)); + addDependency(dependentName, dependencyClassName); + collectDependent(dependentName, dependentSources); + } + } + } + + protected void addDependency(String dependent, String dependency) { + if (!dependent.equals(dependency)) { + dependencies.put(dependent, dependency); + } + } + + private void addSource(String importedClassName) throws IOException { + sources.put(importedClassName, sourceProvider.getSourceString(importedClassName)); + } + + protected List unwrapImportValue(String importValue) { + if (importValue.endsWith(WHOLE_PACKAGE_PLACEHOLDER)) { + String packageName = importValue.replace(WHOLE_PACKAGE_PLACEHOLDER, ""); + if (sourceProvider.directoryExistsInFileSystem(packageName)) { + return sourceProvider.getAllClassesFromPackage(packageName); + } + } else if (sourceProvider.sourceExistsInFileSystem(importValue)) { + return Collections.singletonList(importValue); + } + + return Collections.emptyList(); + } + + protected List getDynamicallyLoadedImports(CharSequence src) { + List importedClassNames = new ArrayList<>(); + + List importValues = getMatchedStrings(src, IMPORT_PATTERN, 1); + for (String importValue : importValues) { + importedClassNames.addAll(unwrapImportValue(importValue)); + } + + importValues = getMatchedStrings(src, IMPORT_STATIC_PATTERN, 1); + for (String importValue : importValues) { + importedClassNames.addAll(unwrapImportValue(importValue)); + } + return importedClassNames; + } + + protected List getMatchedStrings(CharSequence source, String pattern, int groupNumber) { + ArrayList result = new ArrayList<>(); + Pattern importPattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); + Matcher matcher = importPattern.matcher(source); + while (matcher.find()) { + result.add(matcher.group(groupNumber)); + } + return result; + } + + @Nullable + protected String extractPackageFromClassname(String className) { + int endOfPackageName = className.lastIndexOf('.'); + if (endOfPackageName != -1) { + return className.substring(0, endOfPackageName); + } else { + return null; + } + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/TimestampClass.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/TimestampClass.java index ad880b2468..a65c67f9f9 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/TimestampClass.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/TimestampClass.java @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; - -class TimestampClass { - Class clazz; - Date timestamp; - Collection dependencies = new HashSet<>(); - Collection dependent= new HashSet<>(); - - TimestampClass(Class clazz, Date timestamp) { - this.clazz = clazz; - this.timestamp = timestamp; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TimestampClass that = (TimestampClass) o; - - if (clazz != null ? !clazz.equals(that.clazz) : that.clazz != null) return false; - if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = clazz != null ? clazz.hashCode() : 0; - result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0); - return result; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; + +class TimestampClass { + Class clazz; + Date timestamp; + Collection dependencies = new HashSet<>(); + Collection dependent= new HashSet<>(); + + TimestampClass(Class clazz, Date timestamp) { + this.clazz = clazz; + this.timestamp = timestamp; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TimestampClass that = (TimestampClass) o; + + if (clazz != null ? !clazz.equals(that.clazz) : that.clazz != null) return false; + if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = clazz != null ? clazz.hashCode() : 0; + result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0); + return result; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompiler.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompiler.java index 5bd02a5d5e..6cca4e9c6b 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompiler.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompiler.java @@ -1,339 +1,339 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.compiler; - -import com.haulmont.cuba.core.sys.javacl.ProxyClassLoader; - -import javax.tools.*; -import java.util.List; -import java.util.ArrayList; -import java.util.Map; -import java.util.HashMap; -import java.net.URI; -import java.net.URISyntaxException; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.ByteArrayInputStream; -import java.io.OutputStream; - -/** - * Compile a String or other {@link CharSequence}, returning a Java - * {@link Class} instance that may be instantiated. This class is a Facade - * around {@link javax.tools.JavaCompiler} for a narrower use case, but a bit easier to use. - */ -public class CharSequenceCompiler { - // Compiler requires source files with a ".java" extension: - static final String JAVA_EXTENSION = ".java"; - - private final ClassLoaderImpl classLoader; - - // The compiler instance that this facade uses. - private final JavaCompiler compiler; - - // The compiler options (such as "-target" "1.5"). - private final List options; - - // collect compiler diagnostics in this instance. - private DiagnosticCollector diagnostics; - - // The FileManager which will store source and class "files". - private final FileManagerImpl javaFileManager; - - /** - * Construct a new instance which delegates to the named class loader. - * - * @param loader the application ClassLoader. The compiler will look through to - * this // class loader for dependent classes - * @param options The compiler options (such as "-target" "1.5"). See the usage - * for javac - * @throws IllegalStateException if the Java compiler cannot be loaded. - */ - public CharSequenceCompiler(ProxyClassLoader loader, Iterable options) { - compiler = ToolProvider.getSystemJavaCompiler(); - if (compiler == null) { - throw new IllegalStateException("Cannot find the system Java compiler. " - + "Check that your class path includes tools.jar"); - } - classLoader = new ClassLoaderImpl(loader); - diagnostics = new DiagnosticCollector<>(); - final JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, - null, null); - // create our FileManager which chains to the default file manager - // and our ClassLoader - javaFileManager = new FileManagerImpl(fileManager, classLoader); - this.options = new ArrayList<>(); - if (options != null) { // make a save copy of input options - for (String option : options) { - this.options.add(option); - } - } - } - - /** - * Compile Java source in {@code javaSource} and return the resulting - * class.
- * Thread safety: this method is thread safe if the {@code javaSource} - * and {@code diagnosticsList} are isolated to this thread. - * - * @param qualifiedClassName The fully qualified class name. - * @param javaSource Complete java source, including a package statement and a class, - * interface, or annotation declaration. - * @param diagnosticsList Any diagnostics generated by compiling the source are added to - * this collector. - * @param types zero or more Class objects representing classes or interfaces - * that the resulting class must be assignable (castable) to. - * @return a Class which is generated by compiling the source - * @throws CharSequenceCompilerException if the source cannot be compiled - for example, if it contains - * syntax or semantic errors or if dependent classes cannot be - * found. - * @throws ClassCastException if the generated class is not assignable to all the optional - * {@code types}. - */ - public synchronized Class compile(final String qualifiedClassName, - final CharSequence javaSource, - final DiagnosticCollector diagnosticsList, - final Class... types) throws CharSequenceCompilerException, - ClassCastException { - if (diagnosticsList != null) - diagnostics = diagnosticsList; - else - diagnostics = new DiagnosticCollector<>(); - Map classes = new HashMap<>(1); - classes.put(qualifiedClassName, javaSource); - Map> compiled = compile(classes, diagnosticsList); - Class newClass = compiled.get(qualifiedClassName); - return castable(newClass, types); - } - - /** - * Compile multiple Java source strings and return a Map containing the - * resulting classes.
- * Thread safety: this method is thread safe if the {@code classes} and - * {@code diagnosticsList} are isolated to this thread. - * - * @param classes A Map whose keys are qualified class names and whose values are - * the Java source strings containing the definition of the class. - * A map value may be null, indicating that compiled class is - * expected, although no source exists for it (it may be a - * non-public class contained in one of the other strings.) - * @param diagnosticsList Any diagnostics generated by compiling the source are added to - * this list. - * @return A mapping of qualified class names to their corresponding classes. - * The map has the same keys as the input {@code classes}; the - * values are the corresponding Class objects. - * @throws CharSequenceCompilerException if the source cannot be compiled - */ - public synchronized Map> compile( - final Map classes, - final DiagnosticCollector diagnosticsList) - throws CharSequenceCompilerException { - List sources = new ArrayList<>(); - for (Map.Entry entry : classes.entrySet()) { - String qualifiedClassName = entry.getKey(); - CharSequence javaSource = entry.getValue(); - if (javaSource != null) { - final int dotPos = qualifiedClassName.lastIndexOf('.'); - final String className = dotPos == -1 ? qualifiedClassName - : qualifiedClassName.substring(dotPos + 1); - final String packageName = dotPos == -1 ? "" : qualifiedClassName - .substring(0, dotPos); - final JavaFileObjectImpl source = new JavaFileObjectImpl(className, - javaSource); - sources.add(source); - // Store the source file in the FileManager via package/class - // name. - // For source files, we add a .java extension - javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, - className + JAVA_EXTENSION, source); - } - } - // Get a CompilationTask from the compiler and compile the sources - final JavaCompiler.CompilationTask task = compiler.getTask(null, javaFileManager, diagnostics, - options, null, sources); - final Boolean result = task.call(); - if (result == null || !result) { - StringBuilder cause = new StringBuilder("\n"); - for (Diagnostic d : diagnostics.getDiagnostics()) { - cause.append(d).append(" "); - - } - throw new CharSequenceCompilerException("Compilation failed. Causes: " + cause, classes - .keySet(), diagnostics); - } - try { - // For each class name in the input map, get its compiled - // class and put it in the output map - Map> compiled = new HashMap<>(); - for (String qualifiedClassName : classLoader.classNames()) { - final Class newClass = loadClass(qualifiedClassName); - compiled.put(qualifiedClassName, newClass); - } - return compiled; - } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) { - throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); - } - } - - /** - * Load a class that was generated by this instance or accessible from its - * parent class loader. Use this method if you need access to additional - * classes compiled by - * {@link #compile(String, CharSequence, javax.tools.DiagnosticCollector, Class...) compile()}, - * for example if the primary class contained nested classes or additional - * non-public classes. - * - * @param qualifiedClassName the name of the compiled class you wish to load - * @return a Class instance named by {@code qualifiedClassName} - * @throws ClassNotFoundException if no such class is found. - */ - @SuppressWarnings("unchecked") - public Class loadClass(final String qualifiedClassName) - throws ClassNotFoundException { - return (Class) classLoader.loadClass(qualifiedClassName); - } - - /** - * Check that the {@code newClass} is a subtype of all the type - * parameters and throw a ClassCastException if not. - * - * @param types zero of more classes or interfaces that the {@code newClass} - * must be castable to. - * @return {@code newClass} if it is castable to all the types - * @throws ClassCastException if {@code newClass} is not castable to all the types. - */ - private Class castable(Class newClass, Class... types) - throws ClassCastException { - for (Class type : types) - if (!type.isAssignableFrom(newClass)) { - throw new ClassCastException(type.getName()); - } - return newClass; - } - - /** - * Converts a String to a URI. - * - * @param name a file name - * @return a URI - */ - static URI toURI(String name) { - try { - return new URI(name); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - - /** - * @return This compiler's class loader. - */ - public ClassLoader getClassLoader() { - return javaFileManager.getClassLoader(); - } -} - -/** - * A JavaFileObject which contains either the source text or the compiler - * generated class. This class is used in two cases. - *
    - *
  1. This instance uses it to store the source which is passed to the - * compiler. This uses the - * {@link JavaFileObjectImpl#JavaFileObjectImpl(String, CharSequence)} - * constructor. - *
  2. The Java compiler also creates instances (indirectly through the - * FileManagerImplFileManager) when it wants to create a JavaFileObject for the - * .class output. This uses the - * {@link JavaFileObjectImpl#JavaFileObjectImpl(String, javax.tools.JavaFileObject.Kind)} - * constructor. - *
- * This class does not attempt to reuse instances (there does not seem to be a - * need, as it would require adding a Map for the purpose, and this would also - * prevent garbage collection of class byte code.) - */ -final class JavaFileObjectImpl extends SimpleJavaFileObject { - // If kind == CLASS, this stores byte code from openOutputStream - private ByteArrayOutputStream byteCode; - - // if kind == SOURCE, this contains the source text - private final CharSequence source; - - Class definedClass; - - /** - * Construct a new instance which stores source - * - * @param baseName the base name - * @param source the source code - */ - JavaFileObjectImpl(final String baseName, final CharSequence source) { - super(CharSequenceCompiler.toURI(baseName + CharSequenceCompiler.JAVA_EXTENSION), - Kind.SOURCE); - this.source = source; - } - - /** - * Construct a new instance - * - * @param name the file name - * @param kind the kind of file - */ - JavaFileObjectImpl(final String name, final Kind kind) { - super(CharSequenceCompiler.toURI(name), kind); - source = null; - } - - /** - * Return the source code content - * - * @see javax.tools.SimpleJavaFileObject#getCharContent(boolean) - */ - @Override - public CharSequence getCharContent(final boolean ignoreEncodingErrors) - throws UnsupportedOperationException { - if (source == null) - throw new UnsupportedOperationException("getCharContent()"); - return source; - } - - /** - * Return an input stream for reading the byte code - * - * @see javax.tools.SimpleJavaFileObject#openInputStream() - */ - @Override - public InputStream openInputStream() { - return new ByteArrayInputStream(getByteCode()); - } - - /** - * Return an output stream for writing the bytecode - * - * @see javax.tools.SimpleJavaFileObject#openOutputStream() - */ - @Override - public OutputStream openOutputStream() { - byteCode = new ByteArrayOutputStream(); - return byteCode; - } - - /** - * @return the byte code generated by the compiler - */ - byte[] getByteCode() { - return byteCode.toByteArray(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.compiler; + +import com.haulmont.cuba.core.sys.javacl.ProxyClassLoader; + +import javax.tools.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.net.URI; +import java.net.URISyntaxException; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.OutputStream; + +/** + * Compile a String or other {@link CharSequence}, returning a Java + * {@link Class} instance that may be instantiated. This class is a Facade + * around {@link javax.tools.JavaCompiler} for a narrower use case, but a bit easier to use. + */ +public class CharSequenceCompiler { + // Compiler requires source files with a ".java" extension: + static final String JAVA_EXTENSION = ".java"; + + private final ClassLoaderImpl classLoader; + + // The compiler instance that this facade uses. + private final JavaCompiler compiler; + + // The compiler options (such as "-target" "1.5"). + private final List options; + + // collect compiler diagnostics in this instance. + private DiagnosticCollector diagnostics; + + // The FileManager which will store source and class "files". + private final FileManagerImpl javaFileManager; + + /** + * Construct a new instance which delegates to the named class loader. + * + * @param loader the application ClassLoader. The compiler will look through to + * this // class loader for dependent classes + * @param options The compiler options (such as "-target" "1.5"). See the usage + * for javac + * @throws IllegalStateException if the Java compiler cannot be loaded. + */ + public CharSequenceCompiler(ProxyClassLoader loader, Iterable options) { + compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new IllegalStateException("Cannot find the system Java compiler. " + + "Check that your class path includes tools.jar"); + } + classLoader = new ClassLoaderImpl(loader); + diagnostics = new DiagnosticCollector<>(); + final JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, + null, null); + // create our FileManager which chains to the default file manager + // and our ClassLoader + javaFileManager = new FileManagerImpl(fileManager, classLoader); + this.options = new ArrayList<>(); + if (options != null) { // make a save copy of input options + for (String option : options) { + this.options.add(option); + } + } + } + + /** + * Compile Java source in {@code javaSource} and return the resulting + * class.
+ * Thread safety: this method is thread safe if the {@code javaSource} + * and {@code diagnosticsList} are isolated to this thread. + * + * @param qualifiedClassName The fully qualified class name. + * @param javaSource Complete java source, including a package statement and a class, + * interface, or annotation declaration. + * @param diagnosticsList Any diagnostics generated by compiling the source are added to + * this collector. + * @param types zero or more Class objects representing classes or interfaces + * that the resulting class must be assignable (castable) to. + * @return a Class which is generated by compiling the source + * @throws CharSequenceCompilerException if the source cannot be compiled - for example, if it contains + * syntax or semantic errors or if dependent classes cannot be + * found. + * @throws ClassCastException if the generated class is not assignable to all the optional + * {@code types}. + */ + public synchronized Class compile(final String qualifiedClassName, + final CharSequence javaSource, + final DiagnosticCollector diagnosticsList, + final Class... types) throws CharSequenceCompilerException, + ClassCastException { + if (diagnosticsList != null) + diagnostics = diagnosticsList; + else + diagnostics = new DiagnosticCollector<>(); + Map classes = new HashMap<>(1); + classes.put(qualifiedClassName, javaSource); + Map> compiled = compile(classes, diagnosticsList); + Class newClass = compiled.get(qualifiedClassName); + return castable(newClass, types); + } + + /** + * Compile multiple Java source strings and return a Map containing the + * resulting classes.
+ * Thread safety: this method is thread safe if the {@code classes} and + * {@code diagnosticsList} are isolated to this thread. + * + * @param classes A Map whose keys are qualified class names and whose values are + * the Java source strings containing the definition of the class. + * A map value may be null, indicating that compiled class is + * expected, although no source exists for it (it may be a + * non-public class contained in one of the other strings.) + * @param diagnosticsList Any diagnostics generated by compiling the source are added to + * this list. + * @return A mapping of qualified class names to their corresponding classes. + * The map has the same keys as the input {@code classes}; the + * values are the corresponding Class objects. + * @throws CharSequenceCompilerException if the source cannot be compiled + */ + public synchronized Map> compile( + final Map classes, + final DiagnosticCollector diagnosticsList) + throws CharSequenceCompilerException { + List sources = new ArrayList<>(); + for (Map.Entry entry : classes.entrySet()) { + String qualifiedClassName = entry.getKey(); + CharSequence javaSource = entry.getValue(); + if (javaSource != null) { + final int dotPos = qualifiedClassName.lastIndexOf('.'); + final String className = dotPos == -1 ? qualifiedClassName + : qualifiedClassName.substring(dotPos + 1); + final String packageName = dotPos == -1 ? "" : qualifiedClassName + .substring(0, dotPos); + final JavaFileObjectImpl source = new JavaFileObjectImpl(className, + javaSource); + sources.add(source); + // Store the source file in the FileManager via package/class + // name. + // For source files, we add a .java extension + javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, + className + JAVA_EXTENSION, source); + } + } + // Get a CompilationTask from the compiler and compile the sources + final JavaCompiler.CompilationTask task = compiler.getTask(null, javaFileManager, diagnostics, + options, null, sources); + final Boolean result = task.call(); + if (result == null || !result) { + StringBuilder cause = new StringBuilder("\n"); + for (Diagnostic d : diagnostics.getDiagnostics()) { + cause.append(d).append(" "); + + } + throw new CharSequenceCompilerException("Compilation failed. Causes: " + cause, classes + .keySet(), diagnostics); + } + try { + // For each class name in the input map, get its compiled + // class and put it in the output map + Map> compiled = new HashMap<>(); + for (String qualifiedClassName : classLoader.classNames()) { + final Class newClass = loadClass(qualifiedClassName); + compiled.put(qualifiedClassName, newClass); + } + return compiled; + } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) { + throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); + } + } + + /** + * Load a class that was generated by this instance or accessible from its + * parent class loader. Use this method if you need access to additional + * classes compiled by + * {@link #compile(String, CharSequence, javax.tools.DiagnosticCollector, Class...) compile()}, + * for example if the primary class contained nested classes or additional + * non-public classes. + * + * @param qualifiedClassName the name of the compiled class you wish to load + * @return a Class instance named by {@code qualifiedClassName} + * @throws ClassNotFoundException if no such class is found. + */ + @SuppressWarnings("unchecked") + public Class loadClass(final String qualifiedClassName) + throws ClassNotFoundException { + return (Class) classLoader.loadClass(qualifiedClassName); + } + + /** + * Check that the {@code newClass} is a subtype of all the type + * parameters and throw a ClassCastException if not. + * + * @param types zero of more classes or interfaces that the {@code newClass} + * must be castable to. + * @return {@code newClass} if it is castable to all the types + * @throws ClassCastException if {@code newClass} is not castable to all the types. + */ + private Class castable(Class newClass, Class... types) + throws ClassCastException { + for (Class type : types) + if (!type.isAssignableFrom(newClass)) { + throw new ClassCastException(type.getName()); + } + return newClass; + } + + /** + * Converts a String to a URI. + * + * @param name a file name + * @return a URI + */ + static URI toURI(String name) { + try { + return new URI(name); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** + * @return This compiler's class loader. + */ + public ClassLoader getClassLoader() { + return javaFileManager.getClassLoader(); + } +} + +/** + * A JavaFileObject which contains either the source text or the compiler + * generated class. This class is used in two cases. + *
    + *
  1. This instance uses it to store the source which is passed to the + * compiler. This uses the + * {@link JavaFileObjectImpl#JavaFileObjectImpl(String, CharSequence)} + * constructor. + *
  2. The Java compiler also creates instances (indirectly through the + * FileManagerImplFileManager) when it wants to create a JavaFileObject for the + * .class output. This uses the + * {@link JavaFileObjectImpl#JavaFileObjectImpl(String, javax.tools.JavaFileObject.Kind)} + * constructor. + *
+ * This class does not attempt to reuse instances (there does not seem to be a + * need, as it would require adding a Map for the purpose, and this would also + * prevent garbage collection of class byte code.) + */ +final class JavaFileObjectImpl extends SimpleJavaFileObject { + // If kind == CLASS, this stores byte code from openOutputStream + private ByteArrayOutputStream byteCode; + + // if kind == SOURCE, this contains the source text + private final CharSequence source; + + Class definedClass; + + /** + * Construct a new instance which stores source + * + * @param baseName the base name + * @param source the source code + */ + JavaFileObjectImpl(final String baseName, final CharSequence source) { + super(CharSequenceCompiler.toURI(baseName + CharSequenceCompiler.JAVA_EXTENSION), + Kind.SOURCE); + this.source = source; + } + + /** + * Construct a new instance + * + * @param name the file name + * @param kind the kind of file + */ + JavaFileObjectImpl(final String name, final Kind kind) { + super(CharSequenceCompiler.toURI(name), kind); + source = null; + } + + /** + * Return the source code content + * + * @see javax.tools.SimpleJavaFileObject#getCharContent(boolean) + */ + @Override + public CharSequence getCharContent(final boolean ignoreEncodingErrors) + throws UnsupportedOperationException { + if (source == null) + throw new UnsupportedOperationException("getCharContent()"); + return source; + } + + /** + * Return an input stream for reading the byte code + * + * @see javax.tools.SimpleJavaFileObject#openInputStream() + */ + @Override + public InputStream openInputStream() { + return new ByteArrayInputStream(getByteCode()); + } + + /** + * Return an output stream for writing the bytecode + * + * @see javax.tools.SimpleJavaFileObject#openOutputStream() + */ + @Override + public OutputStream openOutputStream() { + byteCode = new ByteArrayOutputStream(); + return byteCode; + } + + /** + * @return the byte code generated by the compiler + */ + byte[] getByteCode() { + return byteCode.toByteArray(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompilerException.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompilerException.java index d7d8aff12d..ebdf7d788c 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompilerException.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/CharSequenceCompilerException.java @@ -1,93 +1,93 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.javacl.compiler; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; - -/** - * An exception thrown when trying to compile Java programs from strings - * containing source. - * - */ -public class CharSequenceCompilerException extends Exception { - private static final long serialVersionUID = 1L; - /** - * The fully qualified name of the class that was being compiled. - */ - private Set classNames; - // Unfortunately, Diagnostic and Collector are not Serializable, so we can't - // serialize the collector. - transient private DiagnosticCollector diagnostics; - - public CharSequenceCompilerException(String message, - Set qualifiedClassNames, Throwable cause, - DiagnosticCollector diagnostics) { - super(message, cause); - setClassNames(qualifiedClassNames); - setDiagnostics(diagnostics); - } - - public CharSequenceCompilerException(String message, - Set qualifiedClassNames, - DiagnosticCollector diagnostics) { - super(message); - setClassNames(qualifiedClassNames); - setDiagnostics(diagnostics); - } - - public CharSequenceCompilerException(Set qualifiedClassNames, - Throwable cause, DiagnosticCollector diagnostics) { - super(cause); - setClassNames(qualifiedClassNames); - setDiagnostics(diagnostics); - } - - private void setClassNames(Set qualifiedClassNames) { - // create a new HashSet because the set passed in may not - // be Serializable. For example, Map.keySet() returns a non-Serializable - // set. - classNames = new HashSet<>(qualifiedClassNames); - } - - private void setDiagnostics(DiagnosticCollector diagnostics) { - this.diagnostics = diagnostics; - } - - /** - * Gets the diagnostics collected by this exception. - * - * @return this exception's diagnostics - */ - public DiagnosticCollector getDiagnostics() { - return diagnostics; - } - - /** - * @return The name of the classes whose compilation caused the compile - * exception - */ - public Collection getClassNames() { - return Collections.unmodifiableSet(classNames); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.javacl.compiler; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; + +/** + * An exception thrown when trying to compile Java programs from strings + * containing source. + * + */ +public class CharSequenceCompilerException extends Exception { + private static final long serialVersionUID = 1L; + /** + * The fully qualified name of the class that was being compiled. + */ + private Set classNames; + // Unfortunately, Diagnostic and Collector are not Serializable, so we can't + // serialize the collector. + transient private DiagnosticCollector diagnostics; + + public CharSequenceCompilerException(String message, + Set qualifiedClassNames, Throwable cause, + DiagnosticCollector diagnostics) { + super(message, cause); + setClassNames(qualifiedClassNames); + setDiagnostics(diagnostics); + } + + public CharSequenceCompilerException(String message, + Set qualifiedClassNames, + DiagnosticCollector diagnostics) { + super(message); + setClassNames(qualifiedClassNames); + setDiagnostics(diagnostics); + } + + public CharSequenceCompilerException(Set qualifiedClassNames, + Throwable cause, DiagnosticCollector diagnostics) { + super(cause); + setClassNames(qualifiedClassNames); + setDiagnostics(diagnostics); + } + + private void setClassNames(Set qualifiedClassNames) { + // create a new HashSet because the set passed in may not + // be Serializable. For example, Map.keySet() returns a non-Serializable + // set. + classNames = new HashSet<>(qualifiedClassNames); + } + + private void setDiagnostics(DiagnosticCollector diagnostics) { + this.diagnostics = diagnostics; + } + + /** + * Gets the diagnostics collected by this exception. + * + * @return this exception's diagnostics + */ + public DiagnosticCollector getDiagnostics() { + return diagnostics; + } + + /** + * @return The name of the classes whose compilation caused the compile + * exception + */ + public Collection getClassNames() { + return Collections.unmodifiableSet(classNames); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/ClassLoaderImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/ClassLoaderImpl.java index 1931f880de..c289b4b7e9 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/ClassLoaderImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/ClassLoaderImpl.java @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.compiler; - -import com.haulmont.cuba.core.sys.javacl.ProxyClassLoader; -import org.apache.commons.lang.StringUtils; - -import javax.tools.JavaFileObject; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * A custom ClassLoader which maps class names to JavaFileObjectImpl instances. - */ -final class ClassLoaderImpl extends ClassLoader { - private final Map classes = new HashMap<>(); - private final ProxyClassLoader proxyClassLoader; - - ClassLoaderImpl(final ProxyClassLoader proxyClassLoader) { - super(proxyClassLoader); - this.proxyClassLoader = proxyClassLoader; - } - - /** - * @return An collection of JavaFileObject instances for the classes in the - * class loader. - */ - Collection files() { - return Collections.unmodifiableCollection(classes.values()); - } - - Collection classNames() { - return Collections.unmodifiableCollection(classes.keySet()); - } - - @Override - protected Class findClass(final String qualifiedClassName) - throws ClassNotFoundException { - JavaFileObject file = classes.get(qualifiedClassName); - if (file != null) { - JavaFileObjectImpl castedFile = (JavaFileObjectImpl) file; - if (castedFile.definedClass != null) { - return castedFile.definedClass; - } else { - - byte[] bytes = castedFile.getByteCode(); - Class justDefinedClass = defineClass(qualifiedClassName, bytes, 0, bytes.length); - castedFile.definedClass = justDefinedClass; - return justDefinedClass; - } - } - // Workaround for "feature" in Java 6 - // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6434149 - try { - Class c = Class.forName(qualifiedClassName); - return c; - } catch (ClassNotFoundException nf) { - // Ignore and fall through - } - return super.findClass(qualifiedClassName); - } - - /** - * Add a class name/JavaFileObject mapping - * - * @param qualifiedClassName the name - * @param javaFile the file associated with the name - */ - void add(final String qualifiedClassName, final JavaFileObject javaFile) { - classes.put(qualifiedClassName, javaFile); - } - - @Override - protected synchronized Class loadClass(final String qualifiedClassName, final boolean resolve) - throws ClassNotFoundException { - if (!cacheContainsFirstLevelClass(qualifiedClassName)) { - Class clazz = findClass(qualifiedClassName); - if (clazz != null) { - return clazz; - } else { - return super.loadClass(qualifiedClassName, resolve); - } - } else { - return super.loadClass(qualifiedClassName, resolve); - } - } - - private boolean cacheContainsFirstLevelClass(String qualifiedClassName) { - String outerClassName = StringUtils.substringBefore(qualifiedClassName, "$"); - return proxyClassLoader.contains(outerClassName); - } - - @Override - public InputStream getResourceAsStream(final String name) { - if (name.endsWith(".class")) { - String qualifiedClassName = name.substring(0, - name.length() - ".class".length()).replace('/', '.'); - JavaFileObjectImpl file = (JavaFileObjectImpl) classes.get(qualifiedClassName); - if (file != null) { - return new ByteArrayInputStream(file.getByteCode()); - } - } - return super.getResourceAsStream(name); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.compiler; + +import com.haulmont.cuba.core.sys.javacl.ProxyClassLoader; +import org.apache.commons.lang.StringUtils; + +import javax.tools.JavaFileObject; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * A custom ClassLoader which maps class names to JavaFileObjectImpl instances. + */ +final class ClassLoaderImpl extends ClassLoader { + private final Map classes = new HashMap<>(); + private final ProxyClassLoader proxyClassLoader; + + ClassLoaderImpl(final ProxyClassLoader proxyClassLoader) { + super(proxyClassLoader); + this.proxyClassLoader = proxyClassLoader; + } + + /** + * @return An collection of JavaFileObject instances for the classes in the + * class loader. + */ + Collection files() { + return Collections.unmodifiableCollection(classes.values()); + } + + Collection classNames() { + return Collections.unmodifiableCollection(classes.keySet()); + } + + @Override + protected Class findClass(final String qualifiedClassName) + throws ClassNotFoundException { + JavaFileObject file = classes.get(qualifiedClassName); + if (file != null) { + JavaFileObjectImpl castedFile = (JavaFileObjectImpl) file; + if (castedFile.definedClass != null) { + return castedFile.definedClass; + } else { + + byte[] bytes = castedFile.getByteCode(); + Class justDefinedClass = defineClass(qualifiedClassName, bytes, 0, bytes.length); + castedFile.definedClass = justDefinedClass; + return justDefinedClass; + } + } + // Workaround for "feature" in Java 6 + // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6434149 + try { + Class c = Class.forName(qualifiedClassName); + return c; + } catch (ClassNotFoundException nf) { + // Ignore and fall through + } + return super.findClass(qualifiedClassName); + } + + /** + * Add a class name/JavaFileObject mapping + * + * @param qualifiedClassName the name + * @param javaFile the file associated with the name + */ + void add(final String qualifiedClassName, final JavaFileObject javaFile) { + classes.put(qualifiedClassName, javaFile); + } + + @Override + protected synchronized Class loadClass(final String qualifiedClassName, final boolean resolve) + throws ClassNotFoundException { + if (!cacheContainsFirstLevelClass(qualifiedClassName)) { + Class clazz = findClass(qualifiedClassName); + if (clazz != null) { + return clazz; + } else { + return super.loadClass(qualifiedClassName, resolve); + } + } else { + return super.loadClass(qualifiedClassName, resolve); + } + } + + private boolean cacheContainsFirstLevelClass(String qualifiedClassName) { + String outerClassName = StringUtils.substringBefore(qualifiedClassName, "$"); + return proxyClassLoader.contains(outerClassName); + } + + @Override + public InputStream getResourceAsStream(final String name) { + if (name.endsWith(".class")) { + String qualifiedClassName = name.substring(0, + name.length() - ".class".length()).replace('/', '.'); + JavaFileObjectImpl file = (JavaFileObjectImpl) classes.get(qualifiedClassName); + if (file != null) { + return new ByteArrayInputStream(file.getByteCode()); + } + } + return super.getResourceAsStream(name); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/FileManagerImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/FileManagerImpl.java index 5b7bac5d1a..459229d7e2 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/FileManagerImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/javacl/compiler/FileManagerImpl.java @@ -1,171 +1,171 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.compiler; - -import javax.tools.*; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * A JavaFileManager which manages Java source and classes. This FileManager - * delegates to the JavaFileManager and the ClassLoaderImpl provided in the - * constructor. The sources are all in memory CharSequence instances and the - * classes are all in memory byte arrays. - * - */ -final class FileManagerImpl extends ForwardingJavaFileManager { - // the delegating class loader (passed to the constructor) - private final ClassLoaderImpl classLoader; - - // Internal map of filename URIs to JavaFileObjects. - private final Map fileObjects = new HashMap<>(); - - /** - * Construct a new FileManager which forwards to the fileManager - * for source and to the classLoader for classes - * - * @param fileManager - * another FileManager that this instance delegates to for - * additional source. - * @param classLoader - * a ClassLoader which contains dependent classes that the compiled - * classes will require when compiling them. - */ - public FileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) { - super(fileManager); - this.classLoader = classLoader; - } - - /** - * @return the class loader which this file manager delegates to - */ - public ClassLoader getClassLoader() { - return classLoader; - } - - /** - * For a given file location, return a FileObject from which the - * compiler can obtain source or byte code. - * - * @param location - * an abstract file location - * @param packageName - * the package name for the file - * @param relativeName - * the file's relative name - * @return a FileObject from this or the delegated FileManager - * @see javax.tools.ForwardingJavaFileManager#getFileForInput(javax.tools.JavaFileManager.Location, - * String, String) - */ - @Override - public FileObject getFileForInput(Location location, String packageName, - String relativeName) throws IOException { - FileObject o = fileObjects.get(uri(location, packageName, relativeName)); - if (o != null) - return o; - return super.getFileForInput(location, packageName, relativeName); - } - - /** - * Store a file that may be retrieved later with - * {@link #getFileForInput(javax.tools.JavaFileManager.Location, String, String)} - * - * @param location - * the file location - * @param packageName - * the Java class' package name - * @param relativeName - * the relative name - * @param file - * the file object to store for later retrieval - */ - public void putFileForInput(StandardLocation location, String packageName, - String relativeName, JavaFileObject file) { - fileObjects.put(uri(location, packageName, relativeName), file); - } - - /** - * Convert a location and class name to a URI - */ - private URI uri(Location location, String packageName, String relativeName) { - return CharSequenceCompiler.toURI(location.getName() + '/' + packageName + '/' - + relativeName); - } - - /** - * Create a JavaFileImpl for an output class file and store it in the - * classloader. - * - * @see javax.tools.ForwardingJavaFileManager#getJavaFileForOutput(javax.tools.JavaFileManager.Location, - * String, javax.tools.JavaFileObject.Kind, - * javax.tools.FileObject) - */ - @Override - public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, - JavaFileObject.Kind kind, FileObject outputFile) throws IOException { - JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind); - classLoader.add(qualifiedName, file); - return file; - } - - @Override - public ClassLoader getClassLoader(Location location) { - return classLoader; - } - - @Override - public String inferBinaryName(Location loc, JavaFileObject file) { - String result; - // For our JavaFileImpl instances, return the file's name, else - // simply run the default implementation - if (file instanceof JavaFileObjectImpl) - result = file.getName(); - else - result = super.inferBinaryName(loc, file); - return result; - } - - @Override - public Iterable list(Location location, String packageName, - Set kinds, boolean recurse) throws IOException { - Iterable result = super.list(location, packageName, kinds, - recurse); - ArrayList files = new ArrayList<>(); - if (location == StandardLocation.CLASS_PATH - && kinds.contains(JavaFileObject.Kind.CLASS)) { - for (JavaFileObject file : fileObjects.values()) { - if (file.getKind() == JavaFileObject.Kind.CLASS && file.getName().startsWith(packageName)) - files.add(file); - } - files.addAll(classLoader.files()); - } else if (location == StandardLocation.SOURCE_PATH - && kinds.contains(JavaFileObject.Kind.SOURCE)) { - for (JavaFileObject file : fileObjects.values()) { - if (file.getKind() == JavaFileObject.Kind.SOURCE && file.getName().startsWith(packageName)) - files.add(file); - } - } - for (JavaFileObject file : result) { - files.add(file); - } - return files; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.compiler; + +import javax.tools.*; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * A JavaFileManager which manages Java source and classes. This FileManager + * delegates to the JavaFileManager and the ClassLoaderImpl provided in the + * constructor. The sources are all in memory CharSequence instances and the + * classes are all in memory byte arrays. + * + */ +final class FileManagerImpl extends ForwardingJavaFileManager { + // the delegating class loader (passed to the constructor) + private final ClassLoaderImpl classLoader; + + // Internal map of filename URIs to JavaFileObjects. + private final Map fileObjects = new HashMap<>(); + + /** + * Construct a new FileManager which forwards to the fileManager + * for source and to the classLoader for classes + * + * @param fileManager + * another FileManager that this instance delegates to for + * additional source. + * @param classLoader + * a ClassLoader which contains dependent classes that the compiled + * classes will require when compiling them. + */ + public FileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) { + super(fileManager); + this.classLoader = classLoader; + } + + /** + * @return the class loader which this file manager delegates to + */ + public ClassLoader getClassLoader() { + return classLoader; + } + + /** + * For a given file location, return a FileObject from which the + * compiler can obtain source or byte code. + * + * @param location + * an abstract file location + * @param packageName + * the package name for the file + * @param relativeName + * the file's relative name + * @return a FileObject from this or the delegated FileManager + * @see javax.tools.ForwardingJavaFileManager#getFileForInput(javax.tools.JavaFileManager.Location, + * String, String) + */ + @Override + public FileObject getFileForInput(Location location, String packageName, + String relativeName) throws IOException { + FileObject o = fileObjects.get(uri(location, packageName, relativeName)); + if (o != null) + return o; + return super.getFileForInput(location, packageName, relativeName); + } + + /** + * Store a file that may be retrieved later with + * {@link #getFileForInput(javax.tools.JavaFileManager.Location, String, String)} + * + * @param location + * the file location + * @param packageName + * the Java class' package name + * @param relativeName + * the relative name + * @param file + * the file object to store for later retrieval + */ + public void putFileForInput(StandardLocation location, String packageName, + String relativeName, JavaFileObject file) { + fileObjects.put(uri(location, packageName, relativeName), file); + } + + /** + * Convert a location and class name to a URI + */ + private URI uri(Location location, String packageName, String relativeName) { + return CharSequenceCompiler.toURI(location.getName() + '/' + packageName + '/' + + relativeName); + } + + /** + * Create a JavaFileImpl for an output class file and store it in the + * classloader. + * + * @see javax.tools.ForwardingJavaFileManager#getJavaFileForOutput(javax.tools.JavaFileManager.Location, + * String, javax.tools.JavaFileObject.Kind, + * javax.tools.FileObject) + */ + @Override + public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, + JavaFileObject.Kind kind, FileObject outputFile) throws IOException { + JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind); + classLoader.add(qualifiedName, file); + return file; + } + + @Override + public ClassLoader getClassLoader(Location location) { + return classLoader; + } + + @Override + public String inferBinaryName(Location loc, JavaFileObject file) { + String result; + // For our JavaFileImpl instances, return the file's name, else + // simply run the default implementation + if (file instanceof JavaFileObjectImpl) + result = file.getName(); + else + result = super.inferBinaryName(loc, file); + return result; + } + + @Override + public Iterable list(Location location, String packageName, + Set kinds, boolean recurse) throws IOException { + Iterable result = super.list(location, packageName, kinds, + recurse); + ArrayList files = new ArrayList<>(); + if (location == StandardLocation.CLASS_PATH + && kinds.contains(JavaFileObject.Kind.CLASS)) { + for (JavaFileObject file : fileObjects.values()) { + if (file.getKind() == JavaFileObject.Kind.CLASS && file.getName().startsWith(packageName)) + files.add(file); + } + files.addAll(classLoader.files()); + } else if (location == StandardLocation.SOURCE_PATH + && kinds.contains(JavaFileObject.Kind.SOURCE)) { + for (JavaFileObject file : fileObjects.values()) { + if (file.getKind() == JavaFileObject.Kind.SOURCE && file.getName().startsWith(packageName)) + files.add(file); + } + } + for (JavaFileObject file : result) { + files.add(file); + } + return files; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jmx/AnnotationMBeanInfoAssembler.java b/modules/global/src/com/haulmont/cuba/core/sys/jmx/AnnotationMBeanInfoAssembler.java index c268eed058..2787e6efef 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jmx/AnnotationMBeanInfoAssembler.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jmx/AnnotationMBeanInfoAssembler.java @@ -1,460 +1,460 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jmx; - -import com.google.common.collect.Maps; -import org.springframework.aop.support.AopUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; -import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler; -import org.springframework.jmx.export.metadata.*; -import org.springframework.jmx.support.JmxUtils; -import org.springframework.jmx.support.MetricType; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -import javax.management.Descriptor; -import javax.management.MBeanParameterInfo; -import javax.management.modelmbean.ModelMBeanNotificationInfo; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Map; - -/** - * This assembler is a hybrid of {@link org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler} - * and {@link org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler}. - *
- * It auto-detects jmx interface either by *-MBean naming convention or by looking for @ManagedResource annotated interface. - * Any getter, setter or operation of jmx interface become JMX-exposed. - * Bean, operation, operation parameter and attribute descriptions can be customized by using spring annotations - * (like for MetadataMBeanInfoAssembler). - *
- * If getter or setter is annotated as @ManagedOperation, it is considered as heavy operation. - * Such method is exposed as operation, not as attribute accessor. - */ -public class AnnotationMBeanInfoAssembler extends AbstractReflectiveMBeanInfoAssembler { - protected static final String FIELD_RUN_ASYNC = "runAsync"; - protected static final String FIELD_TIMEOUT = "timeout"; - - /* Map: Bean name -> jmx interface */ - private Map interfaceCache = Maps.newHashMap(); - - /* Extracts annotation information from jmx interface */ - private JmxAttributeSource attributeSource; - - public AnnotationMBeanInfoAssembler() { - attributeSource = new AnnotationJmxAttributeSource(); - } - - public void setAttributeSource(JmxAttributeSource attributeSource) { - this.attributeSource = attributeSource; - } - - private Class findJmxInterface(String beanKey, Class beanClass) { - Class cachedInterface = interfaceCache.get(beanKey); - if (cachedInterface != null) { - return cachedInterface; - } - - Class mbeanInterface = JmxUtils.getMBeanInterface(beanClass); - if (mbeanInterface != null) { // found with MBean ending - interfaceCache.put(beanKey, mbeanInterface); - return mbeanInterface; - } - - Class[] ifaces = ClassUtils.getAllInterfacesForClass(beanClass); - - for (Class ifc : ifaces) { - ManagedResource metadata = attributeSource.getManagedResource(ifc); - if (metadata != null) { // found with @ManagedResource annotation - interfaceCache.put(beanKey, ifc); - return ifc; - } - } - - String msg = "Bean " + beanKey + " doesn't implement management interfaces. " + - "Management interface should either follow naming scheme or be annotated by @ManagedResource"; - throw new IllegalArgumentException(msg); - } - - /** - * Vote on the inclusion of an attribute accessor. - * - * @param method the accessor method - * @param beanKey the key associated with the MBean in the beans map - * @return whether the method has the appropriate metadata - */ - @Override - protected boolean includeReadAttribute(Method method, String beanKey) { - Method interfaceMethod = findJmxMethod(method, beanKey); - boolean metric = interfaceMethod != null && attributeSource.getManagedMetric(interfaceMethod) != null; - boolean operation = interfaceMethod != null && attributeSource.getManagedOperation(interfaceMethod) != null; - - // either metric or just interface method without @Operation annotation - boolean result = interfaceMethod != null && (metric || !operation); - return result; - } - - /** - * Votes on the inclusion of an attribute mutator. - * - * @param method the mutator method - * @param beanKey the key associated with the MBean in the beans map - * @return whether the method has the appropriate metadata - */ - @Override - protected boolean includeWriteAttribute(Method method, String beanKey) { - Method interfaceMethod = findJmxMethod(method, beanKey); - boolean operation = interfaceMethod != null && attributeSource.getManagedOperation(interfaceMethod) != null; - - // @Operation annotation means it's really an operation, not attribute setter - boolean result = interfaceMethod != null && !operation; - return result; - } - - /** - * Votes on the inclusion of an operation. - * - * @param method the operation method - * @param beanKey the key associated with the MBean in the beans map - * @return whether the method has the appropriate metadata - */ - @Override - protected boolean includeOperation(Method method, String beanKey) { - Method interfaceMethod = findJmxMethod(method, beanKey); - return interfaceMethod != null; - } - - /* Try to find method exposed in bean JMX interface. Return null if not found */ - private Method findJmxMethod(Method method, String beanKey) { - if (method == null) { - return null; - } - Class ifc = findJmxInterface(beanKey, method.getDeclaringClass()); - if (ifc == null) { - return null; - } - - for (Method ifcMethod : ifc.getMethods()) { - if (ifcMethod.getName().equals(method.getName()) && - Arrays.equals(ifcMethod.getParameterTypes(), method.getParameterTypes())) { - return ifcMethod; - } - } - return null; - } - - /** - * Reads managed resource description from the source level metadata. - * Returns an empty {@code String} if no description can be found. - */ - @Override - protected String getDescription(Object managedBean, String beanKey) { - Class ifc = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); - ManagedResource mr = this.attributeSource.getManagedResource(ifc); - return (mr != null ? mr.getDescription() : null); - } - - /** - * Creates a description for the attribute corresponding to this property - * descriptor. Attempts to create the description using metadata from either - * the getter or setter attributes, otherwise uses the property name. - */ - @Override - protected String getAttributeDescription(PropertyDescriptor propertyDescriptor, String beanKey) { - Method readMethod = propertyDescriptor.getReadMethod(); - Method writeMethod = propertyDescriptor.getWriteMethod(); - - Method resolvedGetter = findJmxMethod(readMethod, beanKey); - Method resolvedSetter = findJmxMethod(writeMethod, beanKey); - - ManagedAttribute getter = - (resolvedGetter != null ? this.attributeSource.getManagedAttribute(resolvedGetter) : null); - ManagedAttribute setter = - (resolvedSetter != null ? this.attributeSource.getManagedAttribute(resolvedSetter) : null); - - if (getter != null && StringUtils.hasText(getter.getDescription())) { - return getter.getDescription(); - } else if (setter != null && StringUtils.hasText(setter.getDescription())) { - return setter.getDescription(); - } - - ManagedMetric metric = (resolvedGetter != null ? this.attributeSource.getManagedMetric(resolvedGetter) : null); - if (metric != null && StringUtils.hasText(metric.getDescription())) { - return metric.getDescription(); - } - - return null; - } - - /** - * Retrieves the description for the supplied {@code Method} from the - * metadata. Uses the method name is no description is present in the metadata. - */ - @Override - protected String getOperationDescription(Method method, String beanKey) { - PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); - Method resolvedMethod = findJmxMethod(method, beanKey); - if (pd != null) { - ManagedAttribute ma = this.attributeSource.getManagedAttribute(resolvedMethod); - if (ma != null && StringUtils.hasText(ma.getDescription())) { - return ma.getDescription(); - } - ManagedMetric metric = this.attributeSource.getManagedMetric(resolvedMethod); - if (metric != null && StringUtils.hasText(metric.getDescription())) { - return metric.getDescription(); - } - } - - ManagedOperation mo = this.attributeSource.getManagedOperation(resolvedMethod); - if (mo != null && StringUtils.hasText(mo.getDescription())) { - return mo.getDescription(); - } - return null; // no operation description by default - } - - /** - * Reads {@code MBeanParameterInfo} from the {@code ManagedOperationParameter} - * attributes attached to a method. Returns an empty array of {@code MBeanParameterInfo} - * if no attributes are found. - */ - @Override - protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) { - Method resolvedMethod = findJmxMethod(method, beanKey); - ManagedOperationParameter[] params = this.attributeSource.getManagedOperationParameters(resolvedMethod); - if (params == null || params.length == 0) { - return new MBeanParameterInfo[0]; - } - - MBeanParameterInfo[] parameterInfo = new MBeanParameterInfo[params.length]; - Class[] methodParameters = method.getParameterTypes(); - - for (int i = 0; i < params.length; i++) { - ManagedOperationParameter param = params[i]; - parameterInfo[i] = - new MBeanParameterInfo(param.getName(), methodParameters[i].getName(), param.getDescription()); - } - - return parameterInfo; - } - - /** - * Reads the {@link ManagedNotification} metadata from the {@code Class} of the managed resource - * and generates and returns the corresponding {@link javax.management.modelmbean.ModelMBeanNotificationInfo} metadata. - */ - @Override - protected ModelMBeanNotificationInfo[] getNotificationInfo(Object managedBean, String beanKey) { - Class intf = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); - ManagedNotification[] notificationAttributes = - this.attributeSource.getManagedNotifications(intf); - ModelMBeanNotificationInfo[] notificationInfos = - new ModelMBeanNotificationInfo[notificationAttributes.length]; - - for (int i = 0; i < notificationAttributes.length; i++) { - ManagedNotification attribute = notificationAttributes[i]; - notificationInfos[i] = JmxMetadataUtils.convertToModelMBeanNotificationInfo(attribute); - } - - return notificationInfos; - } - - /** - * Adds descriptor fields from the {@code ManagedResource} attribute - * to the MBean descriptor. Specifically, adds the {@code currencyTimeLimit}, - * {@code persistPolicy}, {@code persistPeriod}, {@code persistLocation} - * and {@code persistName} descriptor fields if they are present in the metadata. - */ - @Override - protected void populateMBeanDescriptor(Descriptor desc, Object managedBean, String beanKey) { - Class intf = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); - ManagedResource mr = this.attributeSource.getManagedResource(intf); - if (mr == null) { - applyDefaultCurrencyTimeLimit(desc); - return; - } - - applyCurrencyTimeLimit(desc, mr.getCurrencyTimeLimit()); - - if (mr.isLog()) { - desc.setField(FIELD_LOG, "true"); - } - if (StringUtils.hasLength(mr.getLogFile())) { - desc.setField(FIELD_LOG_FILE, mr.getLogFile()); - } - - if (StringUtils.hasLength(mr.getPersistPolicy())) { - desc.setField(FIELD_PERSIST_POLICY, mr.getPersistPolicy()); - } - if (mr.getPersistPeriod() >= 0) { - desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(mr.getPersistPeriod())); - } - if (StringUtils.hasLength(mr.getPersistName())) { - desc.setField(FIELD_PERSIST_NAME, mr.getPersistName()); - } - if (StringUtils.hasLength(mr.getPersistLocation())) { - desc.setField(FIELD_PERSIST_LOCATION, mr.getPersistLocation()); - } - } - - /** - * Adds descriptor fields from the {@code ManagedAttribute} attribute or the {@code ManagedMetric} attribute - * to the attribute descriptor. - */ - @Override - protected void populateAttributeDescriptor(Descriptor desc, Method getter, Method setter, String beanKey) { - Method resolvedGetter = findJmxMethod(getter, beanKey); - Method resolvedSetter = findJmxMethod(setter, beanKey); - ManagedMetric metricInfo = resolvedGetter != null ? attributeSource.getManagedMetric(resolvedGetter) : null; - if (getter != null && metricInfo != null) { - populateMetricDescriptor(desc, metricInfo); - } else { - ManagedAttribute gma = - (resolvedGetter == null) ? null : this.attributeSource.getManagedAttribute(resolvedGetter); - ManagedAttribute sma = - (resolvedSetter == null) ? null : this.attributeSource.getManagedAttribute(resolvedSetter); - if (gma == null) { - gma = ManagedAttribute.EMPTY; - } - if (sma == null) { - sma = ManagedAttribute.EMPTY; - } - populateAttributeDescriptor(desc, gma, sma); - } - } - - private void populateAttributeDescriptor(Descriptor desc, ManagedAttribute gma, ManagedAttribute sma) { - applyCurrencyTimeLimit(desc, resolveIntDescriptor(gma.getCurrencyTimeLimit(), sma.getCurrencyTimeLimit())); - - Object defaultValue = resolveObjectDescriptor(gma.getDefaultValue(), sma.getDefaultValue()); - desc.setField(FIELD_DEFAULT, defaultValue); - - String persistPolicy = resolveStringDescriptor(gma.getPersistPolicy(), sma.getPersistPolicy()); - if (StringUtils.hasLength(persistPolicy)) { - desc.setField(FIELD_PERSIST_POLICY, persistPolicy); - } - int persistPeriod = resolveIntDescriptor(gma.getPersistPeriod(), sma.getPersistPeriod()); - if (persistPeriod >= 0) { - desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(persistPeriod)); - } - } - - private void populateMetricDescriptor(Descriptor desc, ManagedMetric metric) { - applyCurrencyTimeLimit(desc, metric.getCurrencyTimeLimit()); - - if (StringUtils.hasLength(metric.getPersistPolicy())) { - desc.setField(FIELD_PERSIST_POLICY, metric.getPersistPolicy()); - } - if (metric.getPersistPeriod() >= 0) { - desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(metric.getPersistPeriod())); - } - - if (StringUtils.hasLength(metric.getDisplayName())) { - desc.setField(FIELD_DISPLAY_NAME, metric.getDisplayName()); - } - - if (StringUtils.hasLength(metric.getUnit())) { - desc.setField(FIELD_UNITS, metric.getUnit()); - } - - if (StringUtils.hasLength(metric.getCategory())) { - desc.setField(FIELD_METRIC_CATEGORY, metric.getCategory()); - } - - String metricType = (metric.getMetricType() == null) ? MetricType.GAUGE.toString() : metric.getMetricType().toString(); - desc.setField(FIELD_METRIC_TYPE, metricType); - } - - /** - * Adds descriptor fields from the {@code ManagedAttribute} attribute - * to the attribute descriptor. Specifically, adds the {@code currencyTimeLimit} - * descriptor field if it is present in the metadata. - */ - @Override - protected void populateOperationDescriptor(Descriptor desc, Method method, String beanKey) { - Method resolvedOperation = findJmxMethod(method, beanKey); - ManagedOperation mo = this.attributeSource.getManagedOperation(resolvedOperation); - - if (resolvedOperation != null) { - applyRunAsync(desc, resolvedOperation); - } - - if (mo != null) { - applyCurrencyTimeLimit(desc, mo.getCurrencyTimeLimit()); - } - } - - /** - * Adds fields to the operation descriptor in case of operation should be executed asynchronously if - * operation was annotated by {@link JmxRunAsync}. - * - * @param desc operation descriptor - * @param operation operation - */ - protected void applyRunAsync(Descriptor desc, Method operation) { - JmxRunAsync jmxRunAsync = operation.getAnnotation(JmxRunAsync.class); - if (jmxRunAsync == null) { - return; - } - - desc.setField(FIELD_RUN_ASYNC, true); - desc.setField(FIELD_TIMEOUT, jmxRunAsync.timeout()); - } - - /** - * Determines which of two {@code int} values should be used as the value - * for an attribute descriptor. In general, only the getter or the setter will - * be have a non-negative value so we use that value. In the event that both values - * are non-negative, we use the greater of the two. This method can be used to - * resolve any {@code int} valued descriptor where there are two possible values. - * - * @param getter the int value associated with the getter for this attribute - * @param setter the int associated with the setter for this attribute - */ - private int resolveIntDescriptor(int getter, int setter) { - return (getter >= setter ? getter : setter); - } - - /** - * Locates the value of a descriptor based on values attached - * to both the getter and setter methods. If both have values - * supplied then the value attached to the getter is preferred. - * - * @param getter the Object value associated with the get method - * @param setter the Object value associated with the set method - * @return the appropriate Object to use as the value for the descriptor - */ - private Object resolveObjectDescriptor(Object getter, Object setter) { - return (getter != null ? getter : setter); - } - - /** - * Locates the value of a descriptor based on values attached - * to both the getter and setter methods. If both have values - * supplied then the value attached to the getter is preferred. - * The supplied default value is used to check to see if the value - * associated with the getter has changed from the default. - * - * @param getter the String value associated with the get method - * @param setter the String value associated with the set method - * @return the appropriate String to use as the value for the descriptor - */ - private String resolveStringDescriptor(String getter, String setter) { - return (StringUtils.hasLength(getter) ? getter : setter); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jmx; + +import com.google.common.collect.Maps; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; +import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler; +import org.springframework.jmx.export.metadata.*; +import org.springframework.jmx.support.JmxUtils; +import org.springframework.jmx.support.MetricType; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import javax.management.Descriptor; +import javax.management.MBeanParameterInfo; +import javax.management.modelmbean.ModelMBeanNotificationInfo; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Map; + +/** + * This assembler is a hybrid of {@link org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler} + * and {@link org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler}. + *
+ * It auto-detects jmx interface either by *-MBean naming convention or by looking for @ManagedResource annotated interface. + * Any getter, setter or operation of jmx interface become JMX-exposed. + * Bean, operation, operation parameter and attribute descriptions can be customized by using spring annotations + * (like for MetadataMBeanInfoAssembler). + *
+ * If getter or setter is annotated as @ManagedOperation, it is considered as heavy operation. + * Such method is exposed as operation, not as attribute accessor. + */ +public class AnnotationMBeanInfoAssembler extends AbstractReflectiveMBeanInfoAssembler { + protected static final String FIELD_RUN_ASYNC = "runAsync"; + protected static final String FIELD_TIMEOUT = "timeout"; + + /* Map: Bean name -> jmx interface */ + private Map interfaceCache = Maps.newHashMap(); + + /* Extracts annotation information from jmx interface */ + private JmxAttributeSource attributeSource; + + public AnnotationMBeanInfoAssembler() { + attributeSource = new AnnotationJmxAttributeSource(); + } + + public void setAttributeSource(JmxAttributeSource attributeSource) { + this.attributeSource = attributeSource; + } + + private Class findJmxInterface(String beanKey, Class beanClass) { + Class cachedInterface = interfaceCache.get(beanKey); + if (cachedInterface != null) { + return cachedInterface; + } + + Class mbeanInterface = JmxUtils.getMBeanInterface(beanClass); + if (mbeanInterface != null) { // found with MBean ending + interfaceCache.put(beanKey, mbeanInterface); + return mbeanInterface; + } + + Class[] ifaces = ClassUtils.getAllInterfacesForClass(beanClass); + + for (Class ifc : ifaces) { + ManagedResource metadata = attributeSource.getManagedResource(ifc); + if (metadata != null) { // found with @ManagedResource annotation + interfaceCache.put(beanKey, ifc); + return ifc; + } + } + + String msg = "Bean " + beanKey + " doesn't implement management interfaces. " + + "Management interface should either follow naming scheme or be annotated by @ManagedResource"; + throw new IllegalArgumentException(msg); + } + + /** + * Vote on the inclusion of an attribute accessor. + * + * @param method the accessor method + * @param beanKey the key associated with the MBean in the beans map + * @return whether the method has the appropriate metadata + */ + @Override + protected boolean includeReadAttribute(Method method, String beanKey) { + Method interfaceMethod = findJmxMethod(method, beanKey); + boolean metric = interfaceMethod != null && attributeSource.getManagedMetric(interfaceMethod) != null; + boolean operation = interfaceMethod != null && attributeSource.getManagedOperation(interfaceMethod) != null; + + // either metric or just interface method without @Operation annotation + boolean result = interfaceMethod != null && (metric || !operation); + return result; + } + + /** + * Votes on the inclusion of an attribute mutator. + * + * @param method the mutator method + * @param beanKey the key associated with the MBean in the beans map + * @return whether the method has the appropriate metadata + */ + @Override + protected boolean includeWriteAttribute(Method method, String beanKey) { + Method interfaceMethod = findJmxMethod(method, beanKey); + boolean operation = interfaceMethod != null && attributeSource.getManagedOperation(interfaceMethod) != null; + + // @Operation annotation means it's really an operation, not attribute setter + boolean result = interfaceMethod != null && !operation; + return result; + } + + /** + * Votes on the inclusion of an operation. + * + * @param method the operation method + * @param beanKey the key associated with the MBean in the beans map + * @return whether the method has the appropriate metadata + */ + @Override + protected boolean includeOperation(Method method, String beanKey) { + Method interfaceMethod = findJmxMethod(method, beanKey); + return interfaceMethod != null; + } + + /* Try to find method exposed in bean JMX interface. Return null if not found */ + private Method findJmxMethod(Method method, String beanKey) { + if (method == null) { + return null; + } + Class ifc = findJmxInterface(beanKey, method.getDeclaringClass()); + if (ifc == null) { + return null; + } + + for (Method ifcMethod : ifc.getMethods()) { + if (ifcMethod.getName().equals(method.getName()) && + Arrays.equals(ifcMethod.getParameterTypes(), method.getParameterTypes())) { + return ifcMethod; + } + } + return null; + } + + /** + * Reads managed resource description from the source level metadata. + * Returns an empty {@code String} if no description can be found. + */ + @Override + protected String getDescription(Object managedBean, String beanKey) { + Class ifc = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); + ManagedResource mr = this.attributeSource.getManagedResource(ifc); + return (mr != null ? mr.getDescription() : null); + } + + /** + * Creates a description for the attribute corresponding to this property + * descriptor. Attempts to create the description using metadata from either + * the getter or setter attributes, otherwise uses the property name. + */ + @Override + protected String getAttributeDescription(PropertyDescriptor propertyDescriptor, String beanKey) { + Method readMethod = propertyDescriptor.getReadMethod(); + Method writeMethod = propertyDescriptor.getWriteMethod(); + + Method resolvedGetter = findJmxMethod(readMethod, beanKey); + Method resolvedSetter = findJmxMethod(writeMethod, beanKey); + + ManagedAttribute getter = + (resolvedGetter != null ? this.attributeSource.getManagedAttribute(resolvedGetter) : null); + ManagedAttribute setter = + (resolvedSetter != null ? this.attributeSource.getManagedAttribute(resolvedSetter) : null); + + if (getter != null && StringUtils.hasText(getter.getDescription())) { + return getter.getDescription(); + } else if (setter != null && StringUtils.hasText(setter.getDescription())) { + return setter.getDescription(); + } + + ManagedMetric metric = (resolvedGetter != null ? this.attributeSource.getManagedMetric(resolvedGetter) : null); + if (metric != null && StringUtils.hasText(metric.getDescription())) { + return metric.getDescription(); + } + + return null; + } + + /** + * Retrieves the description for the supplied {@code Method} from the + * metadata. Uses the method name is no description is present in the metadata. + */ + @Override + protected String getOperationDescription(Method method, String beanKey) { + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + Method resolvedMethod = findJmxMethod(method, beanKey); + if (pd != null) { + ManagedAttribute ma = this.attributeSource.getManagedAttribute(resolvedMethod); + if (ma != null && StringUtils.hasText(ma.getDescription())) { + return ma.getDescription(); + } + ManagedMetric metric = this.attributeSource.getManagedMetric(resolvedMethod); + if (metric != null && StringUtils.hasText(metric.getDescription())) { + return metric.getDescription(); + } + } + + ManagedOperation mo = this.attributeSource.getManagedOperation(resolvedMethod); + if (mo != null && StringUtils.hasText(mo.getDescription())) { + return mo.getDescription(); + } + return null; // no operation description by default + } + + /** + * Reads {@code MBeanParameterInfo} from the {@code ManagedOperationParameter} + * attributes attached to a method. Returns an empty array of {@code MBeanParameterInfo} + * if no attributes are found. + */ + @Override + protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) { + Method resolvedMethod = findJmxMethod(method, beanKey); + ManagedOperationParameter[] params = this.attributeSource.getManagedOperationParameters(resolvedMethod); + if (params == null || params.length == 0) { + return new MBeanParameterInfo[0]; + } + + MBeanParameterInfo[] parameterInfo = new MBeanParameterInfo[params.length]; + Class[] methodParameters = method.getParameterTypes(); + + for (int i = 0; i < params.length; i++) { + ManagedOperationParameter param = params[i]; + parameterInfo[i] = + new MBeanParameterInfo(param.getName(), methodParameters[i].getName(), param.getDescription()); + } + + return parameterInfo; + } + + /** + * Reads the {@link ManagedNotification} metadata from the {@code Class} of the managed resource + * and generates and returns the corresponding {@link javax.management.modelmbean.ModelMBeanNotificationInfo} metadata. + */ + @Override + protected ModelMBeanNotificationInfo[] getNotificationInfo(Object managedBean, String beanKey) { + Class intf = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); + ManagedNotification[] notificationAttributes = + this.attributeSource.getManagedNotifications(intf); + ModelMBeanNotificationInfo[] notificationInfos = + new ModelMBeanNotificationInfo[notificationAttributes.length]; + + for (int i = 0; i < notificationAttributes.length; i++) { + ManagedNotification attribute = notificationAttributes[i]; + notificationInfos[i] = JmxMetadataUtils.convertToModelMBeanNotificationInfo(attribute); + } + + return notificationInfos; + } + + /** + * Adds descriptor fields from the {@code ManagedResource} attribute + * to the MBean descriptor. Specifically, adds the {@code currencyTimeLimit}, + * {@code persistPolicy}, {@code persistPeriod}, {@code persistLocation} + * and {@code persistName} descriptor fields if they are present in the metadata. + */ + @Override + protected void populateMBeanDescriptor(Descriptor desc, Object managedBean, String beanKey) { + Class intf = findJmxInterface(beanKey, AopUtils.getTargetClass(managedBean)); + ManagedResource mr = this.attributeSource.getManagedResource(intf); + if (mr == null) { + applyDefaultCurrencyTimeLimit(desc); + return; + } + + applyCurrencyTimeLimit(desc, mr.getCurrencyTimeLimit()); + + if (mr.isLog()) { + desc.setField(FIELD_LOG, "true"); + } + if (StringUtils.hasLength(mr.getLogFile())) { + desc.setField(FIELD_LOG_FILE, mr.getLogFile()); + } + + if (StringUtils.hasLength(mr.getPersistPolicy())) { + desc.setField(FIELD_PERSIST_POLICY, mr.getPersistPolicy()); + } + if (mr.getPersistPeriod() >= 0) { + desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(mr.getPersistPeriod())); + } + if (StringUtils.hasLength(mr.getPersistName())) { + desc.setField(FIELD_PERSIST_NAME, mr.getPersistName()); + } + if (StringUtils.hasLength(mr.getPersistLocation())) { + desc.setField(FIELD_PERSIST_LOCATION, mr.getPersistLocation()); + } + } + + /** + * Adds descriptor fields from the {@code ManagedAttribute} attribute or the {@code ManagedMetric} attribute + * to the attribute descriptor. + */ + @Override + protected void populateAttributeDescriptor(Descriptor desc, Method getter, Method setter, String beanKey) { + Method resolvedGetter = findJmxMethod(getter, beanKey); + Method resolvedSetter = findJmxMethod(setter, beanKey); + ManagedMetric metricInfo = resolvedGetter != null ? attributeSource.getManagedMetric(resolvedGetter) : null; + if (getter != null && metricInfo != null) { + populateMetricDescriptor(desc, metricInfo); + } else { + ManagedAttribute gma = + (resolvedGetter == null) ? null : this.attributeSource.getManagedAttribute(resolvedGetter); + ManagedAttribute sma = + (resolvedSetter == null) ? null : this.attributeSource.getManagedAttribute(resolvedSetter); + if (gma == null) { + gma = ManagedAttribute.EMPTY; + } + if (sma == null) { + sma = ManagedAttribute.EMPTY; + } + populateAttributeDescriptor(desc, gma, sma); + } + } + + private void populateAttributeDescriptor(Descriptor desc, ManagedAttribute gma, ManagedAttribute sma) { + applyCurrencyTimeLimit(desc, resolveIntDescriptor(gma.getCurrencyTimeLimit(), sma.getCurrencyTimeLimit())); + + Object defaultValue = resolveObjectDescriptor(gma.getDefaultValue(), sma.getDefaultValue()); + desc.setField(FIELD_DEFAULT, defaultValue); + + String persistPolicy = resolveStringDescriptor(gma.getPersistPolicy(), sma.getPersistPolicy()); + if (StringUtils.hasLength(persistPolicy)) { + desc.setField(FIELD_PERSIST_POLICY, persistPolicy); + } + int persistPeriod = resolveIntDescriptor(gma.getPersistPeriod(), sma.getPersistPeriod()); + if (persistPeriod >= 0) { + desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(persistPeriod)); + } + } + + private void populateMetricDescriptor(Descriptor desc, ManagedMetric metric) { + applyCurrencyTimeLimit(desc, metric.getCurrencyTimeLimit()); + + if (StringUtils.hasLength(metric.getPersistPolicy())) { + desc.setField(FIELD_PERSIST_POLICY, metric.getPersistPolicy()); + } + if (metric.getPersistPeriod() >= 0) { + desc.setField(FIELD_PERSIST_PERIOD, Integer.toString(metric.getPersistPeriod())); + } + + if (StringUtils.hasLength(metric.getDisplayName())) { + desc.setField(FIELD_DISPLAY_NAME, metric.getDisplayName()); + } + + if (StringUtils.hasLength(metric.getUnit())) { + desc.setField(FIELD_UNITS, metric.getUnit()); + } + + if (StringUtils.hasLength(metric.getCategory())) { + desc.setField(FIELD_METRIC_CATEGORY, metric.getCategory()); + } + + String metricType = (metric.getMetricType() == null) ? MetricType.GAUGE.toString() : metric.getMetricType().toString(); + desc.setField(FIELD_METRIC_TYPE, metricType); + } + + /** + * Adds descriptor fields from the {@code ManagedAttribute} attribute + * to the attribute descriptor. Specifically, adds the {@code currencyTimeLimit} + * descriptor field if it is present in the metadata. + */ + @Override + protected void populateOperationDescriptor(Descriptor desc, Method method, String beanKey) { + Method resolvedOperation = findJmxMethod(method, beanKey); + ManagedOperation mo = this.attributeSource.getManagedOperation(resolvedOperation); + + if (resolvedOperation != null) { + applyRunAsync(desc, resolvedOperation); + } + + if (mo != null) { + applyCurrencyTimeLimit(desc, mo.getCurrencyTimeLimit()); + } + } + + /** + * Adds fields to the operation descriptor in case of operation should be executed asynchronously if + * operation was annotated by {@link JmxRunAsync}. + * + * @param desc operation descriptor + * @param operation operation + */ + protected void applyRunAsync(Descriptor desc, Method operation) { + JmxRunAsync jmxRunAsync = operation.getAnnotation(JmxRunAsync.class); + if (jmxRunAsync == null) { + return; + } + + desc.setField(FIELD_RUN_ASYNC, true); + desc.setField(FIELD_TIMEOUT, jmxRunAsync.timeout()); + } + + /** + * Determines which of two {@code int} values should be used as the value + * for an attribute descriptor. In general, only the getter or the setter will + * be have a non-negative value so we use that value. In the event that both values + * are non-negative, we use the greater of the two. This method can be used to + * resolve any {@code int} valued descriptor where there are two possible values. + * + * @param getter the int value associated with the getter for this attribute + * @param setter the int associated with the setter for this attribute + */ + private int resolveIntDescriptor(int getter, int setter) { + return (getter >= setter ? getter : setter); + } + + /** + * Locates the value of a descriptor based on values attached + * to both the getter and setter methods. If both have values + * supplied then the value attached to the getter is preferred. + * + * @param getter the Object value associated with the get method + * @param setter the Object value associated with the set method + * @return the appropriate Object to use as the value for the descriptor + */ + private Object resolveObjectDescriptor(Object getter, Object setter) { + return (getter != null ? getter : setter); + } + + /** + * Locates the value of a descriptor based on values attached + * to both the getter and setter methods. If both have values + * supplied then the value attached to the getter is preferred. + * The supplied default value is used to check to see if the value + * associated with the getter has changed from the default. + * + * @param getter the String value associated with the get method + * @param setter the String value associated with the set method + * @return the appropriate String to use as the value for the descriptor + */ + private String resolveStringDescriptor(String getter, String setter) { + return (StringUtils.hasLength(getter) ? getter : setter); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifier.java b/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifier.java index a25cdfe054..10f515496a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifier.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifier.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jmx; - -import com.haulmont.cuba.core.global.NodeIdentifier; - -import org.springframework.stereotype.Component; -import javax.inject.Inject; - -@Component("cuba_JmxNodeIdentifierMBean") -public class JmxNodeIdentifier implements JmxNodeIdentifierMBean { - - @Inject - private NodeIdentifier nodeIdentifier; - - @Override - public String getNodeName() { - return nodeIdentifier.getNodeName(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jmx; + +import com.haulmont.cuba.core.global.NodeIdentifier; + +import org.springframework.stereotype.Component; +import javax.inject.Inject; + +@Component("cuba_JmxNodeIdentifierMBean") +public class JmxNodeIdentifier implements JmxNodeIdentifierMBean { + + @Inject + private NodeIdentifier nodeIdentifier; + + @Override + public String getNodeName() { + return nodeIdentifier.getNodeName(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifierMBean.java b/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifierMBean.java index 28d73b6910..6e3657d71d 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifierMBean.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jmx/JmxNodeIdentifierMBean.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jmx; - -/** - * MBean that is used by JMX control facility to identify a JMX node. - * If this MBean is not present in a JVM, the node is considered as unknown. - */ -public interface JmxNodeIdentifierMBean { - - String getNodeName(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jmx; + +/** + * MBean that is used by JMX control facility to identify a JMX node. + * If this MBean is not present in a JVM, the node is considered as unknown. + */ +public interface JmxNodeIdentifierMBean { + + String getNodeName(); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jmx/MBeanExporter.java b/modules/global/src/com/haulmont/cuba/core/sys/jmx/MBeanExporter.java index bfaf5d915b..16e9c7237b 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jmx/MBeanExporter.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jmx/MBeanExporter.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jmx; - -import org.apache.commons.logging.LogFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jmx.support.MBeanRegistrationSupport; - -import javax.management.DynamicMBean; -import javax.management.JMException; -import java.lang.reflect.Field; -import java.util.Map; - -/** - * Tweaked MBean exporter. - *
- * Difference from spring one is that it does not try to expose bean as {@link javax.management.StandardMBean} - * if it complies to MyObject -> MyObjectMBean naming scheme. - *
- * Instead it uses {@link AnnotationMBeanInfoAssembler} to construct MBean descriptor for every bean. - */ -public class MBeanExporter extends org.springframework.jmx.export.MBeanExporter { - - private final Logger log = LoggerFactory.getLogger(MBeanExporter.class); - - public MBeanExporter() { - setAssembler(new AnnotationMBeanInfoAssembler()); - // hack logging - try { - Field loggerField = MBeanRegistrationSupport.class.getDeclaredField("logger"); - loggerField.setAccessible(true); - loggerField.set(this, LogFactory.getLog(org.springframework.jmx.export.MBeanExporter.class)); - } catch (NoSuchFieldException | IllegalAccessException ignore) { - } - } - - @Override - public void afterSingletonsInstantiated() { - // hack logging - Map beans = null; - try { - Field beansField = org.springframework.jmx.export.MBeanExporter.class.getDeclaredField("beans"); - beansField.setAccessible(true); - beans = (Map) beansField.get(this); - } catch (NoSuchFieldException | IllegalAccessException ignore) { - } - if (beans != null) { - log.info("Registering beans for JMX exposure: {}", beans.keySet()); - } - - super.afterSingletonsInstantiated(); - } - - @Override - protected boolean isMBean(Class beanClass) { - /* Never try to adapt to StandardMBean */ - return false; - } - - @Override - protected DynamicMBean adaptMBeanIfPossible(Object bean) throws JMException { - /* Never adapt */ - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jmx; + +import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jmx.support.MBeanRegistrationSupport; + +import javax.management.DynamicMBean; +import javax.management.JMException; +import java.lang.reflect.Field; +import java.util.Map; + +/** + * Tweaked MBean exporter. + *
+ * Difference from spring one is that it does not try to expose bean as {@link javax.management.StandardMBean} + * if it complies to MyObject -> MyObjectMBean naming scheme. + *
+ * Instead it uses {@link AnnotationMBeanInfoAssembler} to construct MBean descriptor for every bean. + */ +public class MBeanExporter extends org.springframework.jmx.export.MBeanExporter { + + private final Logger log = LoggerFactory.getLogger(MBeanExporter.class); + + public MBeanExporter() { + setAssembler(new AnnotationMBeanInfoAssembler()); + // hack logging + try { + Field loggerField = MBeanRegistrationSupport.class.getDeclaredField("logger"); + loggerField.setAccessible(true); + loggerField.set(this, LogFactory.getLog(org.springframework.jmx.export.MBeanExporter.class)); + } catch (NoSuchFieldException | IllegalAccessException ignore) { + } + } + + @Override + public void afterSingletonsInstantiated() { + // hack logging + Map beans = null; + try { + Field beansField = org.springframework.jmx.export.MBeanExporter.class.getDeclaredField("beans"); + beansField.setAccessible(true); + beans = (Map) beansField.get(this); + } catch (NoSuchFieldException | IllegalAccessException ignore) { + } + if (beans != null) { + log.info("Registering beans for JMX exposure: {}", beans.keySet()); + } + + super.afterSingletonsInstantiated(); + } + + @Override + protected boolean isMBean(Class beanClass) { + /* Never try to adapt to StandardMBean */ + return false; + } + + @Override + protected DynamicMBean adaptMBeanIfPossible(Object bean) throws JMException { + /* Never adapt */ + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/AntlrNoCaseStringStream.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/AntlrNoCaseStringStream.java index e1c0487491..2a1cf9d2b1 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/AntlrNoCaseStringStream.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/AntlrNoCaseStringStream.java @@ -1,43 +1,43 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import org.antlr.runtime.ANTLRStringStream; -import org.antlr.runtime.CharStream; - -public class AntlrNoCaseStringStream extends ANTLRStringStream { - public AntlrNoCaseStringStream(String str) { - super(str); - } - - @Override - public int LA(int i) { - if (i == 0) { - return 0; // undefined - } - if (i < 0) { - i++; // e.g., translate LA(-1) to use offset 0 - } - - if ((p + i - 1) >= n) { - - return CharStream.EOF; - } - return Character.toUpperCase(data[p + i - 1]); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; + +public class AntlrNoCaseStringStream extends ANTLRStringStream { + public AntlrNoCaseStringStream(String str) { + super(str); + } + + @Override + public int LA(int i) { + if (i == 0) { + return 0; // undefined + } + if (i < 0) { + i++; // e.g., translate LA(-1) to use offset 0 + } + + if ((p + i - 1) >= n) { + + return CharStream.EOF; + } + return Character.toUpperCase(data[p + i - 1]); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModel.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModel.java index a678deea93..0316519b64 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModel.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModel.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.global.ExtendedEntities; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; - -import javax.annotation.concurrent.NotThreadSafe; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@NotThreadSafe -public class DomainModel { - protected Map entities = new HashMap<>(); - protected ExtendedEntities extendedEntities; - - public DomainModel(ExtendedEntities extendedEntities, JpqlEntityModel... initialEntities) { - this(initialEntities); - this.extendedEntities = extendedEntities; - } - - public DomainModel(JpqlEntityModel... initialEntities) { - for (JpqlEntityModel initialEntity : initialEntities) { - add(initialEntity); - } - } - - public void add(JpqlEntityModel entity) { - if (entity == null) - throw new NullPointerException("No entity passed"); - - entities.put(entity.getName(), entity); - } - - public List findEntitiesStartingWith(String lastWord) { - List result = entities.values().stream() - .filter(entity -> entity.getName().startsWith(lastWord)) - .collect(Collectors.toList()); - return result; - } - - public JpqlEntityModel getEntityByName(String requiredEntityName) throws UnknownEntityNameException { - if (extendedEntities != null) { - MetaClass effectiveMetaClass = extendedEntities.getEffectiveMetaClass(requiredEntityName); - requiredEntityName = effectiveMetaClass.getName(); - } - - JpqlEntityModel entity = entities.get(requiredEntityName); - if (entity == null) { - throw new UnknownEntityNameException(requiredEntityName); - } else { - return entity; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.global.ExtendedEntities; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; + +import javax.annotation.concurrent.NotThreadSafe; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@NotThreadSafe +public class DomainModel { + protected Map entities = new HashMap<>(); + protected ExtendedEntities extendedEntities; + + public DomainModel(ExtendedEntities extendedEntities, JpqlEntityModel... initialEntities) { + this(initialEntities); + this.extendedEntities = extendedEntities; + } + + public DomainModel(JpqlEntityModel... initialEntities) { + for (JpqlEntityModel initialEntity : initialEntities) { + add(initialEntity); + } + } + + public void add(JpqlEntityModel entity) { + if (entity == null) + throw new NullPointerException("No entity passed"); + + entities.put(entity.getName(), entity); + } + + public List findEntitiesStartingWith(String lastWord) { + List result = entities.values().stream() + .filter(entity -> entity.getName().startsWith(lastWord)) + .collect(Collectors.toList()); + return result; + } + + public JpqlEntityModel getEntityByName(String requiredEntityName) throws UnknownEntityNameException { + if (extendedEntities != null) { + MetaClass effectiveMetaClass = extendedEntities.getEffectiveMetaClass(requiredEntityName); + requiredEntityName = effectiveMetaClass.getName(); + } + + JpqlEntityModel entity = entities.get(requiredEntityName); + if (entity == null) { + throw new UnknownEntityNameException(requiredEntityName); + } else { + return entity; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModelBuilder.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModelBuilder.java index 9eaf4176bd..7f22262fd2 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModelBuilder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/DomainModelBuilder.java @@ -1,110 +1,110 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.Range; -import com.haulmont.cuba.core.global.ExtendedEntities; -import com.haulmont.cuba.core.global.MessageTools; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collection; - -/** - * INTERNAL. - * Generates domain model for use in JPQL parser. - */ -@Component(DomainModelBuilder.NAME) -public class DomainModelBuilder { - - public static final String NAME = "cuba_DomainModelBuilder"; - - @Inject - protected Metadata metadata; - - @Inject - protected MetadataTools metadataTools; - - @Inject - protected MessageTools messageTools; - - @Inject - protected ExtendedEntities extendedEntities; - - protected boolean loadCaptions; - - public DomainModel produce() { - Collection classes = metadata.getSession().getClasses(); - DomainModel result = new DomainModel(extendedEntities); - - EntityBuilder builder = new EntityBuilder(); - for (MetaClass aClass : classes) { - builder.startNewEntity(aClass.getName()); - - Collection props = aClass.getProperties(); - for (MetaProperty prop : props) { - if (metadataTools.isPersistent(prop)) - addProperty(builder, aClass, prop); - } - - JpqlEntityModel entity = builder.produce(); - result.add(entity); - } - return result; - } - - private void addProperty(EntityBuilder builder, MetaClass metaClass, MetaProperty prop) { - String name = prop.getName(); - String userFriendlyName = null; - if (loadCaptions) { - userFriendlyName = messageTools.getPropertyCaption(metaClass, prop.getName()); - } - boolean isEmbedded = metadataTools.isEmbedded(prop); - MetaProperty.Type type = prop.getType(); - Class javaType = prop.getJavaType(); - Range range = prop.getRange(); - switch (type) { - case COMPOSITION: - case ASSOCIATION: - if (range.isClass()) { - MetaClass rangeClass = range.asClass(); - if (range.getCardinality().isMany()) { - builder.addCollectionReferenceAttribute(name, rangeClass.getName(), userFriendlyName); - } else { - builder.addReferenceAttribute(name, rangeClass.getName(), userFriendlyName, isEmbedded); - } - } else { - builder.addSingleValueAttribute(javaType, name, userFriendlyName); - } - break; - case ENUM: - //todo - builder.addSingleValueAttribute(javaType, name, userFriendlyName); - break; - case DATATYPE: - builder.addSingleValueAttribute(javaType, name, userFriendlyName); - break; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.Range; +import com.haulmont.cuba.core.global.ExtendedEntities; +import com.haulmont.cuba.core.global.MessageTools; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Collection; + +/** + * INTERNAL. + * Generates domain model for use in JPQL parser. + */ +@Component(DomainModelBuilder.NAME) +public class DomainModelBuilder { + + public static final String NAME = "cuba_DomainModelBuilder"; + + @Inject + protected Metadata metadata; + + @Inject + protected MetadataTools metadataTools; + + @Inject + protected MessageTools messageTools; + + @Inject + protected ExtendedEntities extendedEntities; + + protected boolean loadCaptions; + + public DomainModel produce() { + Collection classes = metadata.getSession().getClasses(); + DomainModel result = new DomainModel(extendedEntities); + + EntityBuilder builder = new EntityBuilder(); + for (MetaClass aClass : classes) { + builder.startNewEntity(aClass.getName()); + + Collection props = aClass.getProperties(); + for (MetaProperty prop : props) { + if (metadataTools.isPersistent(prop)) + addProperty(builder, aClass, prop); + } + + JpqlEntityModel entity = builder.produce(); + result.add(entity); + } + return result; + } + + private void addProperty(EntityBuilder builder, MetaClass metaClass, MetaProperty prop) { + String name = prop.getName(); + String userFriendlyName = null; + if (loadCaptions) { + userFriendlyName = messageTools.getPropertyCaption(metaClass, prop.getName()); + } + boolean isEmbedded = metadataTools.isEmbedded(prop); + MetaProperty.Type type = prop.getType(); + Class javaType = prop.getJavaType(); + Range range = prop.getRange(); + switch (type) { + case COMPOSITION: + case ASSOCIATION: + if (range.isClass()) { + MetaClass rangeClass = range.asClass(); + if (range.getCardinality().isMany()) { + builder.addCollectionReferenceAttribute(name, rangeClass.getName(), userFriendlyName); + } else { + builder.addReferenceAttribute(name, rangeClass.getName(), userFriendlyName, isEmbedded); + } + } else { + builder.addSingleValueAttribute(javaType, name, userFriendlyName); + } + break; + case ENUM: + //todo + builder.addSingleValueAttribute(javaType, name, userFriendlyName); + break; + case DATATYPE: + builder.addSingleValueAttribute(javaType, name, userFriendlyName); + break; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/EntityPath.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/EntityPath.java index bbb812c6c4..ebdf0ba704 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/EntityPath.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/EntityPath.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; -import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; - -import java.util.ArrayList; -import java.util.List; - -public class EntityPath { - public String topEntityVariableName; - public String[] traversedFields; - public String lastEntityFieldPattern; - - public Pointer resolvePointer(DomainModel model, QueryVariableContext queryVC) { - Pointer pointer = EntityPointer.create(queryVC, topEntityVariableName); - for (String traversedField : traversedFields) { - pointer = pointer.next(model, traversedField); - } - return pointer; - } - - public List resolveTransitionalPointers(DomainModel model, QueryVariableContext queryVC) { - List pointers = new ArrayList<>(); - Pointer pointer = EntityPointer.create(queryVC, topEntityVariableName); - pointers.add(pointer); - for (String traversedField : traversedFields) { - pointer = pointer.next(model, traversedField); - pointers.add(pointer); - } - return pointers; - } - - public static EntityPath parseEntityPath(String lastWord) { - String[] parts = lastWord.split("\\."); - EntityPath result = new EntityPath(); - if (parts.length > 0) { - result.topEntityVariableName = parts[0]; - int consumedPartsCount = 1; - if (lastWord.endsWith(".") || parts.length == 1) { - result.lastEntityFieldPattern = ""; - } else { - result.lastEntityFieldPattern = parts[parts.length - 1]; - consumedPartsCount = 2; - } - if (parts.length == 1) { - result.traversedFields = new String[0]; - } else { - result.traversedFields = new String[parts.length - consumedPartsCount]; - System.arraycopy(parts, 1, result.traversedFields, 0, parts.length - consumedPartsCount); - } - } else { - result.traversedFields = new String[0]; - } - return result; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; +import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; + +import java.util.ArrayList; +import java.util.List; + +public class EntityPath { + public String topEntityVariableName; + public String[] traversedFields; + public String lastEntityFieldPattern; + + public Pointer resolvePointer(DomainModel model, QueryVariableContext queryVC) { + Pointer pointer = EntityPointer.create(queryVC, topEntityVariableName); + for (String traversedField : traversedFields) { + pointer = pointer.next(model, traversedField); + } + return pointer; + } + + public List resolveTransitionalPointers(DomainModel model, QueryVariableContext queryVC) { + List pointers = new ArrayList<>(); + Pointer pointer = EntityPointer.create(queryVC, topEntityVariableName); + pointers.add(pointer); + for (String traversedField : traversedFields) { + pointer = pointer.next(model, traversedField); + pointers.add(pointer); + } + return pointers; + } + + public static EntityPath parseEntityPath(String lastWord) { + String[] parts = lastWord.split("\\."); + EntityPath result = new EntityPath(); + if (parts.length > 0) { + result.topEntityVariableName = parts[0]; + int consumedPartsCount = 1; + if (lastWord.endsWith(".") || parts.length == 1) { + result.lastEntityFieldPattern = ""; + } else { + result.lastEntityFieldPattern = parts[parts.length - 1]; + consumedPartsCount = 2; + } + if (parts.length == 1) { + result.traversedFields = new String[0]; + } else { + result.traversedFields = new String[parts.length - consumedPartsCount]; + System.arraycopy(parts, 1, result.traversedFields, 0, parts.length - consumedPartsCount); + } + } else { + result.traversedFields = new String[0]; + } + return result; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorNodesFinder.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorNodesFinder.java index ef452acc1e..d5f789ca54 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorNodesFinder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorNodesFinder.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.TreeVisitorAction; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class ErrorNodesFinder implements TreeVisitorAction { - protected List errorNodes = new ArrayList<>(); - - @Override - public Object pre(Object t) { - if (t instanceof CommonErrorNode) { - errorNodes.add((CommonErrorNode) t); - return t; - } - return t; - } - - @Override - public Object post(Object t) { - return t; - } - - public List getErrorNodes() { - return Collections.unmodifiableList(errorNodes); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.TreeVisitorAction; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ErrorNodesFinder implements TreeVisitorAction { + protected List errorNodes = new ArrayList<>(); + + @Override + public Object pre(Object t) { + if (t instanceof CommonErrorNode) { + errorNodes.add((CommonErrorNode) t); + return t; + } + return t; + } + + @Override + public Object post(Object t) { + return t; + } + + public List getErrorNodes() { + return Collections.unmodifiableList(errorNodes); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorRec.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorRec.java index ae1e7afd28..126bc548a0 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorRec.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/ErrorRec.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import org.antlr.runtime.tree.CommonTree; - -public class ErrorRec { - public final CommonTree node; - public final String message; - - public ErrorRec(CommonTree node, String message) { - this.node = node; - this.message = message; - } - - @Override - public String toString() { - return message + " [" + node.toString() + "]"; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import org.antlr.runtime.tree.CommonTree; + +public class ErrorRec { + public final CommonTree node; + public final String message; + + public ErrorRec(CommonTree node, String message) { + this.node = node; + this.message = message; + } + + @Override + public String toString() { + return message + " [" + node.toString() + "]"; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/IdVarSelector.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/IdVarSelector.java index 079288d1f4..4a6297c071 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/IdVarSelector.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/IdVarSelector.java @@ -1,108 +1,108 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.tree.BaseJoinNode; -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; -import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.TreeVisitorAction; - -import java.util.*; - -public class IdVarSelector implements TreeVisitorAction { - private QueryVariableContext root; - - private List invalidIdVarNodes = new ArrayList<>(); - private DomainModel model; - private Deque stack = new ArrayDeque<>(); - - public IdVarSelector(DomainModel model) { - this.model = model; - } - - public QueryVariableContext getContextTree() { - return root; - } - - @Override - public Object pre(Object t) { - if (!(t instanceof CommonTree)) - return t; - - CommonTree node = (CommonTree) t; - - if (node instanceof QueryNode) { - QueryVariableContext newCurrent = new QueryVariableContext(model, (QueryNode) node); - if (root == null) { - root = newCurrent; - } - QueryVariableContext last = stack.peekLast(); - if (last != null) { - last.addChild(newCurrent); - } - stack.addLast(newCurrent); - } - return t; - } - - @Override - public Object post(Object t) { - if (!(t instanceof CommonTree)) - return t; - - if (t instanceof CommonErrorNode) { - return t; - } - - CommonTree node = (CommonTree) t; - - if (node.token == null) - return t; - - - if ((node instanceof QueryNode) && isInWhereSubquery(node)) { - stack.peekLast().setPropagateVariablesUp(false); - return t; - } - - if (node instanceof IdentificationVariableNode) { - IdentificationVariableNode vnode = (IdentificationVariableNode) node; - vnode.identifyVariableEntity(model, stack, invalidIdVarNodes); - return t; - } - - if (node instanceof BaseJoinNode) { - BaseJoinNode vnode = (BaseJoinNode) node; - vnode.identifyVariableEntity(model, stack, invalidIdVarNodes); - return t; - } - - return t; - } - - private boolean isInWhereSubquery(CommonTree node) { - return node.getParent() != null && node.getParent() instanceof SimpleConditionNode; - } - - public List getInvalidIdVarNodes() { - return Collections.unmodifiableList(invalidIdVarNodes); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.tree.BaseJoinNode; +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; +import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeVisitorAction; + +import java.util.*; + +public class IdVarSelector implements TreeVisitorAction { + private QueryVariableContext root; + + private List invalidIdVarNodes = new ArrayList<>(); + private DomainModel model; + private Deque stack = new ArrayDeque<>(); + + public IdVarSelector(DomainModel model) { + this.model = model; + } + + public QueryVariableContext getContextTree() { + return root; + } + + @Override + public Object pre(Object t) { + if (!(t instanceof CommonTree)) + return t; + + CommonTree node = (CommonTree) t; + + if (node instanceof QueryNode) { + QueryVariableContext newCurrent = new QueryVariableContext(model, (QueryNode) node); + if (root == null) { + root = newCurrent; + } + QueryVariableContext last = stack.peekLast(); + if (last != null) { + last.addChild(newCurrent); + } + stack.addLast(newCurrent); + } + return t; + } + + @Override + public Object post(Object t) { + if (!(t instanceof CommonTree)) + return t; + + if (t instanceof CommonErrorNode) { + return t; + } + + CommonTree node = (CommonTree) t; + + if (node.token == null) + return t; + + + if ((node instanceof QueryNode) && isInWhereSubquery(node)) { + stack.peekLast().setPropagateVariablesUp(false); + return t; + } + + if (node instanceof IdentificationVariableNode) { + IdentificationVariableNode vnode = (IdentificationVariableNode) node; + vnode.identifyVariableEntity(model, stack, invalidIdVarNodes); + return t; + } + + if (node instanceof BaseJoinNode) { + BaseJoinNode vnode = (BaseJoinNode) node; + vnode.identifyVariableEntity(model, stack, invalidIdVarNodes); + return t; + } + + return t; + } + + private boolean isInWhereSubquery(CommonTree node) { + return node.getParent() != null && node.getParent() instanceof SimpleConditionNode; + } + + public List getInvalidIdVarNodes() { + return Collections.unmodifiableList(invalidIdVarNodes); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/InferredType.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/InferredType.java index e6799922a6..1007bf9f5f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/InferredType.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/InferredType.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.model.Attribute; - -public enum InferredType { - Collection { - @Override - public boolean matches(Attribute attribute) { - return attribute.isCollection() && attribute.isEntityReferenceAttribute(); - } - }, - Entity { - @Override - public boolean matches(Attribute attribute) { - return !attribute.isCollection() && attribute.isEntityReferenceAttribute(); - } - }, - Date { - @Override - public boolean matches(Attribute attribute) { - return java.util.Date.class.isAssignableFrom(attribute.getSimpleType()); - } - }, - Any { - @Override - public boolean matches(Attribute attribute) { - return true; - } - }; - - public abstract boolean matches(Attribute attribute); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.model.Attribute; + +public enum InferredType { + Collection { + @Override + public boolean matches(Attribute attribute) { + return attribute.isCollection() && attribute.isEntityReferenceAttribute(); + } + }, + Entity { + @Override + public boolean matches(Attribute attribute) { + return !attribute.isCollection() && attribute.isEntityReferenceAttribute(); + } + }, + Date { + @Override + public boolean matches(Attribute attribute) { + return java.util.Date.class.isAssignableFrom(attribute.getSimpleType()); + } + }, + Any { + @Override + public boolean matches(Attribute attribute) { + return true; + } + }; + + public abstract boolean matches(Attribute attribute); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/Parser.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/Parser.java index 90a0ab6b85..590717c847 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/Parser.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/Parser.java @@ -1,107 +1,107 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Parser; -import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; -import org.antlr.runtime.CharStream; -import org.antlr.runtime.CommonTokenStream; -import org.antlr.runtime.RecognitionException; -import org.antlr.runtime.TokenStream; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.TreeVisitor; -import org.apache.commons.lang.StringUtils; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class Parser { - public static CommonTree parse(String input, boolean failOnErrors) throws RecognitionException { - JPA2Parser parser = createParser(input); - JPA2Parser.ql_statement_return aReturn = parser.ql_statement(); - CommonTree tree = (CommonTree) aReturn.getTree(); - if (failOnErrors) { - checkTreeForExceptions(input, tree); - } - return tree; - } - - public static CommonTree parseWhereClause(String input) throws RecognitionException { - JPA2Parser parser = createParser(input); - JPA2Parser.where_clause_return aReturn = parser.where_clause(); - CommonTree tree = (CommonTree) aReturn.getTree(); - checkTreeForExceptions(input, tree); - return tree; - } - - public static List parseJoinClause(String join) throws RecognitionException { - JPA2Parser parser = createParser(join); - JPA2Parser.join_section_return aReturn = parser.join_section(); - CommonTree tree = (CommonTree) aReturn.getTree(); - if (tree == null) { - parser = createParser("join " + join); - aReturn = parser.join_section(); - tree = (CommonTree) aReturn.getTree(); - } - if (tree instanceof JoinVariableNode) { - checkTreeForExceptions(join, tree); - return Collections.singletonList((JoinVariableNode) tree); - } else { - List joins = tree.getChildren().stream() - .filter(node -> node instanceof JoinVariableNode) - .map(JoinVariableNode.class::cast) - .collect(Collectors.toList()); - checkTreeForExceptions(join, tree); - return joins; - } - } - - public static CommonTree parseSelectionSource(String input) throws RecognitionException { - JPA2Parser parser = createParser(input); - JPA2Parser.identification_variable_declaration_or_collection_member_declaration_return aReturn = - parser.identification_variable_declaration_or_collection_member_declaration(); - CommonTree tree = (CommonTree) aReturn.getTree(); - checkTreeForExceptions(input, tree); - return tree; - } - - private static JPA2Parser createParser(String input) { - if (input.contains("~")) - throw new IllegalArgumentException("Input string cannot contain \"~\""); - - CharStream cs = new AntlrNoCaseStringStream(input); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - return new JPA2Parser(tstream); - } - - private static void checkTreeForExceptions(String input, CommonTree tree) { - TreeVisitor visitor = new TreeVisitor(); - ErrorNodesFinder errorNodesFinder = new ErrorNodesFinder(); - visitor.visit(tree, errorNodesFinder); - - List errors = errorNodesFinder.getErrorNodes().stream() - .map(node -> new ErrorRec(node, "CommonErrorNode")) - .collect(Collectors.toList()); - - if (!errors.isEmpty()) { - throw new JpqlSyntaxException(String.format("Errors found for input jpql:[%s]", StringUtils.strip(input)), errors); - } - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Parser; +import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.TokenStream; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeVisitor; +import org.apache.commons.lang.StringUtils; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class Parser { + public static CommonTree parse(String input, boolean failOnErrors) throws RecognitionException { + JPA2Parser parser = createParser(input); + JPA2Parser.ql_statement_return aReturn = parser.ql_statement(); + CommonTree tree = (CommonTree) aReturn.getTree(); + if (failOnErrors) { + checkTreeForExceptions(input, tree); + } + return tree; + } + + public static CommonTree parseWhereClause(String input) throws RecognitionException { + JPA2Parser parser = createParser(input); + JPA2Parser.where_clause_return aReturn = parser.where_clause(); + CommonTree tree = (CommonTree) aReturn.getTree(); + checkTreeForExceptions(input, tree); + return tree; + } + + public static List parseJoinClause(String join) throws RecognitionException { + JPA2Parser parser = createParser(join); + JPA2Parser.join_section_return aReturn = parser.join_section(); + CommonTree tree = (CommonTree) aReturn.getTree(); + if (tree == null) { + parser = createParser("join " + join); + aReturn = parser.join_section(); + tree = (CommonTree) aReturn.getTree(); + } + if (tree instanceof JoinVariableNode) { + checkTreeForExceptions(join, tree); + return Collections.singletonList((JoinVariableNode) tree); + } else { + List joins = tree.getChildren().stream() + .filter(node -> node instanceof JoinVariableNode) + .map(JoinVariableNode.class::cast) + .collect(Collectors.toList()); + checkTreeForExceptions(join, tree); + return joins; + } + } + + public static CommonTree parseSelectionSource(String input) throws RecognitionException { + JPA2Parser parser = createParser(input); + JPA2Parser.identification_variable_declaration_or_collection_member_declaration_return aReturn = + parser.identification_variable_declaration_or_collection_member_declaration(); + CommonTree tree = (CommonTree) aReturn.getTree(); + checkTreeForExceptions(input, tree); + return tree; + } + + private static JPA2Parser createParser(String input) { + if (input.contains("~")) + throw new IllegalArgumentException("Input string cannot contain \"~\""); + + CharStream cs = new AntlrNoCaseStringStream(input); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + return new JPA2Parser(tstream); + } + + private static void checkTreeForExceptions(String input, CommonTree tree) { + TreeVisitor visitor = new TreeVisitor(); + ErrorNodesFinder errorNodesFinder = new ErrorNodesFinder(); + visitor.visit(tree, errorNodesFinder); + + List errors = errorNodesFinder.getErrorNodes().stream() + .map(node -> new ErrorRec(node, "CommonErrorNode")) + .collect(Collectors.toList()); + + if (!errors.isEmpty()) { + throw new JpqlSyntaxException(String.format("Errors found for input jpql:[%s]", StringUtils.strip(input)), errors); + } + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryBuilder.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryBuilder.java index ba794a6ba7..ae6ace5aca 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryBuilder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryBuilder.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -public class QueryBuilder { - private StringBuilder sb = new StringBuilder(); - - public void appendSpace() { - if (sb.length() != 0 && sb.charAt(sb.length() - 1) != ' ') - sb.append(' '); - } - - public void appendChar(char c) { - if (sb.length() != 0 && getLast() == ' ' && (c == ' ' || c == ')' || c == ',')) { - deleteLast(); - } - sb.append(c); - } - - public void appendString(String s) { - if (s != null) { - if (sb.length() != 0 && getLast() == ' ' && (s.charAt(0) == ' ' || s.charAt(0) == ')' || s.charAt(0) == ',')) { - deleteLast(); - } - sb.append(s); - } - } - - public char getLast() { - return sb.charAt(sb.length() - 1); - } - - public void deleteLast() { - sb.deleteCharAt(sb.length() - 1); - } - - @Override - public String toString() { - return sb.toString(); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +public class QueryBuilder { + private StringBuilder sb = new StringBuilder(); + + public void appendSpace() { + if (sb.length() != 0 && sb.charAt(sb.length() - 1) != ' ') + sb.append(' '); + } + + public void appendChar(char c) { + if (sb.length() != 0 && getLast() == ' ' && (c == ' ' || c == ')' || c == ',')) { + deleteLast(); + } + sb.append(c); + } + + public void appendString(String s) { + if (s != null) { + if (sb.length() != 0 && getLast() == ' ' && (s.charAt(0) == ' ' || s.charAt(0) == ')' || s.charAt(0) == ',')) { + deleteLast(); + } + sb.append(s); + } + } + + public char getLast() { + return sb.charAt(sb.length() - 1); + } + + public void deleteLast() { + sb.deleteCharAt(sb.length() - 1); + } + + @Override + public String toString() { + return sb.toString(); + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryTreeAnalyzer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryTreeAnalyzer.java index eb4a8ca894..c9b80089c2 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryTreeAnalyzer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryTreeAnalyzer.java @@ -1,228 +1,228 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.google.common.base.Preconditions; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; -import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; -import com.haulmont.cuba.core.sys.jpql.transform.NodesFinder; -import com.haulmont.cuba.core.sys.jpql.tree.*; -import org.antlr.runtime.RecognitionException; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; -import org.antlr.runtime.tree.TreeVisitor; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class QueryTreeAnalyzer { - protected DomainModel model; - protected IdVarSelector idVarSelector; - protected CommonTree tree; - - public void prepare(DomainModel model, String query) throws RecognitionException { - prepare(model, query, true); - } - - public void prepare(DomainModel model, String query, boolean failOnErrors) throws RecognitionException { - Preconditions.checkNotNull(query, "query is null"); - this.model = model; - query = query.replace("\n", " "); - query = query.replace("\r", " "); - query = query.replace("\t", " "); - tree = Parser.parse(query, failOnErrors); - TreeVisitor visitor = new TreeVisitor(); - idVarSelector = new IdVarSelector(model); - visitor.visit(tree, idVarSelector); - } - - public QueryVariableContext getRootQueryVariableContext() { - return idVarSelector.getContextTree(); - } - - public List getInvalidIdVarNodes() { - return idVarSelector.getInvalidIdVarNodes(); - } - - public CommonTree getTree() { - return tree; - } - - public String getRootEntityVariableName(String entityName) { - QueryVariableContext ctx = getRootQueryVariableContext(); - return ctx.getVariableNameByEntity(entityName); - } - - public PathNode getSelectedPathNode() { - Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); - boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); - SelectedItemNode selectedItemNode; - if (isDistinct) { - if (selectedItems.getChildCount() != 2) - throw new IllegalStateException("Cannot select path node if multiple fields selected"); - selectedItemNode = (SelectedItemNode) selectedItems.getChild(1); - } else { - if (selectedItems.getChildCount() != 1) - throw new IllegalStateException("Cannot select path node if multiple fields selected"); - selectedItemNode = (SelectedItemNode) selectedItems.getChild(0); - } - - if (!(selectedItemNode.getChild(0) instanceof PathNode)) { - throw new IllegalStateException("An entity path is assumed to be selected"); - } - return (PathNode) selectedItemNode.getChild(0); - } - - public JpqlEntityModel getSelectedEntity(PathNode path) { - Pointer pointer = path.resolvePointer(model, getRootQueryVariableContext()); - if (!(pointer instanceof EntityPointer)) { - throw new IllegalStateException("A path resulting in an entity is assumed to be selected"); - } - return ((EntityPointer) pointer).getEntity(); - } - - @Nullable - public IdentificationVariableNode getMainEntityIdentification() { - List identificationVariables = getIdentificationVariableNodes(); - - String returnedVariableName = getFirstReturnedVariableName(); - if (returnedVariableName != null) { - for (IdentificationVariableNode identificationVariable : identificationVariables) { - if (identificationVariable.getVariableName().equalsIgnoreCase(returnedVariableName)) { - return identificationVariable; - } - } - } - - return identificationVariables.size() > 0 ? identificationVariables.get(0) : null; - } - - @Nullable - public String getFirstReturnedVariableName() { - PathNode returnedPathNode = getFirstReturnedPathNode(); - if (returnedPathNode != null) { - return returnedPathNode.getEntityVariableName(); - } - - return null; - } - - @Nullable - public PathNode getFirstReturnedPathNode() { - List pathNodes = getReturnedPathNodes(); - if (CollectionUtils.isNotEmpty(pathNodes)) { - PathNode pathNode = pathNodes.get(0); - return pathNode; - } - - return null; - } - - @Nullable - public List getReturnedPathNodes() { - CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); - if (selectedItems == null) { - return null; - } - - return getChildrenByClass(selectedItems, SelectedItemNode.class).stream() - .flatMap(selectedItemNode -> getChildrenByClass(selectedItemNode, PathNode.class).stream()) - .collect(Collectors.toList()); - } - - public List getIdentificationVariableNodes() { - CommonTree sourceNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - List identificationVariableNodes = new ArrayList<>(); - - List selectionSources = getChildrenByClass(sourceNode, SelectionSourceNode.class); - for (SelectionSourceNode selectionSource : selectionSources) { - identificationVariableNodes.addAll(getChildrenByClass(selectionSource, IdentificationVariableNode.class)); - } - - return identificationVariableNodes; - } - - public List findAllConditionsForMainEntityAttribute(String attribute) { - IdentificationVariableNode mainEntityIdentification = getMainEntityIdentification(); - if (mainEntityIdentification != null) { - return findAllConditions().stream().filter(condition -> { - List childrenByClass = getChildrenByClass(condition, PathNode.class); - return childrenByClass.stream().anyMatch(pathNode -> { - String pathNodeAttribute = StringUtils.join(pathNode.getChildren(), "."); - return pathNode.getEntityVariableName().equals(mainEntityIdentification.getVariableName()) - && attribute.equals(pathNodeAttribute); - } - ); - }).collect(Collectors.toList()); - } else { - return Collections.emptyList(); - } - } - - public List findConditionsForParameter(String paramName) { - CommonTree whereTree = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_CONDITION); - List conditionNodes = getChildrenByClass(whereTree, SimpleConditionNode.class); - return conditionNodes.stream() - .filter((SimpleConditionNode n) -> { - ParameterNode parameter = (ParameterNode) n.getFirstChildWithType(JPA2Lexer.T_PARAMETER); - return parameter != null && (parameter.getChild(0).getText().contains(paramName) || - parameter.getChildCount() > 1 && paramName.equals(parameter.getChild(1).getText())); - }).collect(Collectors.toList()); - } - - public List findAllConditions() { - NodesFinder nodesFinder = new NodesFinder<>(SimpleConditionNode.class); - TreeVisitor treeVisitor = new TreeVisitor(); - treeVisitor.visit(tree, nodesFinder); - return nodesFinder.getFoundNodes(); - } - - public boolean hasJoins() { - CommonTree sourceNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - List selectionSourceNodes = getChildrenByClass(sourceNode, SelectionSourceNode.class); - if (selectionSourceNodes.size() > 1) { - return true; - } else if (selectionSourceNodes.size() == 1) { - NodesFinder nodesFinder = new NodesFinder<>(JoinVariableNode.class); - TreeVisitor treeVisitor = new TreeVisitor(); - treeVisitor.visit(tree, nodesFinder); - return !nodesFinder.getFoundNodes().isEmpty(); - } else { - return false; - } - } - - - protected List getChildrenByClass(CommonTree commonTree, Class clazz) { - List childrenByClass = new ArrayList<>(); - for (Object o : commonTree.getChildren()) { - if (clazz.isAssignableFrom(o.getClass())) { - childrenByClass.add(o); - } - } - - return (List) childrenByClass; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.google.common.base.Preconditions; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; +import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; +import com.haulmont.cuba.core.sys.jpql.transform.NodesFinder; +import com.haulmont.cuba.core.sys.jpql.tree.*; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; +import org.antlr.runtime.tree.TreeVisitor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class QueryTreeAnalyzer { + protected DomainModel model; + protected IdVarSelector idVarSelector; + protected CommonTree tree; + + public void prepare(DomainModel model, String query) throws RecognitionException { + prepare(model, query, true); + } + + public void prepare(DomainModel model, String query, boolean failOnErrors) throws RecognitionException { + Preconditions.checkNotNull(query, "query is null"); + this.model = model; + query = query.replace("\n", " "); + query = query.replace("\r", " "); + query = query.replace("\t", " "); + tree = Parser.parse(query, failOnErrors); + TreeVisitor visitor = new TreeVisitor(); + idVarSelector = new IdVarSelector(model); + visitor.visit(tree, idVarSelector); + } + + public QueryVariableContext getRootQueryVariableContext() { + return idVarSelector.getContextTree(); + } + + public List getInvalidIdVarNodes() { + return idVarSelector.getInvalidIdVarNodes(); + } + + public CommonTree getTree() { + return tree; + } + + public String getRootEntityVariableName(String entityName) { + QueryVariableContext ctx = getRootQueryVariableContext(); + return ctx.getVariableNameByEntity(entityName); + } + + public PathNode getSelectedPathNode() { + Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); + boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); + SelectedItemNode selectedItemNode; + if (isDistinct) { + if (selectedItems.getChildCount() != 2) + throw new IllegalStateException("Cannot select path node if multiple fields selected"); + selectedItemNode = (SelectedItemNode) selectedItems.getChild(1); + } else { + if (selectedItems.getChildCount() != 1) + throw new IllegalStateException("Cannot select path node if multiple fields selected"); + selectedItemNode = (SelectedItemNode) selectedItems.getChild(0); + } + + if (!(selectedItemNode.getChild(0) instanceof PathNode)) { + throw new IllegalStateException("An entity path is assumed to be selected"); + } + return (PathNode) selectedItemNode.getChild(0); + } + + public JpqlEntityModel getSelectedEntity(PathNode path) { + Pointer pointer = path.resolvePointer(model, getRootQueryVariableContext()); + if (!(pointer instanceof EntityPointer)) { + throw new IllegalStateException("A path resulting in an entity is assumed to be selected"); + } + return ((EntityPointer) pointer).getEntity(); + } + + @Nullable + public IdentificationVariableNode getMainEntityIdentification() { + List identificationVariables = getIdentificationVariableNodes(); + + String returnedVariableName = getFirstReturnedVariableName(); + if (returnedVariableName != null) { + for (IdentificationVariableNode identificationVariable : identificationVariables) { + if (identificationVariable.getVariableName().equalsIgnoreCase(returnedVariableName)) { + return identificationVariable; + } + } + } + + return identificationVariables.size() > 0 ? identificationVariables.get(0) : null; + } + + @Nullable + public String getFirstReturnedVariableName() { + PathNode returnedPathNode = getFirstReturnedPathNode(); + if (returnedPathNode != null) { + return returnedPathNode.getEntityVariableName(); + } + + return null; + } + + @Nullable + public PathNode getFirstReturnedPathNode() { + List pathNodes = getReturnedPathNodes(); + if (CollectionUtils.isNotEmpty(pathNodes)) { + PathNode pathNode = pathNodes.get(0); + return pathNode; + } + + return null; + } + + @Nullable + public List getReturnedPathNodes() { + CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); + if (selectedItems == null) { + return null; + } + + return getChildrenByClass(selectedItems, SelectedItemNode.class).stream() + .flatMap(selectedItemNode -> getChildrenByClass(selectedItemNode, PathNode.class).stream()) + .collect(Collectors.toList()); + } + + public List getIdentificationVariableNodes() { + CommonTree sourceNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + List identificationVariableNodes = new ArrayList<>(); + + List selectionSources = getChildrenByClass(sourceNode, SelectionSourceNode.class); + for (SelectionSourceNode selectionSource : selectionSources) { + identificationVariableNodes.addAll(getChildrenByClass(selectionSource, IdentificationVariableNode.class)); + } + + return identificationVariableNodes; + } + + public List findAllConditionsForMainEntityAttribute(String attribute) { + IdentificationVariableNode mainEntityIdentification = getMainEntityIdentification(); + if (mainEntityIdentification != null) { + return findAllConditions().stream().filter(condition -> { + List childrenByClass = getChildrenByClass(condition, PathNode.class); + return childrenByClass.stream().anyMatch(pathNode -> { + String pathNodeAttribute = StringUtils.join(pathNode.getChildren(), "."); + return pathNode.getEntityVariableName().equals(mainEntityIdentification.getVariableName()) + && attribute.equals(pathNodeAttribute); + } + ); + }).collect(Collectors.toList()); + } else { + return Collections.emptyList(); + } + } + + public List findConditionsForParameter(String paramName) { + CommonTree whereTree = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_CONDITION); + List conditionNodes = getChildrenByClass(whereTree, SimpleConditionNode.class); + return conditionNodes.stream() + .filter((SimpleConditionNode n) -> { + ParameterNode parameter = (ParameterNode) n.getFirstChildWithType(JPA2Lexer.T_PARAMETER); + return parameter != null && (parameter.getChild(0).getText().contains(paramName) || + parameter.getChildCount() > 1 && paramName.equals(parameter.getChild(1).getText())); + }).collect(Collectors.toList()); + } + + public List findAllConditions() { + NodesFinder nodesFinder = new NodesFinder<>(SimpleConditionNode.class); + TreeVisitor treeVisitor = new TreeVisitor(); + treeVisitor.visit(tree, nodesFinder); + return nodesFinder.getFoundNodes(); + } + + public boolean hasJoins() { + CommonTree sourceNode = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + List selectionSourceNodes = getChildrenByClass(sourceNode, SelectionSourceNode.class); + if (selectionSourceNodes.size() > 1) { + return true; + } else if (selectionSourceNodes.size() == 1) { + NodesFinder nodesFinder = new NodesFinder<>(JoinVariableNode.class); + TreeVisitor treeVisitor = new TreeVisitor(); + treeVisitor.visit(tree, nodesFinder); + return !nodesFinder.getFoundNodes().isEmpty(); + } else { + return false; + } + } + + + protected List getChildrenByClass(CommonTree commonTree, Class clazz) { + List childrenByClass = new ArrayList<>(); + for (Object o : commonTree.getChildren()) { + if (clazz.isAssignableFrom(o.getClass())) { + childrenByClass.add(o); + } + } + + return (List) childrenByClass; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryVariableContext.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryVariableContext.java index e163cd9c78..182584dfce 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryVariableContext.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/QueryVariableContext.java @@ -1,151 +1,151 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.model.VirtualJpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class QueryVariableContext { - private Map entityVariableName2entity = new HashMap<>(); - private QueryNode node; - private List children = new ArrayList<>(); - private JpqlEntityModel entity; - private boolean propagateVariablesUpstairs = true; - private QueryVariableContext parent = null; - - public QueryVariableContext(DomainModel model, QueryNode node) { - Preconditions.checkNotNullArgument(model); - Preconditions.checkNotNullArgument(node); - - this.node = node; - this.entity = new VirtualJpqlEntityModel(); - } - - public boolean isPropagateVariablesUpstairs() { - return propagateVariablesUpstairs; - } - - public void setPropagateVariablesUp(boolean propagateVariablesUpstairs) { - this.propagateVariablesUpstairs = propagateVariablesUpstairs; - } - - public JpqlEntityModel getEntityByVariableName(String entityVariableName) { - JpqlEntityModel result = entityVariableName2entity.get(entityVariableName); - if (result != null) { - return result; - } - - return parent == null ? null : parent.getEntityByVariableName(entityVariableName); - } - - public JpqlEntityModel getEntityByVariableNameHierarchically(String entityVariableName) { - JpqlEntityModel result = entityVariableName2entity.get(entityVariableName); - if (result != null) { - return result; - } - if (children != null) { - for (QueryVariableContext child : children) { - JpqlEntityModel childModel = child.getEntityByVariableNameHierarchically(entityVariableName); - if (childModel != null) { - return childModel; - } - } - } - return null; - } - - /** - * Internal method to register entity variables found in query - * - * @param variableName - found entity variable name - * @param entity entity model - */ - public void addEntityVariable(String variableName, JpqlEntityModel entity) { - if (variableName == null) { - throw new NullPointerException("No entity variable name passed"); - } - if (entity == null) { - throw new NullPointerException("No entity passed"); - } - if (entityVariableName2entity.containsKey(variableName)) - throw new IllegalArgumentException(String.format("Trying to rebind variable [%s]", variableName)); - - entityVariableName2entity.put(variableName, entity); - } - - public QueryVariableContext getContextByCaretPosition(int caretPosition) { - if (!node.contains(caretPosition)) { - return null; - } - - for (QueryVariableContext child : children) { - QueryVariableContext childResult = child.getContextByCaretPosition(caretPosition); - if (childResult != null) - return childResult; - } - return this; - - } - - public void addChild(QueryVariableContext child) { - if (child == null) { - throw new NullPointerException("No child passed"); - } - if (child.getParent() != null) { - throw new IllegalArgumentException("Child has parent already"); - } - child.setParent(this); - children.add(child); - } - - public JpqlEntityModel getEntity() { - return entity; - } - - public void setEntity(JpqlEntityModel entity) { - this.entity = entity; - } - - private QueryVariableContext getParent() { - return parent; - } - - private void setParent(QueryVariableContext parent) { - this.parent = parent; - } - - public String getVariableNameByEntity(String entityName) { - if (entityName == null) - throw new NullPointerException("No entity name passed"); - - for (Map.Entry entry : entityVariableName2entity.entrySet()) { - if (entityName.equals(entry.getValue().getName())) { - return entry.getKey(); - } - } - - return parent == null ? null : parent.getVariableNameByEntity(entityName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.model.VirtualJpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class QueryVariableContext { + private Map entityVariableName2entity = new HashMap<>(); + private QueryNode node; + private List children = new ArrayList<>(); + private JpqlEntityModel entity; + private boolean propagateVariablesUpstairs = true; + private QueryVariableContext parent = null; + + public QueryVariableContext(DomainModel model, QueryNode node) { + Preconditions.checkNotNullArgument(model); + Preconditions.checkNotNullArgument(node); + + this.node = node; + this.entity = new VirtualJpqlEntityModel(); + } + + public boolean isPropagateVariablesUpstairs() { + return propagateVariablesUpstairs; + } + + public void setPropagateVariablesUp(boolean propagateVariablesUpstairs) { + this.propagateVariablesUpstairs = propagateVariablesUpstairs; + } + + public JpqlEntityModel getEntityByVariableName(String entityVariableName) { + JpqlEntityModel result = entityVariableName2entity.get(entityVariableName); + if (result != null) { + return result; + } + + return parent == null ? null : parent.getEntityByVariableName(entityVariableName); + } + + public JpqlEntityModel getEntityByVariableNameHierarchically(String entityVariableName) { + JpqlEntityModel result = entityVariableName2entity.get(entityVariableName); + if (result != null) { + return result; + } + if (children != null) { + for (QueryVariableContext child : children) { + JpqlEntityModel childModel = child.getEntityByVariableNameHierarchically(entityVariableName); + if (childModel != null) { + return childModel; + } + } + } + return null; + } + + /** + * Internal method to register entity variables found in query + * + * @param variableName - found entity variable name + * @param entity entity model + */ + public void addEntityVariable(String variableName, JpqlEntityModel entity) { + if (variableName == null) { + throw new NullPointerException("No entity variable name passed"); + } + if (entity == null) { + throw new NullPointerException("No entity passed"); + } + if (entityVariableName2entity.containsKey(variableName)) + throw new IllegalArgumentException(String.format("Trying to rebind variable [%s]", variableName)); + + entityVariableName2entity.put(variableName, entity); + } + + public QueryVariableContext getContextByCaretPosition(int caretPosition) { + if (!node.contains(caretPosition)) { + return null; + } + + for (QueryVariableContext child : children) { + QueryVariableContext childResult = child.getContextByCaretPosition(caretPosition); + if (childResult != null) + return childResult; + } + return this; + + } + + public void addChild(QueryVariableContext child) { + if (child == null) { + throw new NullPointerException("No child passed"); + } + if (child.getParent() != null) { + throw new IllegalArgumentException("Child has parent already"); + } + child.setParent(this); + children.add(child); + } + + public JpqlEntityModel getEntity() { + return entity; + } + + public void setEntity(JpqlEntityModel entity) { + this.entity = entity; + } + + private QueryVariableContext getParent() { + return parent; + } + + private void setParent(QueryVariableContext parent) { + this.parent = parent; + } + + public String getVariableNameByEntity(String entityName) { + if (entityName == null) + throw new NullPointerException("No entity name passed"); + + for (Map.Entry entry : entityVariableName2entity.entrySet()) { + if (entityName.equals(entry.getValue().getName())) { + return entry.getKey(); + } + } + + return parent == null ? null : parent.getVariableNameByEntity(entityName); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/TreeToQuery.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/TreeToQuery.java index 4c6a646882..741ec11b3f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/TreeToQuery.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/TreeToQuery.java @@ -1,146 +1,146 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.tree.TreeToQueryCapable; -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.TreeVisitorAction; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class TreeToQuery implements TreeVisitorAction { - private QueryBuilder sb = new QueryBuilder(); - private List invalidNodes = new ArrayList<>(); - - @Override - public Object pre(Object t) { - if (!(t instanceof CommonTree)) { - return t; - } - - if (t instanceof CommonErrorNode) { - invalidNodes.add(new ErrorRec((CommonErrorNode) t, "Error node")); - return t; - } - - CommonTree node = (CommonTree) t; - - if (node.token == null) - return t; - - if (node.getType() == JPA2Lexer.HAVING || - node.parent != null && node.parent.getType() == JPA2Lexer.T_SIMPLE_CONDITION - && !parentNodeHasPreviousLparen(node) || - node.parent != null && node.parent.getType() == JPA2Lexer.T_GROUP_BY || - node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY && node.getType() != JPA2Lexer.T_ORDER_BY_FIELD || - node.parent != null && node.parent.getType() == JPA2Lexer.T_CONDITION && node.getType() == JPA2Lexer.LPAREN && (node.childIndex == 0 || node.parent.getChild(node.childIndex - 1).getType() != JPA2Lexer.LPAREN) || - node.getType() == JPA2Lexer.AND || - node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY_FIELD || - node.parent != null && node.parent.getType() == JPA2Lexer.T_SELECTED_ITEM && node.getType() == JPA2Lexer.AS || - node.getType() == JPA2Lexer.OR || - node.getType() == JPA2Lexer.NOT || - node.getType() == JPA2Lexer.DISTINCT && node.childIndex == 0 || - node.getType() == JPA2Lexer.JOIN || - node.getType() == JPA2Lexer.LEFT || - node.getType() == JPA2Lexer.OUTER || - node.getType() == JPA2Lexer.INNER || - node.getType() == JPA2Lexer.FETCH - ) { - sb.appendSpace(); - } - - if (node.getType() == JPA2Lexer.T_ORDER_BY_FIELD && node.childIndex > 0 && node.parent.getChild(node.childIndex - 1).getType() == JPA2Lexer.T_ORDER_BY_FIELD) { - sb.appendString(", "); - } - - if (isGroupByItem(node)) { - if (node.childIndex > 0 && isGroupByItem((CommonTree) node.parent.getChild(node.childIndex - 1))) { - sb.appendString(", "); - } - } - - if (node instanceof TreeToQueryCapable) { - return ((TreeToQueryCapable) t).treeToQueryPre(sb, invalidNodes); - } - - if (node.getType() == JPA2Lexer.T_SELECTED_ITEMS) { - return t; - } - - if (node.getType() == JPA2Lexer.T_SOURCES) { - sb.appendString("from "); - return t; - } - - sb.appendString(node.toString()); - return t; - } - - private boolean parentNodeHasPreviousLparen(CommonTree node) { - return (node.childIndex == 0 && node.parent.childIndex > 0 && node.parent.parent.getChild(node.parent.childIndex - 1).getType() == JPA2Lexer.LPAREN); - } - - private boolean isGroupByItem(CommonTree node) { - if (node.parent != null && node.parent.getType() == JPA2Lexer.T_GROUP_BY) { - if (node.getType() != JPA2Lexer.BY && node.getType() != JPA2Lexer.GROUP) { - return true; - } - } - return false; - } - - @Override - public Object post(Object t) { - if (!(t instanceof CommonTree)) - return t; - - if (t instanceof CommonErrorNode) { - return t; - } - - CommonTree node = (CommonTree) t; - - if (node.token == null) - return t; - - if (node.getType() == JPA2Lexer.DISTINCT || - node.getType() == JPA2Lexer.FETCH || - node.parent != null && node.parent.getType() == JPA2Lexer.T_SELECTED_ITEM && node.getType() == JPA2Lexer.AS) { - sb.appendSpace(); - } - - - if (node instanceof TreeToQueryCapable) { - return ((TreeToQueryCapable) t).treeToQueryPost(sb, invalidNodes); - } - - return t; - } - - public List getInvalidNodes() { - return Collections.unmodifiableList(invalidNodes); - } - - public String getQueryString() { - return sb.toString(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.tree.TreeToQueryCapable; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeVisitorAction; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TreeToQuery implements TreeVisitorAction { + private QueryBuilder sb = new QueryBuilder(); + private List invalidNodes = new ArrayList<>(); + + @Override + public Object pre(Object t) { + if (!(t instanceof CommonTree)) { + return t; + } + + if (t instanceof CommonErrorNode) { + invalidNodes.add(new ErrorRec((CommonErrorNode) t, "Error node")); + return t; + } + + CommonTree node = (CommonTree) t; + + if (node.token == null) + return t; + + if (node.getType() == JPA2Lexer.HAVING || + node.parent != null && node.parent.getType() == JPA2Lexer.T_SIMPLE_CONDITION + && !parentNodeHasPreviousLparen(node) || + node.parent != null && node.parent.getType() == JPA2Lexer.T_GROUP_BY || + node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY && node.getType() != JPA2Lexer.T_ORDER_BY_FIELD || + node.parent != null && node.parent.getType() == JPA2Lexer.T_CONDITION && node.getType() == JPA2Lexer.LPAREN && (node.childIndex == 0 || node.parent.getChild(node.childIndex - 1).getType() != JPA2Lexer.LPAREN) || + node.getType() == JPA2Lexer.AND || + node.parent != null && node.parent.getType() == JPA2Lexer.T_ORDER_BY_FIELD || + node.parent != null && node.parent.getType() == JPA2Lexer.T_SELECTED_ITEM && node.getType() == JPA2Lexer.AS || + node.getType() == JPA2Lexer.OR || + node.getType() == JPA2Lexer.NOT || + node.getType() == JPA2Lexer.DISTINCT && node.childIndex == 0 || + node.getType() == JPA2Lexer.JOIN || + node.getType() == JPA2Lexer.LEFT || + node.getType() == JPA2Lexer.OUTER || + node.getType() == JPA2Lexer.INNER || + node.getType() == JPA2Lexer.FETCH + ) { + sb.appendSpace(); + } + + if (node.getType() == JPA2Lexer.T_ORDER_BY_FIELD && node.childIndex > 0 && node.parent.getChild(node.childIndex - 1).getType() == JPA2Lexer.T_ORDER_BY_FIELD) { + sb.appendString(", "); + } + + if (isGroupByItem(node)) { + if (node.childIndex > 0 && isGroupByItem((CommonTree) node.parent.getChild(node.childIndex - 1))) { + sb.appendString(", "); + } + } + + if (node instanceof TreeToQueryCapable) { + return ((TreeToQueryCapable) t).treeToQueryPre(sb, invalidNodes); + } + + if (node.getType() == JPA2Lexer.T_SELECTED_ITEMS) { + return t; + } + + if (node.getType() == JPA2Lexer.T_SOURCES) { + sb.appendString("from "); + return t; + } + + sb.appendString(node.toString()); + return t; + } + + private boolean parentNodeHasPreviousLparen(CommonTree node) { + return (node.childIndex == 0 && node.parent.childIndex > 0 && node.parent.parent.getChild(node.parent.childIndex - 1).getType() == JPA2Lexer.LPAREN); + } + + private boolean isGroupByItem(CommonTree node) { + if (node.parent != null && node.parent.getType() == JPA2Lexer.T_GROUP_BY) { + if (node.getType() != JPA2Lexer.BY && node.getType() != JPA2Lexer.GROUP) { + return true; + } + } + return false; + } + + @Override + public Object post(Object t) { + if (!(t instanceof CommonTree)) + return t; + + if (t instanceof CommonErrorNode) { + return t; + } + + CommonTree node = (CommonTree) t; + + if (node.token == null) + return t; + + if (node.getType() == JPA2Lexer.DISTINCT || + node.getType() == JPA2Lexer.FETCH || + node.parent != null && node.parent.getType() == JPA2Lexer.T_SELECTED_ITEM && node.getType() == JPA2Lexer.AS) { + sb.appendSpace(); + } + + + if (node instanceof TreeToQueryCapable) { + return ((TreeToQueryCapable) t).treeToQueryPost(sb, invalidNodes); + } + + return t; + } + + public List getInvalidNodes() { + return Collections.unmodifiableList(invalidNodes); + } + + public String getQueryString() { + return sb.toString(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/UnknownEntityNameException.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/UnknownEntityNameException.java index eba047ff0d..d0cf827362 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/UnknownEntityNameException.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/UnknownEntityNameException.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -public class UnknownEntityNameException extends Exception { - private String entityName; - - public UnknownEntityNameException(String entityName) { - super("Entity with name [" + entityName + "] is unknown"); - this.entityName = entityName; - } - - public String getEntityName() { - return entityName; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +public class UnknownEntityNameException extends Exception { + private String entityName; + + public UnknownEntityNameException(String entityName) { + super("Entity with name [" + entityName + "] is unknown"); + this.entityName = entityName; + } + + public String getEntityName() { + return entityName; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.g b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.g index bdb330f8b2..54cc35ddcf 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.g +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.g @@ -1,469 +1,469 @@ - -grammar JPA; - -options{ - backtrack=true; - output=AST; -} - -tokens { - T_SELECTED_ITEMS; - T_SELECTED_ITEM; - T_SOURCES; - T_SOURCE; - T_SELECTED_FIELD; - T_SELECTED_ENTITY; - T_ID_VAR; - T_JOIN_VAR; - T_COLLECTION_MEMBER; - T_QUERY; - T_CONDITION; - T_SIMPLE_CONDITION; - T_PARAMETER; - T_GROUP_BY; - T_ORDER_BY; - T_ORDER_BY_FIELD; - T_AGGREGATE_EXPR; - HAVING = 'HAVING'; - ASC = 'ASC'; - DESC = 'DESC'; - AVG = 'AVG'; - MAX = 'MAX'; - MIN = 'MIN'; - SUM = 'SUM'; - COUNT = 'COUNT'; - OR = 'OR'; - AND = 'AND'; - LPAREN = '('; - RPAREN = ')'; - DISTINCT = 'DISTINCT'; - LEFT = 'LEFT'; - OUTER = 'OUTER'; - INNER = 'INNER'; - JOIN = 'JOIN'; - FETCH = 'FETCH'; - ORDER = 'ORDER'; - GROUP = 'GROUP'; - BY = 'BY'; -} - - -@header { -package com.haulmont.cuba.core.sys.jpql.antlr; - -import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; -import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import com.haulmont.cuba.core.sys.jpql.tree.FromNode; -import com.haulmont.cuba.core.sys.jpql.tree.SelectionSourceNode; -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.CollectionMemberNode; -import com.haulmont.cuba.core.sys.jpql.tree.WhereNode; -import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; -import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; -import com.haulmont.cuba.core.sys.jpql.tree.GroupByNode; -import com.haulmont.cuba.core.sys.jpql.tree.OrderByNode; -import com.haulmont.cuba.core.sys.jpql.tree.OrderByFieldNode; -import com.haulmont.cuba.core.sys.jpql.tree.AggregateExpressionNode; -} - -@lexer::header { -package com.haulmont.cuba.core.sys.jpql.antlr; - -} - - -ql_statement - : select_statement; - -select_statement - : sl='SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)? - -> ^(T_QUERY[$sl] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?); - -from_clause - : fr='FROM' identification_variable_declaration (',' identification_variable_or_collection_declaration)* - -> ^(T_SOURCES[$fr] identification_variable_declaration identification_variable_or_collection_declaration*); - -identification_variable_or_collection_declaration - : identification_variable_declaration - | collection_member_declaration -> ^(T_SOURCE collection_member_declaration); - -identification_variable_declaration - : range_variable_declaration joined_clause* - -> ^(T_SOURCE range_variable_declaration joined_clause*); - -joined_clause - : join | fetch_join; - -range_variable_declaration - : range_variable_declaration_source ('AS')? identification_variable - -> ^(T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) - ; - -range_variable_declaration_source - : abstract_schema_name - | lp='(SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)? rp=')' - -> ^(T_QUERY[$lp, $rp] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?) - ; - -join - : join_spec join_association_path_expression ('AS')? identification_variable - -> ^(T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) - ; - -fetch_join - : join_spec 'FETCH' join_association_path_expression; - -join_spec - :(('LEFT') ('OUTER')? | 'INNER' )? 'JOIN'; - -join_association_path_expression - : identification_variable '.' (field'.')* field? - -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) - ; - -collection_member_declaration - : 'IN''(' path_expression ')' ('AS')? identification_variable - -> ^(T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) - ; - -path_expression - : identification_variable '.' (field'.')* (field)? - -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) - ; - -select_clause - : ('DISTINCT')? select_expression (',' select_expression)* - -> ^(T_SELECTED_ITEMS ('DISTINCT')? ^(T_SELECTED_ITEM[] select_expression)*) - ; - -select_expression - : path_expression - | aggregate_expression - | identification_variable -> ^(T_SELECTED_ENTITY[$identification_variable.text]) - | 'OBJECT' '('identification_variable')' - | constructor_expression; - -constructor_expression - : 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')'; - -constructor_item - : path_expression | aggregate_expression; - -aggregate_expression - : aggregate_expression_function_name '(' ('DISTINCT')? path_expression')' - -> ^(T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ('DISTINCT')? path_expression')') - | 'COUNT' '(' ('DISTINCT')? identification_variable ')' - -> ^(T_AGGREGATE_EXPR[] 'COUNT' '(' ('DISTINCT')? identification_variable ')'); - -aggregate_expression_function_name - : 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT'; - -where_clause - : wh='WHERE' conditional_expression-> ^(T_CONDITION[$wh] conditional_expression) - | 'WHERE' path_expression -> ^(T_CONDITION[$wh] path_expression); - -groupby_clause - : 'GROUP' 'BY' groupby_item (',' groupby_item)* - -> ^(T_GROUP_BY[] 'GROUP' 'BY' groupby_item*) - ; - -groupby_item - : path_expression | identification_variable; - -having_clause - : 'HAVING' conditional_expression; - -orderby_clause - : 'ORDER' 'BY' orderby_item (',' orderby_item)* - -> ^(T_ORDER_BY[] 'ORDER' 'BY' orderby_item*); - -orderby_item - : path_expression ('ASC')? - -> ^(T_ORDER_BY_FIELD[] path_expression ('ASC')?) - | path_expression 'DESC' - -> ^(T_ORDER_BY_FIELD[] path_expression 'DESC'); - -subquery - : lp='(SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')' - -> ^(T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? ); - -subquery_from_clause - : fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)* - -> ^(T_SOURCES[$fr] ^(T_SOURCE subselect_identification_variable_declaration)*); - -subselect_identification_variable_declaration - : identification_variable_declaration - | association_path_expression ('AS')? identification_variable - | collection_member_declaration; - -association_path_expression - : path_expression; - -simple_select_clause - : ('DISTINCT')? simple_select_expression - -> ^(T_SELECTED_ITEMS ^(T_SELECTED_ITEM[] ('DISTINCT')? simple_select_expression)); - -simple_select_expression - : path_expression - | aggregate_expression - | identification_variable; - -conditional_expression - : (conditional_term) ('OR' conditional_term)*; - -conditional_term - : (conditional_factor) ('AND' conditional_factor)*; - -conditional_factor - : ('NOT')? simple_cond_expression -> ^(T_SIMPLE_CONDITION[] ('NOT')? simple_cond_expression) - | '('conditional_expression')'; - -simple_cond_expression - : comparison_expression - | between_expression - | like_expression - | in_expression - | null_comparison_expression - | empty_collection_comparison_expression - | collection_member_expression - | exists_expression - | date_macro_expression; - -date_macro_expression - : date_between_macro_expression - | date_before_macro_expression - | date_after_macro_expression - | date_equals_macro_expression - | date_today_macro_expression; - -date_between_macro_expression - : '@BETWEEN' '(' path_expression ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' ('YEAR' | 'MONTH' | 'DAY' | 'HOUR' |'MINUTE' | 'SECOND') ')'; - -date_before_macro_expression - : '@DATEBEFORE' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_after_macro_expression - : '@DATEAFTER' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_equals_macro_expression - : '@DATEEQUALS' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_today_macro_expression - : '@TODAY' '(' path_expression ')'; - -between_expression - : arithmetic_expression ('NOT')? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression - | string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression - | datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression; - -in_expression - : path_expression ('NOT')? 'IN' in_expression_right_part; - -in_expression_right_part - : '(' in_item (',' in_item)* ')' - | subquery; - -in_item - : literal - | input_parameter; - -like_expression - : string_expression ('NOT')? 'LIKE' (pattern_value | input_parameter)('ESCAPE' ESCAPE_CHARACTER)?; - -null_comparison_expression - : (path_expression | input_parameter) 'IS' ('NOT')? 'NULL'; - -empty_collection_comparison_expression - : path_expression 'IS' ('NOT')? 'EMPTY'; - -collection_member_expression - : entity_expression ('NOT')? 'MEMBER' ('OF')? path_expression; - -exists_expression - : ('NOT')? 'EXISTS' subquery; - -all_or_any_expression - : ( 'ALL' | 'ANY' | 'SOME') subquery; - -comparison_expression - : string_expression comparison_operator (string_expression | all_or_any_expression) - | boolean_expression ('=' | '<>') (boolean_expression | all_or_any_expression) - | enum_expression ('='|'<>') (enum_expression | all_or_any_expression) - | datetime_expression comparison_operator (datetime_expression | all_or_any_expression) - | entity_expression ('=' | '<>') (entity_expression | all_or_any_expression) - | arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression); - -comparison_operator - : '=' - | '>' - | '>=' - | '<' - | '<=' - | '<>'; - -arithmetic_expression - : simple_arithmetic_expression - | subquery; - -simple_arithmetic_expression - : (arithmetic_term) (( '+' | '-' ) arithmetic_term)*; - -arithmetic_term - : (arithmetic_factor) (( '*' | '/' ) arithmetic_factor)*; - -arithmetic_factor - : ( '+' | '-' )? arithmetic_primary; - -arithmetic_primary - : path_expression - | numeric_literal - | '('simple_arithmetic_expression')' - | input_parameter - | functions_returning_numerics - | aggregate_expression; - -string_expression - : string_primary | subquery; - -string_primary - : path_expression - | STRINGLITERAL - | input_parameter - | functions_returning_strings - | aggregate_expression; - -datetime_expression - : datetime_primary - | subquery; - -datetime_primary - : path_expression - | input_parameter - | functions_returning_datetime - | aggregate_expression; - -boolean_expression - : boolean_primary - | subquery; - -boolean_primary - : path_expression - | boolean_literal - | input_parameter; - -enum_expression - : enum_primary - | subquery; - -enum_primary - : path_expression - | enum_literal - | input_parameter; - -entity_expression - : path_expression - | simple_entity_expression; - -simple_entity_expression - : identification_variable - | input_parameter; - -functions_returning_numerics - : 'LENGTH' '('string_primary')' - | 'LOCATE' '('string_primary',' string_primary(',' simple_arithmetic_expression)?')' - | 'ABS' '('simple_arithmetic_expression')' - | 'SQRT' '('simple_arithmetic_expression')' - | 'MOD' '('simple_arithmetic_expression',' simple_arithmetic_expression')' - | 'SIZE' '('path_expression')'; - -functions_returning_datetime - : 'CURRENT_DATE' - | 'CURRENT_TIME' - | 'CURRENT_TIMESTAMP'; - -functions_returning_strings - : 'CONCAT' '('string_primary',' string_primary')' - | 'SUBSTRING' '('string_primary','simple_arithmetic_expression',' simple_arithmetic_expression')' - | 'TRIM' '('((trim_specification)? (TRIM_CHARACTER)? 'FROM')? string_primary')' - | 'LOWER' '('string_primary')' - | 'UPPER' '('string_primary')'; - -trim_specification - : 'LEADING' - | 'TRAILING' - | 'BOTH'; - -//my -abstract_schema_name - : WORD; - -//todo fix pattern value if needed -pattern_value - : WORD; - -// my -numeric_literal - : ('0x')? INT_NUMERAL ; - -input_parameter - : '?' INT_NUMERAL -> ^(T_PARAMETER[] '?' INT_NUMERAL ) - | NAMED_PARAMETER -> ^(T_PARAMETER[] NAMED_PARAMETER ) - | '${' WORD '}' -> ^(T_PARAMETER[] '${' WORD '}'); - -literal - : WORD; - -constructor_name - : WORD; - -enum_literal - : WORD; - -boolean_literal - : 'true' - | 'false'; - -// my -field - : WORD | 'GROUP'; - -identification_variable - : WORD; - -parameter_name - : WORD ('.' WORD)*; - - -// Lexical Rules -//fix trim character -TRIM_CHARACTER - : '\'.\''; - -STRINGLITERAL - : '\'' (~('\'' | '"') )* '\'' ; - -WORD - : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')*; - -RUSSIAN_SYMBOLS - : ('\u0400'..'\u04FF'|'\u0500'..'\u052F' ) {if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol");}; - -NAMED_PARAMETER - : ':'('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* (('.') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')+)*; - -WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} - ; - -COMMENT - : '/*' .* '*/' {$channel=HIDDEN;}; - -LINE_COMMENT - : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}; - -ESCAPE_CHARACTER - : '\'' (~('\''|'\\') ) '\''; - -INT_NUMERAL - : ('0'..'9')+; + +grammar JPA; + +options{ + backtrack=true; + output=AST; +} + +tokens { + T_SELECTED_ITEMS; + T_SELECTED_ITEM; + T_SOURCES; + T_SOURCE; + T_SELECTED_FIELD; + T_SELECTED_ENTITY; + T_ID_VAR; + T_JOIN_VAR; + T_COLLECTION_MEMBER; + T_QUERY; + T_CONDITION; + T_SIMPLE_CONDITION; + T_PARAMETER; + T_GROUP_BY; + T_ORDER_BY; + T_ORDER_BY_FIELD; + T_AGGREGATE_EXPR; + HAVING = 'HAVING'; + ASC = 'ASC'; + DESC = 'DESC'; + AVG = 'AVG'; + MAX = 'MAX'; + MIN = 'MIN'; + SUM = 'SUM'; + COUNT = 'COUNT'; + OR = 'OR'; + AND = 'AND'; + LPAREN = '('; + RPAREN = ')'; + DISTINCT = 'DISTINCT'; + LEFT = 'LEFT'; + OUTER = 'OUTER'; + INNER = 'INNER'; + JOIN = 'JOIN'; + FETCH = 'FETCH'; + ORDER = 'ORDER'; + GROUP = 'GROUP'; + BY = 'BY'; +} + + +@header { +package com.haulmont.cuba.core.sys.jpql.antlr; + +import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; +import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import com.haulmont.cuba.core.sys.jpql.tree.FromNode; +import com.haulmont.cuba.core.sys.jpql.tree.SelectionSourceNode; +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.CollectionMemberNode; +import com.haulmont.cuba.core.sys.jpql.tree.WhereNode; +import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; +import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; +import com.haulmont.cuba.core.sys.jpql.tree.GroupByNode; +import com.haulmont.cuba.core.sys.jpql.tree.OrderByNode; +import com.haulmont.cuba.core.sys.jpql.tree.OrderByFieldNode; +import com.haulmont.cuba.core.sys.jpql.tree.AggregateExpressionNode; +} + +@lexer::header { +package com.haulmont.cuba.core.sys.jpql.antlr; + +} + + +ql_statement + : select_statement; + +select_statement + : sl='SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)? + -> ^(T_QUERY[$sl] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?); + +from_clause + : fr='FROM' identification_variable_declaration (',' identification_variable_or_collection_declaration)* + -> ^(T_SOURCES[$fr] identification_variable_declaration identification_variable_or_collection_declaration*); + +identification_variable_or_collection_declaration + : identification_variable_declaration + | collection_member_declaration -> ^(T_SOURCE collection_member_declaration); + +identification_variable_declaration + : range_variable_declaration joined_clause* + -> ^(T_SOURCE range_variable_declaration joined_clause*); + +joined_clause + : join | fetch_join; + +range_variable_declaration + : range_variable_declaration_source ('AS')? identification_variable + -> ^(T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) + ; + +range_variable_declaration_source + : abstract_schema_name + | lp='(SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)?(orderby_clause)? rp=')' + -> ^(T_QUERY[$lp, $rp] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?) + ; + +join + : join_spec join_association_path_expression ('AS')? identification_variable + -> ^(T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) + ; + +fetch_join + : join_spec 'FETCH' join_association_path_expression; + +join_spec + :(('LEFT') ('OUTER')? | 'INNER' )? 'JOIN'; + +join_association_path_expression + : identification_variable '.' (field'.')* field? + -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) + ; + +collection_member_declaration + : 'IN''(' path_expression ')' ('AS')? identification_variable + -> ^(T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) + ; + +path_expression + : identification_variable '.' (field'.')* (field)? + -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) + ; + +select_clause + : ('DISTINCT')? select_expression (',' select_expression)* + -> ^(T_SELECTED_ITEMS ('DISTINCT')? ^(T_SELECTED_ITEM[] select_expression)*) + ; + +select_expression + : path_expression + | aggregate_expression + | identification_variable -> ^(T_SELECTED_ENTITY[$identification_variable.text]) + | 'OBJECT' '('identification_variable')' + | constructor_expression; + +constructor_expression + : 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')'; + +constructor_item + : path_expression | aggregate_expression; + +aggregate_expression + : aggregate_expression_function_name '(' ('DISTINCT')? path_expression')' + -> ^(T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ('DISTINCT')? path_expression')') + | 'COUNT' '(' ('DISTINCT')? identification_variable ')' + -> ^(T_AGGREGATE_EXPR[] 'COUNT' '(' ('DISTINCT')? identification_variable ')'); + +aggregate_expression_function_name + : 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT'; + +where_clause + : wh='WHERE' conditional_expression-> ^(T_CONDITION[$wh] conditional_expression) + | 'WHERE' path_expression -> ^(T_CONDITION[$wh] path_expression); + +groupby_clause + : 'GROUP' 'BY' groupby_item (',' groupby_item)* + -> ^(T_GROUP_BY[] 'GROUP' 'BY' groupby_item*) + ; + +groupby_item + : path_expression | identification_variable; + +having_clause + : 'HAVING' conditional_expression; + +orderby_clause + : 'ORDER' 'BY' orderby_item (',' orderby_item)* + -> ^(T_ORDER_BY[] 'ORDER' 'BY' orderby_item*); + +orderby_item + : path_expression ('ASC')? + -> ^(T_ORDER_BY_FIELD[] path_expression ('ASC')?) + | path_expression 'DESC' + -> ^(T_ORDER_BY_FIELD[] path_expression 'DESC'); + +subquery + : lp='(SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')' + -> ^(T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? ); + +subquery_from_clause + : fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)* + -> ^(T_SOURCES[$fr] ^(T_SOURCE subselect_identification_variable_declaration)*); + +subselect_identification_variable_declaration + : identification_variable_declaration + | association_path_expression ('AS')? identification_variable + | collection_member_declaration; + +association_path_expression + : path_expression; + +simple_select_clause + : ('DISTINCT')? simple_select_expression + -> ^(T_SELECTED_ITEMS ^(T_SELECTED_ITEM[] ('DISTINCT')? simple_select_expression)); + +simple_select_expression + : path_expression + | aggregate_expression + | identification_variable; + +conditional_expression + : (conditional_term) ('OR' conditional_term)*; + +conditional_term + : (conditional_factor) ('AND' conditional_factor)*; + +conditional_factor + : ('NOT')? simple_cond_expression -> ^(T_SIMPLE_CONDITION[] ('NOT')? simple_cond_expression) + | '('conditional_expression')'; + +simple_cond_expression + : comparison_expression + | between_expression + | like_expression + | in_expression + | null_comparison_expression + | empty_collection_comparison_expression + | collection_member_expression + | exists_expression + | date_macro_expression; + +date_macro_expression + : date_between_macro_expression + | date_before_macro_expression + | date_after_macro_expression + | date_equals_macro_expression + | date_today_macro_expression; + +date_between_macro_expression + : '@BETWEEN' '(' path_expression ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' 'NOW' (('+' | '-') INT_NUMERAL)? ',' ('YEAR' | 'MONTH' | 'DAY' | 'HOUR' |'MINUTE' | 'SECOND') ')'; + +date_before_macro_expression + : '@DATEBEFORE' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_after_macro_expression + : '@DATEAFTER' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_equals_macro_expression + : '@DATEEQUALS' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_today_macro_expression + : '@TODAY' '(' path_expression ')'; + +between_expression + : arithmetic_expression ('NOT')? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression + | string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression + | datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression; + +in_expression + : path_expression ('NOT')? 'IN' in_expression_right_part; + +in_expression_right_part + : '(' in_item (',' in_item)* ')' + | subquery; + +in_item + : literal + | input_parameter; + +like_expression + : string_expression ('NOT')? 'LIKE' (pattern_value | input_parameter)('ESCAPE' ESCAPE_CHARACTER)?; + +null_comparison_expression + : (path_expression | input_parameter) 'IS' ('NOT')? 'NULL'; + +empty_collection_comparison_expression + : path_expression 'IS' ('NOT')? 'EMPTY'; + +collection_member_expression + : entity_expression ('NOT')? 'MEMBER' ('OF')? path_expression; + +exists_expression + : ('NOT')? 'EXISTS' subquery; + +all_or_any_expression + : ( 'ALL' | 'ANY' | 'SOME') subquery; + +comparison_expression + : string_expression comparison_operator (string_expression | all_or_any_expression) + | boolean_expression ('=' | '<>') (boolean_expression | all_or_any_expression) + | enum_expression ('='|'<>') (enum_expression | all_or_any_expression) + | datetime_expression comparison_operator (datetime_expression | all_or_any_expression) + | entity_expression ('=' | '<>') (entity_expression | all_or_any_expression) + | arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression); + +comparison_operator + : '=' + | '>' + | '>=' + | '<' + | '<=' + | '<>'; + +arithmetic_expression + : simple_arithmetic_expression + | subquery; + +simple_arithmetic_expression + : (arithmetic_term) (( '+' | '-' ) arithmetic_term)*; + +arithmetic_term + : (arithmetic_factor) (( '*' | '/' ) arithmetic_factor)*; + +arithmetic_factor + : ( '+' | '-' )? arithmetic_primary; + +arithmetic_primary + : path_expression + | numeric_literal + | '('simple_arithmetic_expression')' + | input_parameter + | functions_returning_numerics + | aggregate_expression; + +string_expression + : string_primary | subquery; + +string_primary + : path_expression + | STRINGLITERAL + | input_parameter + | functions_returning_strings + | aggregate_expression; + +datetime_expression + : datetime_primary + | subquery; + +datetime_primary + : path_expression + | input_parameter + | functions_returning_datetime + | aggregate_expression; + +boolean_expression + : boolean_primary + | subquery; + +boolean_primary + : path_expression + | boolean_literal + | input_parameter; + +enum_expression + : enum_primary + | subquery; + +enum_primary + : path_expression + | enum_literal + | input_parameter; + +entity_expression + : path_expression + | simple_entity_expression; + +simple_entity_expression + : identification_variable + | input_parameter; + +functions_returning_numerics + : 'LENGTH' '('string_primary')' + | 'LOCATE' '('string_primary',' string_primary(',' simple_arithmetic_expression)?')' + | 'ABS' '('simple_arithmetic_expression')' + | 'SQRT' '('simple_arithmetic_expression')' + | 'MOD' '('simple_arithmetic_expression',' simple_arithmetic_expression')' + | 'SIZE' '('path_expression')'; + +functions_returning_datetime + : 'CURRENT_DATE' + | 'CURRENT_TIME' + | 'CURRENT_TIMESTAMP'; + +functions_returning_strings + : 'CONCAT' '('string_primary',' string_primary')' + | 'SUBSTRING' '('string_primary','simple_arithmetic_expression',' simple_arithmetic_expression')' + | 'TRIM' '('((trim_specification)? (TRIM_CHARACTER)? 'FROM')? string_primary')' + | 'LOWER' '('string_primary')' + | 'UPPER' '('string_primary')'; + +trim_specification + : 'LEADING' + | 'TRAILING' + | 'BOTH'; + +//my +abstract_schema_name + : WORD; + +//todo fix pattern value if needed +pattern_value + : WORD; + +// my +numeric_literal + : ('0x')? INT_NUMERAL ; + +input_parameter + : '?' INT_NUMERAL -> ^(T_PARAMETER[] '?' INT_NUMERAL ) + | NAMED_PARAMETER -> ^(T_PARAMETER[] NAMED_PARAMETER ) + | '${' WORD '}' -> ^(T_PARAMETER[] '${' WORD '}'); + +literal + : WORD; + +constructor_name + : WORD; + +enum_literal + : WORD; + +boolean_literal + : 'true' + | 'false'; + +// my +field + : WORD | 'GROUP'; + +identification_variable + : WORD; + +parameter_name + : WORD ('.' WORD)*; + + +// Lexical Rules +//fix trim character +TRIM_CHARACTER + : '\'.\''; + +STRINGLITERAL + : '\'' (~('\'' | '"') )* '\'' ; + +WORD + : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')*; + +RUSSIAN_SYMBOLS + : ('\u0400'..'\u04FF'|'\u0500'..'\u052F' ) {if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol");}; + +NAMED_PARAMETER + : ':'('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* (('.') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')+)*; + +WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} + ; + +COMMENT + : '/*' .* '*/' {$channel=HIDDEN;}; + +LINE_COMMENT + : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}; + +ESCAPE_CHARACTER + : '\'' (~('\''|'\\') ) '\''; + +INT_NUMERAL + : ('0'..'9')+; diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.tokens b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.tokens index 99c394621a..4b60620249 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.tokens +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPA.tokens @@ -1,205 +1,205 @@ -T_JOIN_VAR=11 -T_AGGREGATE_EXPR=20 -COUNT=28 -T_ORDER_BY=18 -WORD=46 -T__93=93 -T__94=94 -RPAREN=32 -T__91=91 -T__92=92 -T__90=90 -TRIM_CHARACTER=45 -T_SELECTED_ITEM=5 -COMMENT=50 -T__99=99 -T__98=98 -T__97=97 -T__96=96 -T_QUERY=13 -T__95=95 -T__80=80 -T__81=81 -T__82=82 -T__83=83 -ASC=22 -LINE_COMMENT=51 -T__85=85 -T__84=84 -T__87=87 -T__86=86 -T__89=89 -T__88=88 -GROUP=40 -WS=49 -T__71=71 -T__72=72 -FETCH=38 -T__70=70 -T_SELECTED_FIELD=8 -OR=29 -T__76=76 -T__75=75 -DISTINCT=33 -T__74=74 -T__73=73 -T__79=79 -T__78=78 -T__77=77 -T__68=68 -T__69=69 -T__66=66 -T__67=67 -T_SELECTED_ITEMS=4 -T__64=64 -T__65=65 -INNER=36 -T__62=62 -T__63=63 -ORDER=39 -T__118=118 -T_SOURCE=7 -T__119=119 -T__116=116 -T_ID_VAR=10 -T__117=117 -T_SIMPLE_CONDITION=15 -T__114=114 -T__115=115 -MAX=25 -AND=30 -SUM=27 -T__61=61 -T__60=60 -RUSSIAN_SYMBOLS=48 -LPAREN=31 -T__55=55 -T__56=56 -T__57=57 -T__58=58 -T__52=52 -T__53=53 -T__54=54 -T__107=107 -T__108=108 -T__109=109 -LEFT=34 -AVG=24 -T_ORDER_BY_FIELD=19 -T__59=59 -T__103=103 -T__104=104 -T__105=105 -T__106=106 -T__111=111 -T__110=110 -T__113=113 -T__112=112 -T_GROUP_BY=17 -OUTER=35 -BY=41 -T_CONDITION=14 -T_SELECTED_ENTITY=9 -T__102=102 -HAVING=21 -T__101=101 -MIN=26 -T__100=100 -T_PARAMETER=16 -JOIN=37 -NAMED_PARAMETER=47 -ESCAPE_CHARACTER=43 -INT_NUMERAL=42 -STRINGLITERAL=44 -T_COLLECTION_MEMBER=12 -DESC=23 -T_SOURCES=6 -'>='=92 -'/'=96 -'>'=91 -'MIN'=26 -'SUBSTRING'=107 -'CONCAT'=106 -'FETCH'=38 -'NEW'=60 -'<>'=90 -'+'=65 -'MEMBER'=83 -'LEFT'=34 -'DAY'=69 -'NULL'=81 -'.'=57 -'LENGTH'=97 -'EMPTY'=82 -'true'=118 -'JOIN'=37 -'SIZE'=102 -'OR'=29 -'@DATEAFTER'=74 -'AVG'=24 -'?'=115 -'@DATEBEFORE'=73 -'UPPER'=110 -'${'=116 -'SQRT'=100 -'('=31 -'HAVING'=21 -'-'=66 -'ASC'=22 -'ABS'=99 -'SOME'=88 -','=54 -'EXISTS'=85 -'BY'=41 -'BOTH'=113 -'OBJECT'=59 -'0x'=114 -'SELECT'=52 -'NOT'=62 -'ESCAPE'=79 -'LOWER'=109 -'ANY'=87 -'COUNT'=28 -'FROM'=53 -'LIKE'=78 -'CURRENT_TIMESTAMP'=105 -'OUTER'=35 -'IS'=80 -'LOCATE'=98 -'='=89 -'MONTH'=68 -'DESC'=23 -'@BETWEEN'=63 -'SUM'=27 -')'=32 -'HOUR'=70 -'INNER'=36 -'MAX'=25 -'AND'=30 -'YEAR'=67 -'ORDER'=39 -'TRAILING'=112 -'}'=117 -'LEADING'=111 -'CURRENT_DATE'=103 -'@TODAY'=76 -'IN'=58 -'NOW'=64 -'BETWEEN'=77 -'CURRENT_TIME'=104 -'AS'=55 -'SECOND'=72 -'<='=94 -'false'=119 -'(SELECT'=56 -'<'=93 -'MOD'=101 -'*'=95 -'WHERE'=61 -'@DATEEQUALS'=75 -'TRIM'=108 -'ALL'=86 -'OF'=84 -'DISTINCT'=33 -'MINUTE'=71 -'GROUP'=40 +T_JOIN_VAR=11 +T_AGGREGATE_EXPR=20 +COUNT=28 +T_ORDER_BY=18 +WORD=46 +T__93=93 +T__94=94 +RPAREN=32 +T__91=91 +T__92=92 +T__90=90 +TRIM_CHARACTER=45 +T_SELECTED_ITEM=5 +COMMENT=50 +T__99=99 +T__98=98 +T__97=97 +T__96=96 +T_QUERY=13 +T__95=95 +T__80=80 +T__81=81 +T__82=82 +T__83=83 +ASC=22 +LINE_COMMENT=51 +T__85=85 +T__84=84 +T__87=87 +T__86=86 +T__89=89 +T__88=88 +GROUP=40 +WS=49 +T__71=71 +T__72=72 +FETCH=38 +T__70=70 +T_SELECTED_FIELD=8 +OR=29 +T__76=76 +T__75=75 +DISTINCT=33 +T__74=74 +T__73=73 +T__79=79 +T__78=78 +T__77=77 +T__68=68 +T__69=69 +T__66=66 +T__67=67 +T_SELECTED_ITEMS=4 +T__64=64 +T__65=65 +INNER=36 +T__62=62 +T__63=63 +ORDER=39 +T__118=118 +T_SOURCE=7 +T__119=119 +T__116=116 +T_ID_VAR=10 +T__117=117 +T_SIMPLE_CONDITION=15 +T__114=114 +T__115=115 +MAX=25 +AND=30 +SUM=27 +T__61=61 +T__60=60 +RUSSIAN_SYMBOLS=48 +LPAREN=31 +T__55=55 +T__56=56 +T__57=57 +T__58=58 +T__52=52 +T__53=53 +T__54=54 +T__107=107 +T__108=108 +T__109=109 +LEFT=34 +AVG=24 +T_ORDER_BY_FIELD=19 +T__59=59 +T__103=103 +T__104=104 +T__105=105 +T__106=106 +T__111=111 +T__110=110 +T__113=113 +T__112=112 +T_GROUP_BY=17 +OUTER=35 +BY=41 +T_CONDITION=14 +T_SELECTED_ENTITY=9 +T__102=102 +HAVING=21 +T__101=101 +MIN=26 +T__100=100 +T_PARAMETER=16 +JOIN=37 +NAMED_PARAMETER=47 +ESCAPE_CHARACTER=43 +INT_NUMERAL=42 +STRINGLITERAL=44 +T_COLLECTION_MEMBER=12 +DESC=23 +T_SOURCES=6 +'>='=92 +'/'=96 +'>'=91 +'MIN'=26 +'SUBSTRING'=107 +'CONCAT'=106 +'FETCH'=38 +'NEW'=60 +'<>'=90 +'+'=65 +'MEMBER'=83 +'LEFT'=34 +'DAY'=69 +'NULL'=81 +'.'=57 +'LENGTH'=97 +'EMPTY'=82 +'true'=118 +'JOIN'=37 +'SIZE'=102 +'OR'=29 +'@DATEAFTER'=74 +'AVG'=24 +'?'=115 +'@DATEBEFORE'=73 +'UPPER'=110 +'${'=116 +'SQRT'=100 +'('=31 +'HAVING'=21 +'-'=66 +'ASC'=22 +'ABS'=99 +'SOME'=88 +','=54 +'EXISTS'=85 +'BY'=41 +'BOTH'=113 +'OBJECT'=59 +'0x'=114 +'SELECT'=52 +'NOT'=62 +'ESCAPE'=79 +'LOWER'=109 +'ANY'=87 +'COUNT'=28 +'FROM'=53 +'LIKE'=78 +'CURRENT_TIMESTAMP'=105 +'OUTER'=35 +'IS'=80 +'LOCATE'=98 +'='=89 +'MONTH'=68 +'DESC'=23 +'@BETWEEN'=63 +'SUM'=27 +')'=32 +'HOUR'=70 +'INNER'=36 +'MAX'=25 +'AND'=30 +'YEAR'=67 +'ORDER'=39 +'TRAILING'=112 +'}'=117 +'LEADING'=111 +'CURRENT_DATE'=103 +'@TODAY'=76 +'IN'=58 +'NOW'=64 +'BETWEEN'=77 +'CURRENT_TIME'=104 +'AS'=55 +'SECOND'=72 +'<='=94 +'false'=119 +'(SELECT'=56 +'<'=93 +'MOD'=101 +'*'=95 +'WHERE'=61 +'@DATEEQUALS'=75 +'TRIM'=108 +'ALL'=86 +'OF'=84 +'DISTINCT'=33 +'MINUTE'=71 +'GROUP'=40 diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPALexer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPALexer.java index 936f560620..4dfa788050 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPALexer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPALexer.java @@ -1,3875 +1,3875 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * 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. - * - */ - -// $ANTLR 3.2 Sep 23, 2009 12:02:23 JPA.g 2012-08-06 14:42:50 - -package com.haulmont.cuba.core.sys.jpql.antlr; - - - -import org.antlr.runtime.*; -import java.util.Stack; -import java.util.List; -import java.util.ArrayList; - -public class JPALexer extends Lexer { - public static final int T_JOIN_VAR=11; - public static final int T_AGGREGATE_EXPR=20; - public static final int COUNT=28; - public static final int T_ORDER_BY=18; - public static final int EOF=-1; - public static final int WORD=46; - public static final int T__93=93; - public static final int T__94=94; - public static final int RPAREN=32; - public static final int T__91=91; - public static final int T__92=92; - public static final int T__90=90; - public static final int TRIM_CHARACTER=45; - public static final int T_SELECTED_ITEM=5; - public static final int COMMENT=50; - public static final int T__99=99; - public static final int T__98=98; - public static final int T__97=97; - public static final int T_QUERY=13; - public static final int T__96=96; - public static final int T__95=95; - public static final int T__80=80; - public static final int T__81=81; - public static final int T__82=82; - public static final int ASC=22; - public static final int T__83=83; - public static final int LINE_COMMENT=51; - public static final int T__85=85; - public static final int T__84=84; - public static final int T__87=87; - public static final int T__86=86; - public static final int T__89=89; - public static final int T__88=88; - public static final int GROUP=40; - public static final int T__71=71; - public static final int WS=49; - public static final int T__72=72; - public static final int FETCH=38; - public static final int T__70=70; - public static final int T_SELECTED_FIELD=8; - public static final int OR=29; - public static final int T__76=76; - public static final int T__75=75; - public static final int DISTINCT=33; - public static final int T__74=74; - public static final int T__73=73; - public static final int T__79=79; - public static final int T__78=78; - public static final int T__77=77; - public static final int T__68=68; - public static final int T__69=69; - public static final int T__66=66; - public static final int T__67=67; - public static final int T_SELECTED_ITEMS=4; - public static final int T__64=64; - public static final int T__65=65; - public static final int INNER=36; - public static final int T__62=62; - public static final int T__63=63; - public static final int ORDER=39; - public static final int T__118=118; - public static final int T_SOURCE=7; - public static final int T__119=119; - public static final int T__116=116; - public static final int T_ID_VAR=10; - public static final int T__117=117; - public static final int T_SIMPLE_CONDITION=15; - public static final int T__114=114; - public static final int T__115=115; - public static final int MAX=25; - public static final int AND=30; - public static final int SUM=27; - public static final int T__61=61; - public static final int T__60=60; - public static final int RUSSIAN_SYMBOLS=48; - public static final int LPAREN=31; - public static final int T__55=55; - public static final int T__56=56; - public static final int T__57=57; - public static final int T__58=58; - public static final int T__52=52; - public static final int T__53=53; - public static final int T__54=54; - public static final int T__107=107; - public static final int T__108=108; - public static final int T__109=109; - public static final int LEFT=34; - public static final int AVG=24; - public static final int T_ORDER_BY_FIELD=19; - public static final int T__103=103; - public static final int T__59=59; - public static final int T__104=104; - public static final int T__105=105; - public static final int T__106=106; - public static final int T__111=111; - public static final int T__110=110; - public static final int T__113=113; - public static final int T__112=112; - public static final int T_GROUP_BY=17; - public static final int OUTER=35; - public static final int BY=41; - public static final int T_CONDITION=14; - public static final int T_SELECTED_ENTITY=9; - public static final int HAVING=21; - public static final int T__102=102; - public static final int T__101=101; - public static final int T__100=100; - public static final int MIN=26; - public static final int T_PARAMETER=16; - public static final int JOIN=37; - public static final int ESCAPE_CHARACTER=43; - public static final int NAMED_PARAMETER=47; - public static final int INT_NUMERAL=42; - public static final int STRINGLITERAL=44; - public static final int T_COLLECTION_MEMBER=12; - public static final int DESC=23; - public static final int T_SOURCES=6; - - // delegates - // delegators - - public JPALexer() {;} - public JPALexer(CharStream input) { - this(input, new RecognizerSharedState()); - } - public JPALexer(CharStream input, RecognizerSharedState state) { - super(input,state); - - } - public String getGrammarFileName() { return "JPA.g"; } - - // $ANTLR start "HAVING" - public final void mHAVING() throws RecognitionException { - try { - int _type = HAVING; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:8:8: ( 'HAVING' ) - // JPA.g:8:10: 'HAVING' - { - match("HAVING"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "HAVING" - - // $ANTLR start "ASC" - public final void mASC() throws RecognitionException { - try { - int _type = ASC; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:9:5: ( 'ASC' ) - // JPA.g:9:7: 'ASC' - { - match("ASC"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "ASC" - - // $ANTLR start "DESC" - public final void mDESC() throws RecognitionException { - try { - int _type = DESC; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:10:6: ( 'DESC' ) - // JPA.g:10:8: 'DESC' - { - match("DESC"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "DESC" - - // $ANTLR start "AVG" - public final void mAVG() throws RecognitionException { - try { - int _type = AVG; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:11:5: ( 'AVG' ) - // JPA.g:11:7: 'AVG' - { - match("AVG"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "AVG" - - // $ANTLR start "MAX" - public final void mMAX() throws RecognitionException { - try { - int _type = MAX; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:12:5: ( 'MAX' ) - // JPA.g:12:7: 'MAX' - { - match("MAX"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "MAX" - - // $ANTLR start "MIN" - public final void mMIN() throws RecognitionException { - try { - int _type = MIN; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:13:5: ( 'MIN' ) - // JPA.g:13:7: 'MIN' - { - match("MIN"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "MIN" - - // $ANTLR start "SUM" - public final void mSUM() throws RecognitionException { - try { - int _type = SUM; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:14:5: ( 'SUM' ) - // JPA.g:14:7: 'SUM' - { - match("SUM"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "SUM" - - // $ANTLR start "COUNT" - public final void mCOUNT() throws RecognitionException { - try { - int _type = COUNT; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:15:7: ( 'COUNT' ) - // JPA.g:15:9: 'COUNT' - { - match("COUNT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "COUNT" - - // $ANTLR start "OR" - public final void mOR() throws RecognitionException { - try { - int _type = OR; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:16:4: ( 'OR' ) - // JPA.g:16:6: 'OR' - { - match("OR"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "OR" - - // $ANTLR start "AND" - public final void mAND() throws RecognitionException { - try { - int _type = AND; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:17:5: ( 'AND' ) - // JPA.g:17:7: 'AND' - { - match("AND"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "AND" - - // $ANTLR start "LPAREN" - public final void mLPAREN() throws RecognitionException { - try { - int _type = LPAREN; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:18:8: ( '(' ) - // JPA.g:18:10: '(' - { - match('('); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "LPAREN" - - // $ANTLR start "RPAREN" - public final void mRPAREN() throws RecognitionException { - try { - int _type = RPAREN; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:19:8: ( ')' ) - // JPA.g:19:10: ')' - { - match(')'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "RPAREN" - - // $ANTLR start "DISTINCT" - public final void mDISTINCT() throws RecognitionException { - try { - int _type = DISTINCT; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:20:10: ( 'DISTINCT' ) - // JPA.g:20:12: 'DISTINCT' - { - match("DISTINCT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "DISTINCT" - - // $ANTLR start "LEFT" - public final void mLEFT() throws RecognitionException { - try { - int _type = LEFT; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:21:6: ( 'LEFT' ) - // JPA.g:21:8: 'LEFT' - { - match("LEFT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "LEFT" - - // $ANTLR start "OUTER" - public final void mOUTER() throws RecognitionException { - try { - int _type = OUTER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:22:7: ( 'OUTER' ) - // JPA.g:22:9: 'OUTER' - { - match("OUTER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "OUTER" - - // $ANTLR start "INNER" - public final void mINNER() throws RecognitionException { - try { - int _type = INNER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:23:7: ( 'INNER' ) - // JPA.g:23:9: 'INNER' - { - match("INNER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "INNER" - - // $ANTLR start "JOIN" - public final void mJOIN() throws RecognitionException { - try { - int _type = JOIN; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:24:6: ( 'JOIN' ) - // JPA.g:24:8: 'JOIN' - { - match("JOIN"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "JOIN" - - // $ANTLR start "FETCH" - public final void mFETCH() throws RecognitionException { - try { - int _type = FETCH; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:25:7: ( 'FETCH' ) - // JPA.g:25:9: 'FETCH' - { - match("FETCH"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "FETCH" - - // $ANTLR start "ORDER" - public final void mORDER() throws RecognitionException { - try { - int _type = ORDER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:26:7: ( 'ORDER' ) - // JPA.g:26:9: 'ORDER' - { - match("ORDER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "ORDER" - - // $ANTLR start "GROUP" - public final void mGROUP() throws RecognitionException { - try { - int _type = GROUP; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:27:7: ( 'GROUP' ) - // JPA.g:27:9: 'GROUP' - { - match("GROUP"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "GROUP" - - // $ANTLR start "BY" - public final void mBY() throws RecognitionException { - try { - int _type = BY; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:28:4: ( 'BY' ) - // JPA.g:28:6: 'BY' - { - match("BY"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "BY" - - // $ANTLR start "T__52" - public final void mT__52() throws RecognitionException { - try { - int _type = T__52; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:29:7: ( 'SELECT' ) - // JPA.g:29:9: 'SELECT' - { - match("SELECT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__52" - - // $ANTLR start "T__53" - public final void mT__53() throws RecognitionException { - try { - int _type = T__53; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:30:7: ( 'FROM' ) - // JPA.g:30:9: 'FROM' - { - match("FROM"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__53" - - // $ANTLR start "T__54" - public final void mT__54() throws RecognitionException { - try { - int _type = T__54; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:31:7: ( ',' ) - // JPA.g:31:9: ',' - { - match(','); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__54" - - // $ANTLR start "T__55" - public final void mT__55() throws RecognitionException { - try { - int _type = T__55; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:32:7: ( 'AS' ) - // JPA.g:32:9: 'AS' - { - match("AS"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__55" - - // $ANTLR start "T__56" - public final void mT__56() throws RecognitionException { - try { - int _type = T__56; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:33:7: ( '(SELECT' ) - // JPA.g:33:9: '(SELECT' - { - match("(SELECT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__56" - - // $ANTLR start "T__57" - public final void mT__57() throws RecognitionException { - try { - int _type = T__57; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:34:7: ( '.' ) - // JPA.g:34:9: '.' - { - match('.'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__57" - - // $ANTLR start "T__58" - public final void mT__58() throws RecognitionException { - try { - int _type = T__58; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:35:7: ( 'IN' ) - // JPA.g:35:9: 'IN' - { - match("IN"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__58" - - // $ANTLR start "T__59" - public final void mT__59() throws RecognitionException { - try { - int _type = T__59; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:36:7: ( 'OBJECT' ) - // JPA.g:36:9: 'OBJECT' - { - match("OBJECT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__59" - - // $ANTLR start "T__60" - public final void mT__60() throws RecognitionException { - try { - int _type = T__60; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:37:7: ( 'NEW' ) - // JPA.g:37:9: 'NEW' - { - match("NEW"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__60" - - // $ANTLR start "T__61" - public final void mT__61() throws RecognitionException { - try { - int _type = T__61; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:38:7: ( 'WHERE' ) - // JPA.g:38:9: 'WHERE' - { - match("WHERE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__61" - - // $ANTLR start "T__62" - public final void mT__62() throws RecognitionException { - try { - int _type = T__62; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:39:7: ( 'NOT' ) - // JPA.g:39:9: 'NOT' - { - match("NOT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__62" - - // $ANTLR start "T__63" - public final void mT__63() throws RecognitionException { - try { - int _type = T__63; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:40:7: ( '@BETWEEN' ) - // JPA.g:40:9: '@BETWEEN' - { - match("@BETWEEN"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__63" - - // $ANTLR start "T__64" - public final void mT__64() throws RecognitionException { - try { - int _type = T__64; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:41:7: ( 'NOW' ) - // JPA.g:41:9: 'NOW' - { - match("NOW"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__64" - - // $ANTLR start "T__65" - public final void mT__65() throws RecognitionException { - try { - int _type = T__65; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:42:7: ( '+' ) - // JPA.g:42:9: '+' - { - match('+'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__65" - - // $ANTLR start "T__66" - public final void mT__66() throws RecognitionException { - try { - int _type = T__66; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:43:7: ( '-' ) - // JPA.g:43:9: '-' - { - match('-'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__66" - - // $ANTLR start "T__67" - public final void mT__67() throws RecognitionException { - try { - int _type = T__67; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:44:7: ( 'YEAR' ) - // JPA.g:44:9: 'YEAR' - { - match("YEAR"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__67" - - // $ANTLR start "T__68" - public final void mT__68() throws RecognitionException { - try { - int _type = T__68; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:45:7: ( 'MONTH' ) - // JPA.g:45:9: 'MONTH' - { - match("MONTH"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__68" - - // $ANTLR start "T__69" - public final void mT__69() throws RecognitionException { - try { - int _type = T__69; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:46:7: ( 'DAY' ) - // JPA.g:46:9: 'DAY' - { - match("DAY"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__69" - - // $ANTLR start "T__70" - public final void mT__70() throws RecognitionException { - try { - int _type = T__70; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:47:7: ( 'HOUR' ) - // JPA.g:47:9: 'HOUR' - { - match("HOUR"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__70" - - // $ANTLR start "T__71" - public final void mT__71() throws RecognitionException { - try { - int _type = T__71; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:48:7: ( 'MINUTE' ) - // JPA.g:48:9: 'MINUTE' - { - match("MINUTE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__71" - - // $ANTLR start "T__72" - public final void mT__72() throws RecognitionException { - try { - int _type = T__72; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:49:7: ( 'SECOND' ) - // JPA.g:49:9: 'SECOND' - { - match("SECOND"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__72" - - // $ANTLR start "T__73" - public final void mT__73() throws RecognitionException { - try { - int _type = T__73; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:50:7: ( '@DATEBEFORE' ) - // JPA.g:50:9: '@DATEBEFORE' - { - match("@DATEBEFORE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__73" - - // $ANTLR start "T__74" - public final void mT__74() throws RecognitionException { - try { - int _type = T__74; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:51:7: ( '@DATEAFTER' ) - // JPA.g:51:9: '@DATEAFTER' - { - match("@DATEAFTER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__74" - - // $ANTLR start "T__75" - public final void mT__75() throws RecognitionException { - try { - int _type = T__75; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:52:7: ( '@DATEEQUALS' ) - // JPA.g:52:9: '@DATEEQUALS' - { - match("@DATEEQUALS"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__75" - - // $ANTLR start "T__76" - public final void mT__76() throws RecognitionException { - try { - int _type = T__76; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:53:7: ( '@TODAY' ) - // JPA.g:53:9: '@TODAY' - { - match("@TODAY"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__76" - - // $ANTLR start "T__77" - public final void mT__77() throws RecognitionException { - try { - int _type = T__77; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:54:7: ( 'BETWEEN' ) - // JPA.g:54:9: 'BETWEEN' - { - match("BETWEEN"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__77" - - // $ANTLR start "T__78" - public final void mT__78() throws RecognitionException { - try { - int _type = T__78; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:55:7: ( 'LIKE' ) - // JPA.g:55:9: 'LIKE' - { - match("LIKE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__78" - - // $ANTLR start "T__79" - public final void mT__79() throws RecognitionException { - try { - int _type = T__79; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:56:7: ( 'ESCAPE' ) - // JPA.g:56:9: 'ESCAPE' - { - match("ESCAPE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__79" - - // $ANTLR start "T__80" - public final void mT__80() throws RecognitionException { - try { - int _type = T__80; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:57:7: ( 'IS' ) - // JPA.g:57:9: 'IS' - { - match("IS"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__80" - - // $ANTLR start "T__81" - public final void mT__81() throws RecognitionException { - try { - int _type = T__81; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:58:7: ( 'NULL' ) - // JPA.g:58:9: 'NULL' - { - match("NULL"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__81" - - // $ANTLR start "T__82" - public final void mT__82() throws RecognitionException { - try { - int _type = T__82; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:59:7: ( 'EMPTY' ) - // JPA.g:59:9: 'EMPTY' - { - match("EMPTY"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__82" - - // $ANTLR start "T__83" - public final void mT__83() throws RecognitionException { - try { - int _type = T__83; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:60:7: ( 'MEMBER' ) - // JPA.g:60:9: 'MEMBER' - { - match("MEMBER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__83" - - // $ANTLR start "T__84" - public final void mT__84() throws RecognitionException { - try { - int _type = T__84; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:61:7: ( 'OF' ) - // JPA.g:61:9: 'OF' - { - match("OF"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__84" - - // $ANTLR start "T__85" - public final void mT__85() throws RecognitionException { - try { - int _type = T__85; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:62:7: ( 'EXISTS' ) - // JPA.g:62:9: 'EXISTS' - { - match("EXISTS"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__85" - - // $ANTLR start "T__86" - public final void mT__86() throws RecognitionException { - try { - int _type = T__86; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:63:7: ( 'ALL' ) - // JPA.g:63:9: 'ALL' - { - match("ALL"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__86" - - // $ANTLR start "T__87" - public final void mT__87() throws RecognitionException { - try { - int _type = T__87; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:64:7: ( 'ANY' ) - // JPA.g:64:9: 'ANY' - { - match("ANY"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__87" - - // $ANTLR start "T__88" - public final void mT__88() throws RecognitionException { - try { - int _type = T__88; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:65:7: ( 'SOME' ) - // JPA.g:65:9: 'SOME' - { - match("SOME"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__88" - - // $ANTLR start "T__89" - public final void mT__89() throws RecognitionException { - try { - int _type = T__89; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:66:7: ( '=' ) - // JPA.g:66:9: '=' - { - match('='); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__89" - - // $ANTLR start "T__90" - public final void mT__90() throws RecognitionException { - try { - int _type = T__90; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:67:7: ( '<>' ) - // JPA.g:67:9: '<>' - { - match("<>"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__90" - - // $ANTLR start "T__91" - public final void mT__91() throws RecognitionException { - try { - int _type = T__91; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:68:7: ( '>' ) - // JPA.g:68:9: '>' - { - match('>'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__91" - - // $ANTLR start "T__92" - public final void mT__92() throws RecognitionException { - try { - int _type = T__92; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:69:7: ( '>=' ) - // JPA.g:69:9: '>=' - { - match(">="); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__92" - - // $ANTLR start "T__93" - public final void mT__93() throws RecognitionException { - try { - int _type = T__93; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:70:7: ( '<' ) - // JPA.g:70:9: '<' - { - match('<'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__93" - - // $ANTLR start "T__94" - public final void mT__94() throws RecognitionException { - try { - int _type = T__94; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:71:7: ( '<=' ) - // JPA.g:71:9: '<=' - { - match("<="); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__94" - - // $ANTLR start "T__95" - public final void mT__95() throws RecognitionException { - try { - int _type = T__95; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:72:7: ( '*' ) - // JPA.g:72:9: '*' - { - match('*'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__95" - - // $ANTLR start "T__96" - public final void mT__96() throws RecognitionException { - try { - int _type = T__96; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:73:7: ( '/' ) - // JPA.g:73:9: '/' - { - match('/'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__96" - - // $ANTLR start "T__97" - public final void mT__97() throws RecognitionException { - try { - int _type = T__97; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:74:7: ( 'LENGTH' ) - // JPA.g:74:9: 'LENGTH' - { - match("LENGTH"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__97" - - // $ANTLR start "T__98" - public final void mT__98() throws RecognitionException { - try { - int _type = T__98; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:75:7: ( 'LOCATE' ) - // JPA.g:75:9: 'LOCATE' - { - match("LOCATE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__98" - - // $ANTLR start "T__99" - public final void mT__99() throws RecognitionException { - try { - int _type = T__99; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:76:7: ( 'ABS' ) - // JPA.g:76:9: 'ABS' - { - match("ABS"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__99" - - // $ANTLR start "T__100" - public final void mT__100() throws RecognitionException { - try { - int _type = T__100; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:77:8: ( 'SQRT' ) - // JPA.g:77:10: 'SQRT' - { - match("SQRT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__100" - - // $ANTLR start "T__101" - public final void mT__101() throws RecognitionException { - try { - int _type = T__101; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:78:8: ( 'MOD' ) - // JPA.g:78:10: 'MOD' - { - match("MOD"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__101" - - // $ANTLR start "T__102" - public final void mT__102() throws RecognitionException { - try { - int _type = T__102; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:79:8: ( 'SIZE' ) - // JPA.g:79:10: 'SIZE' - { - match("SIZE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__102" - - // $ANTLR start "T__103" - public final void mT__103() throws RecognitionException { - try { - int _type = T__103; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:80:8: ( 'CURRENT_DATE' ) - // JPA.g:80:10: 'CURRENT_DATE' - { - match("CURRENT_DATE"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__103" - - // $ANTLR start "T__104" - public final void mT__104() throws RecognitionException { - try { - int _type = T__104; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:81:8: ( 'CURRENT_TIME' ) - // JPA.g:81:10: 'CURRENT_TIME' - { - match("CURRENT_TIME"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__104" - - // $ANTLR start "T__105" - public final void mT__105() throws RecognitionException { - try { - int _type = T__105; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:82:8: ( 'CURRENT_TIMESTAMP' ) - // JPA.g:82:10: 'CURRENT_TIMESTAMP' - { - match("CURRENT_TIMESTAMP"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__105" - - // $ANTLR start "T__106" - public final void mT__106() throws RecognitionException { - try { - int _type = T__106; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:83:8: ( 'CONCAT' ) - // JPA.g:83:10: 'CONCAT' - { - match("CONCAT"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__106" - - // $ANTLR start "T__107" - public final void mT__107() throws RecognitionException { - try { - int _type = T__107; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:84:8: ( 'SUBSTRING' ) - // JPA.g:84:10: 'SUBSTRING' - { - match("SUBSTRING"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__107" - - // $ANTLR start "T__108" - public final void mT__108() throws RecognitionException { - try { - int _type = T__108; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:85:8: ( 'TRIM' ) - // JPA.g:85:10: 'TRIM' - { - match("TRIM"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__108" - - // $ANTLR start "T__109" - public final void mT__109() throws RecognitionException { - try { - int _type = T__109; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:86:8: ( 'LOWER' ) - // JPA.g:86:10: 'LOWER' - { - match("LOWER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__109" - - // $ANTLR start "T__110" - public final void mT__110() throws RecognitionException { - try { - int _type = T__110; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:87:8: ( 'UPPER' ) - // JPA.g:87:10: 'UPPER' - { - match("UPPER"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__110" - - // $ANTLR start "T__111" - public final void mT__111() throws RecognitionException { - try { - int _type = T__111; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:88:8: ( 'LEADING' ) - // JPA.g:88:10: 'LEADING' - { - match("LEADING"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__111" - - // $ANTLR start "T__112" - public final void mT__112() throws RecognitionException { - try { - int _type = T__112; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:89:8: ( 'TRAILING' ) - // JPA.g:89:10: 'TRAILING' - { - match("TRAILING"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__112" - - // $ANTLR start "T__113" - public final void mT__113() throws RecognitionException { - try { - int _type = T__113; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:90:8: ( 'BOTH' ) - // JPA.g:90:10: 'BOTH' - { - match("BOTH"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__113" - - // $ANTLR start "T__114" - public final void mT__114() throws RecognitionException { - try { - int _type = T__114; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:91:8: ( '0x' ) - // JPA.g:91:10: '0x' - { - match("0x"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__114" - - // $ANTLR start "T__115" - public final void mT__115() throws RecognitionException { - try { - int _type = T__115; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:92:8: ( '?' ) - // JPA.g:92:10: '?' - { - match('?'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__115" - - // $ANTLR start "T__116" - public final void mT__116() throws RecognitionException { - try { - int _type = T__116; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:93:8: ( '${' ) - // JPA.g:93:10: '${' - { - match("${"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__116" - - // $ANTLR start "T__117" - public final void mT__117() throws RecognitionException { - try { - int _type = T__117; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:94:8: ( '}' ) - // JPA.g:94:10: '}' - { - match('}'); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__117" - - // $ANTLR start "T__118" - public final void mT__118() throws RecognitionException { - try { - int _type = T__118; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:95:8: ( 'true' ) - // JPA.g:95:10: 'true' - { - match("true"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__118" - - // $ANTLR start "T__119" - public final void mT__119() throws RecognitionException { - try { - int _type = T__119; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:96:8: ( 'false' ) - // JPA.g:96:10: 'false' - { - match("false"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "T__119" - - // $ANTLR start "TRIM_CHARACTER" - public final void mTRIM_CHARACTER() throws RecognitionException { - try { - int _type = TRIM_CHARACTER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:450:5: ( '\\'.\\'' ) - // JPA.g:450:7: '\\'.\\'' - { - match("'.'"); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "TRIM_CHARACTER" - - // $ANTLR start "STRINGLITERAL" - public final void mSTRINGLITERAL() throws RecognitionException { - try { - int _type = STRINGLITERAL; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:453:5: ( '\\'' (~ ( '\\'' | '\"' ) )* '\\'' ) - // JPA.g:453:7: '\\'' (~ ( '\\'' | '\"' ) )* '\\'' - { - match('\''); - // JPA.g:453:12: (~ ( '\\'' | '\"' ) )* - loop1: - do { - int alt1=2; - int LA1_0 = input.LA(1); - - if ( ((LA1_0>='\u0000' && LA1_0<='!')||(LA1_0>='#' && LA1_0<='&')||(LA1_0>='(' && LA1_0<='\uFFFF')) ) { - alt1=1; - } - - - switch (alt1) { - case 1 : - // JPA.g:453:13: ~ ( '\\'' | '\"' ) - { - if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='\uFFFF') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - break; - - default : - break loop1; - } - } while (true); - - match('\''); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "STRINGLITERAL" - - // $ANTLR start "WORD" - public final void mWORD() throws RecognitionException { - try { - int _type = WORD; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:456:5: ( ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ) - // JPA.g:456:7: ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* - { - if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - // JPA.g:456:31: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* - loop2: - do { - int alt2=2; - int LA2_0 = input.LA(1); - - if ( (LA2_0=='$'||(LA2_0>='0' && LA2_0<='9')||(LA2_0>='A' && LA2_0<='Z')||LA2_0=='_'||(LA2_0>='a' && LA2_0<='z')) ) { - alt2=1; - } - - - switch (alt2) { - case 1 : - // JPA.g: - { - if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - break; - - default : - break loop2; - } - } while (true); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "WORD" - - // $ANTLR start "RUSSIAN_SYMBOLS" - public final void mRUSSIAN_SYMBOLS() throws RecognitionException { - try { - int _type = RUSSIAN_SYMBOLS; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:459:5: ( ( '\\u0400' .. '\\u04FF' | '\\u0500' .. '\\u052F' ) ) - // JPA.g:459:7: ( '\\u0400' .. '\\u04FF' | '\\u0500' .. '\\u052F' ) - { - if ( (input.LA(1)>='\u0400' && input.LA(1)<='\u052F') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol"); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "RUSSIAN_SYMBOLS" - - // $ANTLR start "NAMED_PARAMETER" - public final void mNAMED_PARAMETER() throws RecognitionException { - try { - int _type = NAMED_PARAMETER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:462:5: ( ':' ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* ) - // JPA.g:462:7: ':' ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* - { - match(':'); - if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - // JPA.g:462:34: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* - loop3: - do { - int alt3=2; - int LA3_0 = input.LA(1); - - if ( (LA3_0=='$'||(LA3_0>='0' && LA3_0<='9')||(LA3_0>='A' && LA3_0<='Z')||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')) ) { - alt3=1; - } - - - switch (alt3) { - case 1 : - // JPA.g: - { - if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - break; - - default : - break loop3; - } - } while (true); - - // JPA.g:462:72: ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* - loop5: - do { - int alt5=2; - int LA5_0 = input.LA(1); - - if ( (LA5_0=='.') ) { - alt5=1; - } - - - switch (alt5) { - case 1 : - // JPA.g:462:73: ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ - { - // JPA.g:462:73: ( '.' ) - // JPA.g:462:74: '.' - { - match('.'); - - } - - // JPA.g:462:79: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ - int cnt4=0; - loop4: - do { - int alt4=2; - int LA4_0 = input.LA(1); - - if ( (LA4_0=='$'||(LA4_0>='0' && LA4_0<='9')||(LA4_0>='A' && LA4_0<='Z')||LA4_0=='_'||(LA4_0>='a' && LA4_0<='z')) ) { - alt4=1; - } - - - switch (alt4) { - case 1 : - // JPA.g: - { - if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - break; - - default : - if ( cnt4 >= 1 ) break loop4; - EarlyExitException eee = - new EarlyExitException(4, input); - throw eee; - } - cnt4++; - } while (true); - - - } - break; - - default : - break loop5; - } - } while (true); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "NAMED_PARAMETER" - - // $ANTLR start "WS" - public final void mWS() throws RecognitionException { - try { - int _type = WS; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:464:5: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) ) - // JPA.g:464:7: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) - { - if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||(input.LA(1)>='\f' && input.LA(1)<='\r')||input.LA(1)==' ' ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - _channel=HIDDEN; - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "WS" - - // $ANTLR start "COMMENT" - public final void mCOMMENT() throws RecognitionException { - try { - int _type = COMMENT; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:468:5: ( '/*' ( . )* '*/' ) - // JPA.g:468:7: '/*' ( . )* '*/' - { - match("/*"); - - // JPA.g:468:12: ( . )* - loop6: - do { - int alt6=2; - int LA6_0 = input.LA(1); - - if ( (LA6_0=='*') ) { - int LA6_1 = input.LA(2); - - if ( (LA6_1=='/') ) { - alt6=2; - } - else if ( ((LA6_1>='\u0000' && LA6_1<='.')||(LA6_1>='0' && LA6_1<='\uFFFF')) ) { - alt6=1; - } - - - } - else if ( ((LA6_0>='\u0000' && LA6_0<=')')||(LA6_0>='+' && LA6_0<='\uFFFF')) ) { - alt6=1; - } - - - switch (alt6) { - case 1 : - // JPA.g:468:12: . - { - matchAny(); - - } - break; - - default : - break loop6; - } - } while (true); - - match("*/"); - - _channel=HIDDEN; - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "COMMENT" - - // $ANTLR start "LINE_COMMENT" - public final void mLINE_COMMENT() throws RecognitionException { - try { - int _type = LINE_COMMENT; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:471:5: ( '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' ) - // JPA.g:471:7: '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' - { - match("//"); - - // JPA.g:471:12: (~ ( '\\n' | '\\r' ) )* - loop7: - do { - int alt7=2; - int LA7_0 = input.LA(1); - - if ( ((LA7_0>='\u0000' && LA7_0<='\t')||(LA7_0>='\u000B' && LA7_0<='\f')||(LA7_0>='\u000E' && LA7_0<='\uFFFF')) ) { - alt7=1; - } - - - switch (alt7) { - case 1 : - // JPA.g:471:12: ~ ( '\\n' | '\\r' ) - { - if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='\uFFFF') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - break; - - default : - break loop7; - } - } while (true); - - // JPA.g:471:26: ( '\\r' )? - int alt8=2; - int LA8_0 = input.LA(1); - - if ( (LA8_0=='\r') ) { - alt8=1; - } - switch (alt8) { - case 1 : - // JPA.g:471:26: '\\r' - { - match('\r'); - - } - break; - - } - - match('\n'); - _channel=HIDDEN; - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "LINE_COMMENT" - - // $ANTLR start "ESCAPE_CHARACTER" - public final void mESCAPE_CHARACTER() throws RecognitionException { - try { - int _type = ESCAPE_CHARACTER; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:474:5: ( '\\'' (~ ( '\\'' | '\\\\' ) ) '\\'' ) - // JPA.g:474:7: '\\'' (~ ( '\\'' | '\\\\' ) ) '\\'' - { - match('\''); - // JPA.g:474:12: (~ ( '\\'' | '\\\\' ) ) - // JPA.g:474:13: ~ ( '\\'' | '\\\\' ) - { - if ( (input.LA(1)>='\u0000' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) { - input.consume(); - - } - else { - MismatchedSetException mse = new MismatchedSetException(null,input); - recover(mse); - throw mse;} - - - } - - match('\''); - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "ESCAPE_CHARACTER" - - // $ANTLR start "INT_NUMERAL" - public final void mINT_NUMERAL() throws RecognitionException { - try { - int _type = INT_NUMERAL; - int _channel = DEFAULT_TOKEN_CHANNEL; - // JPA.g:477:5: ( ( '0' .. '9' )+ ) - // JPA.g:477:7: ( '0' .. '9' )+ - { - // JPA.g:477:7: ( '0' .. '9' )+ - int cnt9=0; - loop9: - do { - int alt9=2; - int LA9_0 = input.LA(1); - - if ( ((LA9_0>='0' && LA9_0<='9')) ) { - alt9=1; - } - - - switch (alt9) { - case 1 : - // JPA.g:477:8: '0' .. '9' - { - matchRange('0','9'); - - } - break; - - default : - if ( cnt9 >= 1 ) break loop9; - EarlyExitException eee = - new EarlyExitException(9, input); - throw eee; - } - cnt9++; - } while (true); - - - } - - state.type = _type; - state.channel = _channel; - } - finally { - } - } - // $ANTLR end "INT_NUMERAL" - - public void mTokens() throws RecognitionException { - // JPA.g:1:8: ( HAVING | ASC | DESC | AVG | MAX | MIN | SUM | COUNT | OR | AND | LPAREN | RPAREN | DISTINCT | LEFT | OUTER | INNER | JOIN | FETCH | ORDER | GROUP | BY | T__52 | T__53 | T__54 | T__55 | T__56 | T__57 | T__58 | T__59 | T__60 | T__61 | T__62 | T__63 | T__64 | T__65 | T__66 | T__67 | T__68 | T__69 | T__70 | T__71 | T__72 | T__73 | T__74 | T__75 | T__76 | T__77 | T__78 | T__79 | T__80 | T__81 | T__82 | T__83 | T__84 | T__85 | T__86 | T__87 | T__88 | T__89 | T__90 | T__91 | T__92 | T__93 | T__94 | T__95 | T__96 | T__97 | T__98 | T__99 | T__100 | T__101 | T__102 | T__103 | T__104 | T__105 | T__106 | T__107 | T__108 | T__109 | T__110 | T__111 | T__112 | T__113 | T__114 | T__115 | T__116 | T__117 | T__118 | T__119 | TRIM_CHARACTER | STRINGLITERAL | WORD | RUSSIAN_SYMBOLS | NAMED_PARAMETER | WS | COMMENT | LINE_COMMENT | ESCAPE_CHARACTER | INT_NUMERAL ) - int alt10=99; - alt10 = dfa10.predict(input); - switch (alt10) { - case 1 : - // JPA.g:1:10: HAVING - { - mHAVING(); - - } - break; - case 2 : - // JPA.g:1:17: ASC - { - mASC(); - - } - break; - case 3 : - // JPA.g:1:21: DESC - { - mDESC(); - - } - break; - case 4 : - // JPA.g:1:26: AVG - { - mAVG(); - - } - break; - case 5 : - // JPA.g:1:30: MAX - { - mMAX(); - - } - break; - case 6 : - // JPA.g:1:34: MIN - { - mMIN(); - - } - break; - case 7 : - // JPA.g:1:38: SUM - { - mSUM(); - - } - break; - case 8 : - // JPA.g:1:42: COUNT - { - mCOUNT(); - - } - break; - case 9 : - // JPA.g:1:48: OR - { - mOR(); - - } - break; - case 10 : - // JPA.g:1:51: AND - { - mAND(); - - } - break; - case 11 : - // JPA.g:1:55: LPAREN - { - mLPAREN(); - - } - break; - case 12 : - // JPA.g:1:62: RPAREN - { - mRPAREN(); - - } - break; - case 13 : - // JPA.g:1:69: DISTINCT - { - mDISTINCT(); - - } - break; - case 14 : - // JPA.g:1:78: LEFT - { - mLEFT(); - - } - break; - case 15 : - // JPA.g:1:83: OUTER - { - mOUTER(); - - } - break; - case 16 : - // JPA.g:1:89: INNER - { - mINNER(); - - } - break; - case 17 : - // JPA.g:1:95: JOIN - { - mJOIN(); - - } - break; - case 18 : - // JPA.g:1:100: FETCH - { - mFETCH(); - - } - break; - case 19 : - // JPA.g:1:106: ORDER - { - mORDER(); - - } - break; - case 20 : - // JPA.g:1:112: GROUP - { - mGROUP(); - - } - break; - case 21 : - // JPA.g:1:118: BY - { - mBY(); - - } - break; - case 22 : - // JPA.g:1:121: T__52 - { - mT__52(); - - } - break; - case 23 : - // JPA.g:1:127: T__53 - { - mT__53(); - - } - break; - case 24 : - // JPA.g:1:133: T__54 - { - mT__54(); - - } - break; - case 25 : - // JPA.g:1:139: T__55 - { - mT__55(); - - } - break; - case 26 : - // JPA.g:1:145: T__56 - { - mT__56(); - - } - break; - case 27 : - // JPA.g:1:151: T__57 - { - mT__57(); - - } - break; - case 28 : - // JPA.g:1:157: T__58 - { - mT__58(); - - } - break; - case 29 : - // JPA.g:1:163: T__59 - { - mT__59(); - - } - break; - case 30 : - // JPA.g:1:169: T__60 - { - mT__60(); - - } - break; - case 31 : - // JPA.g:1:175: T__61 - { - mT__61(); - - } - break; - case 32 : - // JPA.g:1:181: T__62 - { - mT__62(); - - } - break; - case 33 : - // JPA.g:1:187: T__63 - { - mT__63(); - - } - break; - case 34 : - // JPA.g:1:193: T__64 - { - mT__64(); - - } - break; - case 35 : - // JPA.g:1:199: T__65 - { - mT__65(); - - } - break; - case 36 : - // JPA.g:1:205: T__66 - { - mT__66(); - - } - break; - case 37 : - // JPA.g:1:211: T__67 - { - mT__67(); - - } - break; - case 38 : - // JPA.g:1:217: T__68 - { - mT__68(); - - } - break; - case 39 : - // JPA.g:1:223: T__69 - { - mT__69(); - - } - break; - case 40 : - // JPA.g:1:229: T__70 - { - mT__70(); - - } - break; - case 41 : - // JPA.g:1:235: T__71 - { - mT__71(); - - } - break; - case 42 : - // JPA.g:1:241: T__72 - { - mT__72(); - - } - break; - case 43 : - // JPA.g:1:247: T__73 - { - mT__73(); - - } - break; - case 44 : - // JPA.g:1:253: T__74 - { - mT__74(); - - } - break; - case 45 : - // JPA.g:1:259: T__75 - { - mT__75(); - - } - break; - case 46 : - // JPA.g:1:265: T__76 - { - mT__76(); - - } - break; - case 47 : - // JPA.g:1:271: T__77 - { - mT__77(); - - } - break; - case 48 : - // JPA.g:1:277: T__78 - { - mT__78(); - - } - break; - case 49 : - // JPA.g:1:283: T__79 - { - mT__79(); - - } - break; - case 50 : - // JPA.g:1:289: T__80 - { - mT__80(); - - } - break; - case 51 : - // JPA.g:1:295: T__81 - { - mT__81(); - - } - break; - case 52 : - // JPA.g:1:301: T__82 - { - mT__82(); - - } - break; - case 53 : - // JPA.g:1:307: T__83 - { - mT__83(); - - } - break; - case 54 : - // JPA.g:1:313: T__84 - { - mT__84(); - - } - break; - case 55 : - // JPA.g:1:319: T__85 - { - mT__85(); - - } - break; - case 56 : - // JPA.g:1:325: T__86 - { - mT__86(); - - } - break; - case 57 : - // JPA.g:1:331: T__87 - { - mT__87(); - - } - break; - case 58 : - // JPA.g:1:337: T__88 - { - mT__88(); - - } - break; - case 59 : - // JPA.g:1:343: T__89 - { - mT__89(); - - } - break; - case 60 : - // JPA.g:1:349: T__90 - { - mT__90(); - - } - break; - case 61 : - // JPA.g:1:355: T__91 - { - mT__91(); - - } - break; - case 62 : - // JPA.g:1:361: T__92 - { - mT__92(); - - } - break; - case 63 : - // JPA.g:1:367: T__93 - { - mT__93(); - - } - break; - case 64 : - // JPA.g:1:373: T__94 - { - mT__94(); - - } - break; - case 65 : - // JPA.g:1:379: T__95 - { - mT__95(); - - } - break; - case 66 : - // JPA.g:1:385: T__96 - { - mT__96(); - - } - break; - case 67 : - // JPA.g:1:391: T__97 - { - mT__97(); - - } - break; - case 68 : - // JPA.g:1:397: T__98 - { - mT__98(); - - } - break; - case 69 : - // JPA.g:1:403: T__99 - { - mT__99(); - - } - break; - case 70 : - // JPA.g:1:409: T__100 - { - mT__100(); - - } - break; - case 71 : - // JPA.g:1:416: T__101 - { - mT__101(); - - } - break; - case 72 : - // JPA.g:1:423: T__102 - { - mT__102(); - - } - break; - case 73 : - // JPA.g:1:430: T__103 - { - mT__103(); - - } - break; - case 74 : - // JPA.g:1:437: T__104 - { - mT__104(); - - } - break; - case 75 : - // JPA.g:1:444: T__105 - { - mT__105(); - - } - break; - case 76 : - // JPA.g:1:451: T__106 - { - mT__106(); - - } - break; - case 77 : - // JPA.g:1:458: T__107 - { - mT__107(); - - } - break; - case 78 : - // JPA.g:1:465: T__108 - { - mT__108(); - - } - break; - case 79 : - // JPA.g:1:472: T__109 - { - mT__109(); - - } - break; - case 80 : - // JPA.g:1:479: T__110 - { - mT__110(); - - } - break; - case 81 : - // JPA.g:1:486: T__111 - { - mT__111(); - - } - break; - case 82 : - // JPA.g:1:493: T__112 - { - mT__112(); - - } - break; - case 83 : - // JPA.g:1:500: T__113 - { - mT__113(); - - } - break; - case 84 : - // JPA.g:1:507: T__114 - { - mT__114(); - - } - break; - case 85 : - // JPA.g:1:514: T__115 - { - mT__115(); - - } - break; - case 86 : - // JPA.g:1:521: T__116 - { - mT__116(); - - } - break; - case 87 : - // JPA.g:1:528: T__117 - { - mT__117(); - - } - break; - case 88 : - // JPA.g:1:535: T__118 - { - mT__118(); - - } - break; - case 89 : - // JPA.g:1:542: T__119 - { - mT__119(); - - } - break; - case 90 : - // JPA.g:1:549: TRIM_CHARACTER - { - mTRIM_CHARACTER(); - - } - break; - case 91 : - // JPA.g:1:564: STRINGLITERAL - { - mSTRINGLITERAL(); - - } - break; - case 92 : - // JPA.g:1:578: WORD - { - mWORD(); - - } - break; - case 93 : - // JPA.g:1:583: RUSSIAN_SYMBOLS - { - mRUSSIAN_SYMBOLS(); - - } - break; - case 94 : - // JPA.g:1:599: NAMED_PARAMETER - { - mNAMED_PARAMETER(); - - } - break; - case 95 : - // JPA.g:1:615: WS - { - mWS(); - - } - break; - case 96 : - // JPA.g:1:618: COMMENT - { - mCOMMENT(); - - } - break; - case 97 : - // JPA.g:1:626: LINE_COMMENT - { - mLINE_COMMENT(); - - } - break; - case 98 : - // JPA.g:1:639: ESCAPE_CHARACTER - { - mESCAPE_CHARACTER(); - - } - break; - case 99 : - // JPA.g:1:656: INT_NUMERAL - { - mINT_NUMERAL(); - - } - break; - - } - - } - - - protected DFA10 dfa10 = new DFA10(this); - static final String DFA10_eotS = - "\1\uffff\7\47\1\106\1\uffff\6\47\2\uffff\2\47\3\uffff\2\47\1\uffff"+ - "\1\140\1\142\1\uffff\1\145\2\47\1\53\3\uffff\2\47\6\uffff\2\47\1"+ - "\162\22\47\1\u008b\2\47\1\u008e\2\uffff\3\47\1\u0096\1\u0097\4\47"+ - "\1\u009c\6\47\3\uffff\4\47\10\uffff\2\47\1\uffff\2\47\4\uffff\2"+ - "\47\1\u00b2\1\uffff\1\u00b3\1\u00b4\1\u00b5\1\u00b6\1\u00b7\2\47"+ - "\1\u00ba\1\u00bb\1\u00bd\1\47\1\u00bf\1\47\1\u00c1\12\47\1\uffff"+ - "\2\47\1\uffff\7\47\2\uffff\4\47\1\uffff\2\47\1\u00db\1\u00dc\1\u00dd"+ - "\2\47\1\uffff\11\47\2\uffff\1\47\1\u00ec\6\uffff\1\u00ed\1\47\2"+ - "\uffff\1\47\1\uffff\1\47\1\uffff\1\47\1\uffff\3\47\1\u00f5\1\u00f6"+ - "\1\u00f7\6\47\1\u00fe\2\47\1\u0101\3\47\1\u0105\1\47\1\u0107\2\47"+ - "\1\u010a\3\uffff\1\u010b\1\47\1\uffff\1\u010e\3\47\1\u0112\2\47"+ - "\1\u0115\1\47\1\uffff\1\47\2\uffff\2\47\1\u011a\4\47\3\uffff\1\u011f"+ - "\2\47\1\u0122\1\u0123\1\47\1\uffff\2\47\1\uffff\1\47\1\u0128\1\u0129"+ - "\1\uffff\1\u012a\1\uffff\1\u012b\1\47\2\uffff\1\u012d\2\uffff\1"+ - "\47\1\u0132\1\47\1\uffff\1\47\1\u0135\1\uffff\1\u0136\1\u0137\1"+ - "\47\1\u0139\1\uffff\1\u013a\1\47\1\u013c\1\u013d\1\uffff\1\u013e"+ - "\1\47\2\uffff\1\u0140\1\u0141\1\47\1\u0143\4\uffff\1\47\4\uffff"+ - "\1\u0145\1\uffff\1\u0146\1\47\3\uffff\1\47\2\uffff\1\47\3\uffff"+ - "\1\47\2\uffff\1\u014b\1\uffff\1\u014c\2\uffff\1\47\1\u014e\2\47"+ - "\2\uffff\1\u0152\1\uffff\1\u0153\2\47\2\uffff\4\47\1\u015a\1\u015c"+ - "\1\uffff\1\47\1\uffff\3\47\1\u0161\1\uffff"; - static final String DFA10_eofS = - "\u0162\uffff"; - static final String DFA10_minS = - "\1\11\1\101\1\102\2\101\1\105\1\117\1\102\1\123\1\uffff\1\105\1"+ - "\116\1\117\1\105\1\122\1\105\2\uffff\1\105\1\110\1\102\2\uffff\1"+ - "\105\1\115\1\uffff\2\75\1\uffff\1\52\1\122\1\120\1\170\3\uffff\1"+ - "\162\1\141\1\0\5\uffff\1\126\1\125\1\44\1\107\1\104\1\114\3\123"+ - "\1\131\1\130\1\116\1\104\1\115\1\102\1\103\1\115\1\122\1\132\1\116"+ - "\1\122\1\44\1\124\1\112\1\44\2\uffff\1\101\1\113\1\103\2\44\1\111"+ - "\1\124\2\117\1\44\2\124\1\127\1\124\1\114\1\105\1\uffff\1\101\1"+ - "\uffff\1\101\1\103\1\120\1\111\10\uffff\1\101\1\120\1\uffff\1\165"+ - "\1\154\2\0\2\uffff\1\111\1\122\1\44\1\uffff\5\44\1\103\1\124\3\44"+ - "\1\124\1\44\1\102\1\44\1\123\1\105\1\117\1\105\1\124\1\105\1\116"+ - "\1\103\1\122\1\105\1\uffff\2\105\1\uffff\1\124\1\107\1\104\1\105"+ - "\1\101\2\105\2\uffff\1\116\1\103\1\115\1\125\1\uffff\1\127\1\110"+ - "\3\44\1\114\1\122\1\124\1\122\1\101\1\124\1\123\1\115\1\111\1\105"+ - "\1\145\1\163\2\uffff\1\116\1\44\6\uffff\1\44\1\111\2\uffff\1\124"+ - "\1\uffff\1\110\1\uffff\1\105\1\uffff\1\124\1\103\1\116\3\44\1\124"+ - "\1\101\1\105\2\122\1\103\1\44\1\124\1\111\1\44\1\124\2\122\1\44"+ - "\1\110\1\44\1\120\1\105\1\44\3\uffff\1\44\2\105\1\44\1\120\1\131"+ - "\1\124\1\44\1\114\1\122\1\44\1\145\1\uffff\1\107\2\uffff\1\116\1"+ - "\105\1\44\2\122\1\124\1\104\3\uffff\1\44\1\124\1\116\2\44\1\124"+ - "\1\uffff\1\110\1\116\1\uffff\1\105\2\44\1\uffff\1\44\1\uffff\1\44"+ - "\1\105\2\uffff\1\44\1\101\1\uffff\1\105\1\44\1\123\1\uffff\1\111"+ - "\1\44\1\uffff\2\44\1\103\1\44\1\uffff\1\44\1\111\2\44\1\uffff\1"+ - "\44\1\124\2\uffff\2\44\1\107\1\44\4\uffff\1\116\4\uffff\1\44\1\uffff"+ - "\1\44\1\116\3\uffff\1\124\2\uffff\1\116\3\uffff\1\137\2\uffff\1"+ - "\44\1\uffff\1\44\2\uffff\1\107\1\44\1\107\1\104\2\uffff\1\44\1\uffff"+ - "\1\44\1\101\1\111\2\uffff\1\124\1\115\2\105\2\44\1\uffff\1\124\1"+ - "\uffff\1\101\1\115\1\120\1\44\1\uffff"; - static final String DFA10_maxS = - "\1\u052f\1\117\1\126\1\111\1\117\3\125\1\123\1\uffff\1\117\1\123"+ - "\1\117\2\122\1\131\2\uffff\1\125\1\110\1\124\2\uffff\1\105\1\130"+ - "\1\uffff\1\76\1\75\1\uffff\1\57\1\122\1\120\1\170\3\uffff\1\162"+ - "\1\141\1\uffff\5\uffff\1\126\1\125\1\172\1\107\1\131\1\114\3\123"+ - "\1\131\1\130\2\116\2\115\1\114\1\115\1\122\1\132\1\125\1\122\1\172"+ - "\1\124\1\112\1\172\2\uffff\1\116\1\113\1\127\2\172\1\111\1\124\2"+ - "\117\1\172\2\124\2\127\1\114\1\105\1\uffff\1\101\1\uffff\1\101\1"+ - "\103\1\120\1\111\10\uffff\1\111\1\120\1\uffff\1\165\1\154\2\uffff"+ - "\2\uffff\1\111\1\122\1\172\1\uffff\5\172\1\103\1\124\3\172\1\124"+ - "\1\172\1\102\1\172\1\123\1\105\1\117\1\105\1\124\1\105\1\116\1\103"+ - "\1\122\1\105\1\uffff\2\105\1\uffff\1\124\1\107\1\104\1\105\1\101"+ - "\2\105\2\uffff\1\116\1\103\1\115\1\125\1\uffff\1\127\1\110\3\172"+ - "\1\114\1\122\1\124\1\122\1\101\1\124\1\123\1\115\1\111\1\105\1\145"+ - "\1\163\2\uffff\1\116\1\172\6\uffff\1\172\1\111\2\uffff\1\124\1\uffff"+ - "\1\110\1\uffff\1\105\1\uffff\1\124\1\103\1\116\3\172\1\124\1\101"+ - "\1\105\2\122\1\103\1\172\1\124\1\111\1\172\1\124\2\122\1\172\1\110"+ - "\1\172\1\120\1\105\1\172\3\uffff\1\172\2\105\1\172\1\120\1\131\1"+ - "\124\1\172\1\114\1\122\1\172\1\145\1\uffff\1\107\2\uffff\1\116\1"+ - "\105\1\172\2\122\1\124\1\104\3\uffff\1\172\1\124\1\116\2\172\1\124"+ - "\1\uffff\1\110\1\116\1\uffff\1\105\2\172\1\uffff\1\172\1\uffff\1"+ - "\172\1\105\2\uffff\1\172\1\105\1\uffff\1\105\1\172\1\123\1\uffff"+ - "\1\111\1\172\1\uffff\2\172\1\103\1\172\1\uffff\1\172\1\111\2\172"+ - "\1\uffff\1\172\1\124\2\uffff\2\172\1\107\1\172\4\uffff\1\116\4\uffff"+ - "\1\172\1\uffff\1\172\1\116\3\uffff\1\124\2\uffff\1\116\3\uffff\1"+ - "\137\2\uffff\1\172\1\uffff\1\172\2\uffff\1\107\1\172\1\107\1\124"+ - "\2\uffff\1\172\1\uffff\1\172\1\101\1\111\2\uffff\1\124\1\115\2\105"+ - "\2\172\1\uffff\1\124\1\uffff\1\101\1\115\1\120\1\172\1\uffff"; - static final String DFA10_acceptS = - "\11\uffff\1\14\6\uffff\1\30\1\33\3\uffff\1\43\1\44\2\uffff\1\73"+ - "\2\uffff\1\101\4\uffff\1\125\1\126\1\127\3\uffff\1\134\1\135\1\136"+ - "\1\137\1\143\31\uffff\1\32\1\13\20\uffff\1\41\1\uffff\1\56\4\uffff"+ - "\1\74\1\100\1\77\1\76\1\75\1\140\1\141\1\102\2\uffff\1\124\4\uffff"+ - "\1\142\1\133\3\uffff\1\31\30\uffff\1\11\2\uffff\1\66\7\uffff\1\34"+ - "\1\62\4\uffff\1\25\21\uffff\1\132\1\133\2\uffff\1\2\1\4\1\12\1\71"+ - "\1\70\1\105\2\uffff\1\47\1\5\1\uffff\1\6\1\uffff\1\107\1\uffff\1"+ - "\7\31\uffff\1\36\1\40\1\42\14\uffff\1\132\1\uffff\1\50\1\3\7\uffff"+ - "\1\72\1\106\1\110\6\uffff\1\16\2\uffff\1\60\3\uffff\1\21\1\uffff"+ - "\1\27\2\uffff\1\123\1\63\2\uffff\1\45\3\uffff\1\116\2\uffff\1\130"+ - "\4\uffff\1\46\4\uffff\1\10\2\uffff\1\23\1\17\4\uffff\1\117\1\20"+ - "\1\22\1\24\1\uffff\1\37\1\53\1\54\1\55\1\uffff\1\64\2\uffff\1\120"+ - "\1\131\1\1\1\uffff\1\51\1\65\1\uffff\1\26\1\52\1\114\1\uffff\1\35"+ - "\1\103\1\uffff\1\104\1\uffff\1\61\1\67\4\uffff\1\121\1\57\1\uffff"+ - "\1\15\3\uffff\1\122\1\115\6\uffff\1\111\1\uffff\1\112\4\uffff\1"+ - "\113"; - static final String DFA10_specialS = - "\46\uffff\1\1\104\uffff\1\2\1\0\u00f5\uffff}>"; - static final String[] DFA10_transitionS = { - "\2\52\1\uffff\2\52\22\uffff\1\52\3\uffff\1\42\2\uffff\1\46"+ - "\1\10\1\11\1\34\1\25\1\20\1\26\1\21\1\35\1\40\11\53\1\51\1\uffff"+ - "\1\32\1\31\1\33\1\41\1\24\1\2\1\17\1\6\1\3\1\30\1\15\1\16\1"+ - "\1\1\13\1\14\1\47\1\12\1\4\1\22\1\7\3\47\1\5\1\36\1\37\1\47"+ - "\1\23\1\47\1\27\1\47\4\uffff\1\47\1\uffff\5\47\1\45\15\47\1"+ - "\44\6\47\2\uffff\1\43\u0382\uffff\u0130\50", - "\1\54\15\uffff\1\55", - "\1\62\11\uffff\1\61\1\uffff\1\60\4\uffff\1\56\2\uffff\1\57", - "\1\65\3\uffff\1\63\3\uffff\1\64", - "\1\66\3\uffff\1\71\3\uffff\1\67\5\uffff\1\70", - "\1\73\3\uffff\1\76\5\uffff\1\74\1\uffff\1\75\3\uffff\1\72", - "\1\77\5\uffff\1\100", - "\1\103\3\uffff\1\104\13\uffff\1\101\2\uffff\1\102", - "\1\105", - "", - "\1\107\3\uffff\1\110\5\uffff\1\111", - "\1\112\4\uffff\1\113", - "\1\114", - "\1\115\14\uffff\1\116", - "\1\117", - "\1\121\11\uffff\1\122\11\uffff\1\120", - "", - "", - "\1\123\11\uffff\1\124\5\uffff\1\125", - "\1\126", - "\1\127\1\uffff\1\130\17\uffff\1\131", - "", - "", - "\1\132", - "\1\134\5\uffff\1\133\4\uffff\1\135", - "", - "\1\137\1\136", - "\1\141", - "", - "\1\143\4\uffff\1\144", - "\1\146", - "\1\147", - "\1\150", - "", - "", - "", - "\1\151", - "\1\152", - "\42\154\1\155\4\154\1\156\6\154\1\153\55\154\1\156\uffa3\154", - "", - "", - "", - "", - "", - "\1\157", - "\1\160", - "\1\47\13\uffff\12\47\7\uffff\2\47\1\161\27\47\4\uffff\1\47"+ - "\1\uffff\32\47", - "\1\163", - "\1\164\24\uffff\1\165", - "\1\166", - "\1\167", - "\1\170", - "\1\171", - "\1\172", - "\1\173", - "\1\174", - "\1\176\11\uffff\1\175", - "\1\177", - "\1\u0081\12\uffff\1\u0080", - "\1\u0083\10\uffff\1\u0082", - "\1\u0084", - "\1\u0085", - "\1\u0086", - "\1\u0088\6\uffff\1\u0087", - "\1\u0089", - "\1\47\13\uffff\12\47\7\uffff\3\47\1\u008a\26\47\4\uffff\1"+ - "\47\1\uffff\32\47", - "\1\u008c", - "\1\u008d", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "", - "\1\u0091\4\uffff\1\u008f\7\uffff\1\u0090", - "\1\u0092", - "\1\u0093\23\uffff\1\u0094", - "\1\47\13\uffff\12\47\7\uffff\15\47\1\u0095\14\47\4\uffff\1"+ - "\47\1\uffff\32\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0098", - "\1\u0099", - "\1\u009a", - "\1\u009b", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u009d", - "\1\u009e", - "\1\u009f", - "\1\u00a0\2\uffff\1\u00a1", - "\1\u00a2", - "\1\u00a3", - "", - "\1\u00a4", - "", - "\1\u00a5", - "\1\u00a6", - "\1\u00a7", - "\1\u00a8", - "", - "", - "", - "", - "", - "", - "", - "", - "\1\u00aa\7\uffff\1\u00a9", - "\1\u00ab", - "", - "\1\u00ac", - "\1\u00ad", - "\42\156\1\uffff\4\156\1\u00ae\uffd8\156", - "\42\156\1\uffff\4\156\1\u00af\uffd8\156", - "", - "", - "\1\u00b0", - "\1\u00b1", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00b8", - "\1\u00b9", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\24\47\1\u00bc\5\47\4\uffff\1"+ - "\47\1\uffff\32\47", - "\1\u00be", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00c0", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00c2", - "\1\u00c3", - "\1\u00c4", - "\1\u00c5", - "\1\u00c6", - "\1\u00c7", - "\1\u00c8", - "\1\u00c9", - "\1\u00ca", - "\1\u00cb", - "", - "\1\u00cc", - "\1\u00cd", - "", - "\1\u00ce", - "\1\u00cf", - "\1\u00d0", - "\1\u00d1", - "\1\u00d2", - "\1\u00d3", - "\1\u00d4", - "", - "", - "\1\u00d5", - "\1\u00d6", - "\1\u00d7", - "\1\u00d8", - "", - "\1\u00d9", - "\1\u00da", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00de", - "\1\u00df", - "\1\u00e0", - "\1\u00e1", - "\1\u00e2", - "\1\u00e3", - "\1\u00e4", - "\1\u00e5", - "\1\u00e6", - "\1\u00e7", - "\1\u00e8", - "\1\u00e9", - "", - "", - "\1\u00eb", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "", - "", - "", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00ee", - "", - "", - "\1\u00ef", - "", - "\1\u00f0", - "", - "\1\u00f1", - "", - "\1\u00f2", - "\1\u00f3", - "\1\u00f4", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00f8", - "\1\u00f9", - "\1\u00fa", - "\1\u00fb", - "\1\u00fc", - "\1\u00fd", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u00ff", - "\1\u0100", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0102", - "\1\u0103", - "\1\u0104", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0106", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0108", - "\1\u0109", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u010c", - "\1\u010d", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u010f", - "\1\u0110", - "\1\u0111", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0113", - "\1\u0114", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0116", - "", - "\1\u0117", - "", - "", - "\1\u0118", - "\1\u0119", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u011b", - "\1\u011c", - "\1\u011d", - "\1\u011e", - "", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0120", - "\1\u0121", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0124", - "", - "\1\u0125", - "\1\u0126", - "", - "\1\u0127", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u012c", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u012f\1\u012e\2\uffff\1\u0130", - "", - "\1\u0131", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0133", - "", - "\1\u0134", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0138", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u013b", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u013f", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0142", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "", - "", - "", - "\1\u0144", - "", - "", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0147", - "", - "", - "", - "\1\u0148", - "", - "", - "\1\u0149", - "", - "", - "", - "\1\u014a", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "", - "\1\u014d", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u014f", - "\1\u0150\17\uffff\1\u0151", - "", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\u0154", - "\1\u0155", - "", - "", - "\1\u0156", - "\1\u0157", - "\1\u0158", - "\1\u0159", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "\1\47\13\uffff\12\47\7\uffff\22\47\1\u015b\7\47\4\uffff\1"+ - "\47\1\uffff\32\47", - "", - "\1\u015d", - "", - "\1\u015e", - "\1\u015f", - "\1\u0160", - "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ - "\47", - "" - }; - - static final short[] DFA10_eot = DFA.unpackEncodedString(DFA10_eotS); - static final short[] DFA10_eof = DFA.unpackEncodedString(DFA10_eofS); - static final char[] DFA10_min = DFA.unpackEncodedStringToUnsignedChars(DFA10_minS); - static final char[] DFA10_max = DFA.unpackEncodedStringToUnsignedChars(DFA10_maxS); - static final short[] DFA10_accept = DFA.unpackEncodedString(DFA10_acceptS); - static final short[] DFA10_special = DFA.unpackEncodedString(DFA10_specialS); - static final short[][] DFA10_transition; - - static { - int numStates = DFA10_transitionS.length; - DFA10_transition = new short[numStates][]; - for (int i=0; i='\u0000' && LA10_108<='!')||(LA10_108>='#' && LA10_108<='&')||(LA10_108>='(' && LA10_108<='\uFFFF')) ) {s = 110;} - - if ( s>=0 ) return s; - break; - case 1 : - int LA10_38 = input.LA(1); - - s = -1; - if ( (LA10_38=='.') ) {s = 107;} - - else if ( ((LA10_38>='\u0000' && LA10_38<='!')||(LA10_38>='#' && LA10_38<='&')||(LA10_38>='(' && LA10_38<='-')||(LA10_38>='/' && LA10_38<='[')||(LA10_38>=']' && LA10_38<='\uFFFF')) ) {s = 108;} - - else if ( (LA10_38=='\"') ) {s = 109;} - - else if ( (LA10_38=='\''||LA10_38=='\\') ) {s = 110;} - - if ( s>=0 ) return s; - break; - case 2 : - int LA10_107 = input.LA(1); - - s = -1; - if ( (LA10_107=='\'') ) {s = 174;} - - else if ( ((LA10_107>='\u0000' && LA10_107<='!')||(LA10_107>='#' && LA10_107<='&')||(LA10_107>='(' && LA10_107<='\uFFFF')) ) {s = 110;} - - if ( s>=0 ) return s; - break; - } - NoViableAltException nvae = - new NoViableAltException(getDescription(), 10, _s, input); - error(nvae); - throw nvae; - } - } - - @Override - public void emitErrorMessage(String msg) { - //do nothing - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * 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. + * + */ + +// $ANTLR 3.2 Sep 23, 2009 12:02:23 JPA.g 2012-08-06 14:42:50 + +package com.haulmont.cuba.core.sys.jpql.antlr; + + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; + +public class JPALexer extends Lexer { + public static final int T_JOIN_VAR=11; + public static final int T_AGGREGATE_EXPR=20; + public static final int COUNT=28; + public static final int T_ORDER_BY=18; + public static final int EOF=-1; + public static final int WORD=46; + public static final int T__93=93; + public static final int T__94=94; + public static final int RPAREN=32; + public static final int T__91=91; + public static final int T__92=92; + public static final int T__90=90; + public static final int TRIM_CHARACTER=45; + public static final int T_SELECTED_ITEM=5; + public static final int COMMENT=50; + public static final int T__99=99; + public static final int T__98=98; + public static final int T__97=97; + public static final int T_QUERY=13; + public static final int T__96=96; + public static final int T__95=95; + public static final int T__80=80; + public static final int T__81=81; + public static final int T__82=82; + public static final int ASC=22; + public static final int T__83=83; + public static final int LINE_COMMENT=51; + public static final int T__85=85; + public static final int T__84=84; + public static final int T__87=87; + public static final int T__86=86; + public static final int T__89=89; + public static final int T__88=88; + public static final int GROUP=40; + public static final int T__71=71; + public static final int WS=49; + public static final int T__72=72; + public static final int FETCH=38; + public static final int T__70=70; + public static final int T_SELECTED_FIELD=8; + public static final int OR=29; + public static final int T__76=76; + public static final int T__75=75; + public static final int DISTINCT=33; + public static final int T__74=74; + public static final int T__73=73; + public static final int T__79=79; + public static final int T__78=78; + public static final int T__77=77; + public static final int T__68=68; + public static final int T__69=69; + public static final int T__66=66; + public static final int T__67=67; + public static final int T_SELECTED_ITEMS=4; + public static final int T__64=64; + public static final int T__65=65; + public static final int INNER=36; + public static final int T__62=62; + public static final int T__63=63; + public static final int ORDER=39; + public static final int T__118=118; + public static final int T_SOURCE=7; + public static final int T__119=119; + public static final int T__116=116; + public static final int T_ID_VAR=10; + public static final int T__117=117; + public static final int T_SIMPLE_CONDITION=15; + public static final int T__114=114; + public static final int T__115=115; + public static final int MAX=25; + public static final int AND=30; + public static final int SUM=27; + public static final int T__61=61; + public static final int T__60=60; + public static final int RUSSIAN_SYMBOLS=48; + public static final int LPAREN=31; + public static final int T__55=55; + public static final int T__56=56; + public static final int T__57=57; + public static final int T__58=58; + public static final int T__52=52; + public static final int T__53=53; + public static final int T__54=54; + public static final int T__107=107; + public static final int T__108=108; + public static final int T__109=109; + public static final int LEFT=34; + public static final int AVG=24; + public static final int T_ORDER_BY_FIELD=19; + public static final int T__103=103; + public static final int T__59=59; + public static final int T__104=104; + public static final int T__105=105; + public static final int T__106=106; + public static final int T__111=111; + public static final int T__110=110; + public static final int T__113=113; + public static final int T__112=112; + public static final int T_GROUP_BY=17; + public static final int OUTER=35; + public static final int BY=41; + public static final int T_CONDITION=14; + public static final int T_SELECTED_ENTITY=9; + public static final int HAVING=21; + public static final int T__102=102; + public static final int T__101=101; + public static final int T__100=100; + public static final int MIN=26; + public static final int T_PARAMETER=16; + public static final int JOIN=37; + public static final int ESCAPE_CHARACTER=43; + public static final int NAMED_PARAMETER=47; + public static final int INT_NUMERAL=42; + public static final int STRINGLITERAL=44; + public static final int T_COLLECTION_MEMBER=12; + public static final int DESC=23; + public static final int T_SOURCES=6; + + // delegates + // delegators + + public JPALexer() {;} + public JPALexer(CharStream input) { + this(input, new RecognizerSharedState()); + } + public JPALexer(CharStream input, RecognizerSharedState state) { + super(input,state); + + } + public String getGrammarFileName() { return "JPA.g"; } + + // $ANTLR start "HAVING" + public final void mHAVING() throws RecognitionException { + try { + int _type = HAVING; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:8:8: ( 'HAVING' ) + // JPA.g:8:10: 'HAVING' + { + match("HAVING"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "HAVING" + + // $ANTLR start "ASC" + public final void mASC() throws RecognitionException { + try { + int _type = ASC; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:9:5: ( 'ASC' ) + // JPA.g:9:7: 'ASC' + { + match("ASC"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "ASC" + + // $ANTLR start "DESC" + public final void mDESC() throws RecognitionException { + try { + int _type = DESC; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:10:6: ( 'DESC' ) + // JPA.g:10:8: 'DESC' + { + match("DESC"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "DESC" + + // $ANTLR start "AVG" + public final void mAVG() throws RecognitionException { + try { + int _type = AVG; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:11:5: ( 'AVG' ) + // JPA.g:11:7: 'AVG' + { + match("AVG"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "AVG" + + // $ANTLR start "MAX" + public final void mMAX() throws RecognitionException { + try { + int _type = MAX; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:12:5: ( 'MAX' ) + // JPA.g:12:7: 'MAX' + { + match("MAX"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "MAX" + + // $ANTLR start "MIN" + public final void mMIN() throws RecognitionException { + try { + int _type = MIN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:13:5: ( 'MIN' ) + // JPA.g:13:7: 'MIN' + { + match("MIN"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "MIN" + + // $ANTLR start "SUM" + public final void mSUM() throws RecognitionException { + try { + int _type = SUM; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:14:5: ( 'SUM' ) + // JPA.g:14:7: 'SUM' + { + match("SUM"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "SUM" + + // $ANTLR start "COUNT" + public final void mCOUNT() throws RecognitionException { + try { + int _type = COUNT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:15:7: ( 'COUNT' ) + // JPA.g:15:9: 'COUNT' + { + match("COUNT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "COUNT" + + // $ANTLR start "OR" + public final void mOR() throws RecognitionException { + try { + int _type = OR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:16:4: ( 'OR' ) + // JPA.g:16:6: 'OR' + { + match("OR"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "OR" + + // $ANTLR start "AND" + public final void mAND() throws RecognitionException { + try { + int _type = AND; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:17:5: ( 'AND' ) + // JPA.g:17:7: 'AND' + { + match("AND"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "AND" + + // $ANTLR start "LPAREN" + public final void mLPAREN() throws RecognitionException { + try { + int _type = LPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:18:8: ( '(' ) + // JPA.g:18:10: '(' + { + match('('); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "LPAREN" + + // $ANTLR start "RPAREN" + public final void mRPAREN() throws RecognitionException { + try { + int _type = RPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:19:8: ( ')' ) + // JPA.g:19:10: ')' + { + match(')'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "RPAREN" + + // $ANTLR start "DISTINCT" + public final void mDISTINCT() throws RecognitionException { + try { + int _type = DISTINCT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:20:10: ( 'DISTINCT' ) + // JPA.g:20:12: 'DISTINCT' + { + match("DISTINCT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "DISTINCT" + + // $ANTLR start "LEFT" + public final void mLEFT() throws RecognitionException { + try { + int _type = LEFT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:21:6: ( 'LEFT' ) + // JPA.g:21:8: 'LEFT' + { + match("LEFT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "LEFT" + + // $ANTLR start "OUTER" + public final void mOUTER() throws RecognitionException { + try { + int _type = OUTER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:22:7: ( 'OUTER' ) + // JPA.g:22:9: 'OUTER' + { + match("OUTER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "OUTER" + + // $ANTLR start "INNER" + public final void mINNER() throws RecognitionException { + try { + int _type = INNER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:23:7: ( 'INNER' ) + // JPA.g:23:9: 'INNER' + { + match("INNER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "INNER" + + // $ANTLR start "JOIN" + public final void mJOIN() throws RecognitionException { + try { + int _type = JOIN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:24:6: ( 'JOIN' ) + // JPA.g:24:8: 'JOIN' + { + match("JOIN"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "JOIN" + + // $ANTLR start "FETCH" + public final void mFETCH() throws RecognitionException { + try { + int _type = FETCH; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:25:7: ( 'FETCH' ) + // JPA.g:25:9: 'FETCH' + { + match("FETCH"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "FETCH" + + // $ANTLR start "ORDER" + public final void mORDER() throws RecognitionException { + try { + int _type = ORDER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:26:7: ( 'ORDER' ) + // JPA.g:26:9: 'ORDER' + { + match("ORDER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "ORDER" + + // $ANTLR start "GROUP" + public final void mGROUP() throws RecognitionException { + try { + int _type = GROUP; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:27:7: ( 'GROUP' ) + // JPA.g:27:9: 'GROUP' + { + match("GROUP"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "GROUP" + + // $ANTLR start "BY" + public final void mBY() throws RecognitionException { + try { + int _type = BY; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:28:4: ( 'BY' ) + // JPA.g:28:6: 'BY' + { + match("BY"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "BY" + + // $ANTLR start "T__52" + public final void mT__52() throws RecognitionException { + try { + int _type = T__52; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:29:7: ( 'SELECT' ) + // JPA.g:29:9: 'SELECT' + { + match("SELECT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__52" + + // $ANTLR start "T__53" + public final void mT__53() throws RecognitionException { + try { + int _type = T__53; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:30:7: ( 'FROM' ) + // JPA.g:30:9: 'FROM' + { + match("FROM"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__53" + + // $ANTLR start "T__54" + public final void mT__54() throws RecognitionException { + try { + int _type = T__54; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:31:7: ( ',' ) + // JPA.g:31:9: ',' + { + match(','); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__54" + + // $ANTLR start "T__55" + public final void mT__55() throws RecognitionException { + try { + int _type = T__55; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:32:7: ( 'AS' ) + // JPA.g:32:9: 'AS' + { + match("AS"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__55" + + // $ANTLR start "T__56" + public final void mT__56() throws RecognitionException { + try { + int _type = T__56; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:33:7: ( '(SELECT' ) + // JPA.g:33:9: '(SELECT' + { + match("(SELECT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__56" + + // $ANTLR start "T__57" + public final void mT__57() throws RecognitionException { + try { + int _type = T__57; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:34:7: ( '.' ) + // JPA.g:34:9: '.' + { + match('.'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__57" + + // $ANTLR start "T__58" + public final void mT__58() throws RecognitionException { + try { + int _type = T__58; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:35:7: ( 'IN' ) + // JPA.g:35:9: 'IN' + { + match("IN"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__58" + + // $ANTLR start "T__59" + public final void mT__59() throws RecognitionException { + try { + int _type = T__59; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:36:7: ( 'OBJECT' ) + // JPA.g:36:9: 'OBJECT' + { + match("OBJECT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__59" + + // $ANTLR start "T__60" + public final void mT__60() throws RecognitionException { + try { + int _type = T__60; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:37:7: ( 'NEW' ) + // JPA.g:37:9: 'NEW' + { + match("NEW"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__60" + + // $ANTLR start "T__61" + public final void mT__61() throws RecognitionException { + try { + int _type = T__61; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:38:7: ( 'WHERE' ) + // JPA.g:38:9: 'WHERE' + { + match("WHERE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__61" + + // $ANTLR start "T__62" + public final void mT__62() throws RecognitionException { + try { + int _type = T__62; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:39:7: ( 'NOT' ) + // JPA.g:39:9: 'NOT' + { + match("NOT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__62" + + // $ANTLR start "T__63" + public final void mT__63() throws RecognitionException { + try { + int _type = T__63; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:40:7: ( '@BETWEEN' ) + // JPA.g:40:9: '@BETWEEN' + { + match("@BETWEEN"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__63" + + // $ANTLR start "T__64" + public final void mT__64() throws RecognitionException { + try { + int _type = T__64; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:41:7: ( 'NOW' ) + // JPA.g:41:9: 'NOW' + { + match("NOW"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__64" + + // $ANTLR start "T__65" + public final void mT__65() throws RecognitionException { + try { + int _type = T__65; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:42:7: ( '+' ) + // JPA.g:42:9: '+' + { + match('+'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__65" + + // $ANTLR start "T__66" + public final void mT__66() throws RecognitionException { + try { + int _type = T__66; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:43:7: ( '-' ) + // JPA.g:43:9: '-' + { + match('-'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__66" + + // $ANTLR start "T__67" + public final void mT__67() throws RecognitionException { + try { + int _type = T__67; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:44:7: ( 'YEAR' ) + // JPA.g:44:9: 'YEAR' + { + match("YEAR"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__67" + + // $ANTLR start "T__68" + public final void mT__68() throws RecognitionException { + try { + int _type = T__68; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:45:7: ( 'MONTH' ) + // JPA.g:45:9: 'MONTH' + { + match("MONTH"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__68" + + // $ANTLR start "T__69" + public final void mT__69() throws RecognitionException { + try { + int _type = T__69; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:46:7: ( 'DAY' ) + // JPA.g:46:9: 'DAY' + { + match("DAY"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__69" + + // $ANTLR start "T__70" + public final void mT__70() throws RecognitionException { + try { + int _type = T__70; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:47:7: ( 'HOUR' ) + // JPA.g:47:9: 'HOUR' + { + match("HOUR"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__70" + + // $ANTLR start "T__71" + public final void mT__71() throws RecognitionException { + try { + int _type = T__71; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:48:7: ( 'MINUTE' ) + // JPA.g:48:9: 'MINUTE' + { + match("MINUTE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__71" + + // $ANTLR start "T__72" + public final void mT__72() throws RecognitionException { + try { + int _type = T__72; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:49:7: ( 'SECOND' ) + // JPA.g:49:9: 'SECOND' + { + match("SECOND"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__72" + + // $ANTLR start "T__73" + public final void mT__73() throws RecognitionException { + try { + int _type = T__73; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:50:7: ( '@DATEBEFORE' ) + // JPA.g:50:9: '@DATEBEFORE' + { + match("@DATEBEFORE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__73" + + // $ANTLR start "T__74" + public final void mT__74() throws RecognitionException { + try { + int _type = T__74; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:51:7: ( '@DATEAFTER' ) + // JPA.g:51:9: '@DATEAFTER' + { + match("@DATEAFTER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__74" + + // $ANTLR start "T__75" + public final void mT__75() throws RecognitionException { + try { + int _type = T__75; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:52:7: ( '@DATEEQUALS' ) + // JPA.g:52:9: '@DATEEQUALS' + { + match("@DATEEQUALS"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__75" + + // $ANTLR start "T__76" + public final void mT__76() throws RecognitionException { + try { + int _type = T__76; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:53:7: ( '@TODAY' ) + // JPA.g:53:9: '@TODAY' + { + match("@TODAY"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__76" + + // $ANTLR start "T__77" + public final void mT__77() throws RecognitionException { + try { + int _type = T__77; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:54:7: ( 'BETWEEN' ) + // JPA.g:54:9: 'BETWEEN' + { + match("BETWEEN"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__77" + + // $ANTLR start "T__78" + public final void mT__78() throws RecognitionException { + try { + int _type = T__78; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:55:7: ( 'LIKE' ) + // JPA.g:55:9: 'LIKE' + { + match("LIKE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__78" + + // $ANTLR start "T__79" + public final void mT__79() throws RecognitionException { + try { + int _type = T__79; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:56:7: ( 'ESCAPE' ) + // JPA.g:56:9: 'ESCAPE' + { + match("ESCAPE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__79" + + // $ANTLR start "T__80" + public final void mT__80() throws RecognitionException { + try { + int _type = T__80; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:57:7: ( 'IS' ) + // JPA.g:57:9: 'IS' + { + match("IS"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__80" + + // $ANTLR start "T__81" + public final void mT__81() throws RecognitionException { + try { + int _type = T__81; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:58:7: ( 'NULL' ) + // JPA.g:58:9: 'NULL' + { + match("NULL"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__81" + + // $ANTLR start "T__82" + public final void mT__82() throws RecognitionException { + try { + int _type = T__82; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:59:7: ( 'EMPTY' ) + // JPA.g:59:9: 'EMPTY' + { + match("EMPTY"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__82" + + // $ANTLR start "T__83" + public final void mT__83() throws RecognitionException { + try { + int _type = T__83; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:60:7: ( 'MEMBER' ) + // JPA.g:60:9: 'MEMBER' + { + match("MEMBER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__83" + + // $ANTLR start "T__84" + public final void mT__84() throws RecognitionException { + try { + int _type = T__84; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:61:7: ( 'OF' ) + // JPA.g:61:9: 'OF' + { + match("OF"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__84" + + // $ANTLR start "T__85" + public final void mT__85() throws RecognitionException { + try { + int _type = T__85; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:62:7: ( 'EXISTS' ) + // JPA.g:62:9: 'EXISTS' + { + match("EXISTS"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__85" + + // $ANTLR start "T__86" + public final void mT__86() throws RecognitionException { + try { + int _type = T__86; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:63:7: ( 'ALL' ) + // JPA.g:63:9: 'ALL' + { + match("ALL"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__86" + + // $ANTLR start "T__87" + public final void mT__87() throws RecognitionException { + try { + int _type = T__87; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:64:7: ( 'ANY' ) + // JPA.g:64:9: 'ANY' + { + match("ANY"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__87" + + // $ANTLR start "T__88" + public final void mT__88() throws RecognitionException { + try { + int _type = T__88; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:65:7: ( 'SOME' ) + // JPA.g:65:9: 'SOME' + { + match("SOME"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__88" + + // $ANTLR start "T__89" + public final void mT__89() throws RecognitionException { + try { + int _type = T__89; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:66:7: ( '=' ) + // JPA.g:66:9: '=' + { + match('='); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__89" + + // $ANTLR start "T__90" + public final void mT__90() throws RecognitionException { + try { + int _type = T__90; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:67:7: ( '<>' ) + // JPA.g:67:9: '<>' + { + match("<>"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__90" + + // $ANTLR start "T__91" + public final void mT__91() throws RecognitionException { + try { + int _type = T__91; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:68:7: ( '>' ) + // JPA.g:68:9: '>' + { + match('>'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__91" + + // $ANTLR start "T__92" + public final void mT__92() throws RecognitionException { + try { + int _type = T__92; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:69:7: ( '>=' ) + // JPA.g:69:9: '>=' + { + match(">="); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__92" + + // $ANTLR start "T__93" + public final void mT__93() throws RecognitionException { + try { + int _type = T__93; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:70:7: ( '<' ) + // JPA.g:70:9: '<' + { + match('<'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__93" + + // $ANTLR start "T__94" + public final void mT__94() throws RecognitionException { + try { + int _type = T__94; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:71:7: ( '<=' ) + // JPA.g:71:9: '<=' + { + match("<="); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__94" + + // $ANTLR start "T__95" + public final void mT__95() throws RecognitionException { + try { + int _type = T__95; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:72:7: ( '*' ) + // JPA.g:72:9: '*' + { + match('*'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__95" + + // $ANTLR start "T__96" + public final void mT__96() throws RecognitionException { + try { + int _type = T__96; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:73:7: ( '/' ) + // JPA.g:73:9: '/' + { + match('/'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__96" + + // $ANTLR start "T__97" + public final void mT__97() throws RecognitionException { + try { + int _type = T__97; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:74:7: ( 'LENGTH' ) + // JPA.g:74:9: 'LENGTH' + { + match("LENGTH"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__97" + + // $ANTLR start "T__98" + public final void mT__98() throws RecognitionException { + try { + int _type = T__98; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:75:7: ( 'LOCATE' ) + // JPA.g:75:9: 'LOCATE' + { + match("LOCATE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__98" + + // $ANTLR start "T__99" + public final void mT__99() throws RecognitionException { + try { + int _type = T__99; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:76:7: ( 'ABS' ) + // JPA.g:76:9: 'ABS' + { + match("ABS"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__99" + + // $ANTLR start "T__100" + public final void mT__100() throws RecognitionException { + try { + int _type = T__100; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:77:8: ( 'SQRT' ) + // JPA.g:77:10: 'SQRT' + { + match("SQRT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__100" + + // $ANTLR start "T__101" + public final void mT__101() throws RecognitionException { + try { + int _type = T__101; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:78:8: ( 'MOD' ) + // JPA.g:78:10: 'MOD' + { + match("MOD"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__101" + + // $ANTLR start "T__102" + public final void mT__102() throws RecognitionException { + try { + int _type = T__102; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:79:8: ( 'SIZE' ) + // JPA.g:79:10: 'SIZE' + { + match("SIZE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__102" + + // $ANTLR start "T__103" + public final void mT__103() throws RecognitionException { + try { + int _type = T__103; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:80:8: ( 'CURRENT_DATE' ) + // JPA.g:80:10: 'CURRENT_DATE' + { + match("CURRENT_DATE"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__103" + + // $ANTLR start "T__104" + public final void mT__104() throws RecognitionException { + try { + int _type = T__104; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:81:8: ( 'CURRENT_TIME' ) + // JPA.g:81:10: 'CURRENT_TIME' + { + match("CURRENT_TIME"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__104" + + // $ANTLR start "T__105" + public final void mT__105() throws RecognitionException { + try { + int _type = T__105; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:82:8: ( 'CURRENT_TIMESTAMP' ) + // JPA.g:82:10: 'CURRENT_TIMESTAMP' + { + match("CURRENT_TIMESTAMP"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__105" + + // $ANTLR start "T__106" + public final void mT__106() throws RecognitionException { + try { + int _type = T__106; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:83:8: ( 'CONCAT' ) + // JPA.g:83:10: 'CONCAT' + { + match("CONCAT"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__106" + + // $ANTLR start "T__107" + public final void mT__107() throws RecognitionException { + try { + int _type = T__107; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:84:8: ( 'SUBSTRING' ) + // JPA.g:84:10: 'SUBSTRING' + { + match("SUBSTRING"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__107" + + // $ANTLR start "T__108" + public final void mT__108() throws RecognitionException { + try { + int _type = T__108; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:85:8: ( 'TRIM' ) + // JPA.g:85:10: 'TRIM' + { + match("TRIM"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__108" + + // $ANTLR start "T__109" + public final void mT__109() throws RecognitionException { + try { + int _type = T__109; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:86:8: ( 'LOWER' ) + // JPA.g:86:10: 'LOWER' + { + match("LOWER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__109" + + // $ANTLR start "T__110" + public final void mT__110() throws RecognitionException { + try { + int _type = T__110; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:87:8: ( 'UPPER' ) + // JPA.g:87:10: 'UPPER' + { + match("UPPER"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__110" + + // $ANTLR start "T__111" + public final void mT__111() throws RecognitionException { + try { + int _type = T__111; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:88:8: ( 'LEADING' ) + // JPA.g:88:10: 'LEADING' + { + match("LEADING"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__111" + + // $ANTLR start "T__112" + public final void mT__112() throws RecognitionException { + try { + int _type = T__112; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:89:8: ( 'TRAILING' ) + // JPA.g:89:10: 'TRAILING' + { + match("TRAILING"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__112" + + // $ANTLR start "T__113" + public final void mT__113() throws RecognitionException { + try { + int _type = T__113; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:90:8: ( 'BOTH' ) + // JPA.g:90:10: 'BOTH' + { + match("BOTH"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__113" + + // $ANTLR start "T__114" + public final void mT__114() throws RecognitionException { + try { + int _type = T__114; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:91:8: ( '0x' ) + // JPA.g:91:10: '0x' + { + match("0x"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__114" + + // $ANTLR start "T__115" + public final void mT__115() throws RecognitionException { + try { + int _type = T__115; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:92:8: ( '?' ) + // JPA.g:92:10: '?' + { + match('?'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__115" + + // $ANTLR start "T__116" + public final void mT__116() throws RecognitionException { + try { + int _type = T__116; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:93:8: ( '${' ) + // JPA.g:93:10: '${' + { + match("${"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__116" + + // $ANTLR start "T__117" + public final void mT__117() throws RecognitionException { + try { + int _type = T__117; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:94:8: ( '}' ) + // JPA.g:94:10: '}' + { + match('}'); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__117" + + // $ANTLR start "T__118" + public final void mT__118() throws RecognitionException { + try { + int _type = T__118; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:95:8: ( 'true' ) + // JPA.g:95:10: 'true' + { + match("true"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__118" + + // $ANTLR start "T__119" + public final void mT__119() throws RecognitionException { + try { + int _type = T__119; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:96:8: ( 'false' ) + // JPA.g:96:10: 'false' + { + match("false"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "T__119" + + // $ANTLR start "TRIM_CHARACTER" + public final void mTRIM_CHARACTER() throws RecognitionException { + try { + int _type = TRIM_CHARACTER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:450:5: ( '\\'.\\'' ) + // JPA.g:450:7: '\\'.\\'' + { + match("'.'"); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "TRIM_CHARACTER" + + // $ANTLR start "STRINGLITERAL" + public final void mSTRINGLITERAL() throws RecognitionException { + try { + int _type = STRINGLITERAL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:453:5: ( '\\'' (~ ( '\\'' | '\"' ) )* '\\'' ) + // JPA.g:453:7: '\\'' (~ ( '\\'' | '\"' ) )* '\\'' + { + match('\''); + // JPA.g:453:12: (~ ( '\\'' | '\"' ) )* + loop1: + do { + int alt1=2; + int LA1_0 = input.LA(1); + + if ( ((LA1_0>='\u0000' && LA1_0<='!')||(LA1_0>='#' && LA1_0<='&')||(LA1_0>='(' && LA1_0<='\uFFFF')) ) { + alt1=1; + } + + + switch (alt1) { + case 1 : + // JPA.g:453:13: ~ ( '\\'' | '\"' ) + { + if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='\uFFFF') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + break; + + default : + break loop1; + } + } while (true); + + match('\''); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "STRINGLITERAL" + + // $ANTLR start "WORD" + public final void mWORD() throws RecognitionException { + try { + int _type = WORD; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:456:5: ( ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ) + // JPA.g:456:7: ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* + { + if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + // JPA.g:456:31: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* + loop2: + do { + int alt2=2; + int LA2_0 = input.LA(1); + + if ( (LA2_0=='$'||(LA2_0>='0' && LA2_0<='9')||(LA2_0>='A' && LA2_0<='Z')||LA2_0=='_'||(LA2_0>='a' && LA2_0<='z')) ) { + alt2=1; + } + + + switch (alt2) { + case 1 : + // JPA.g: + { + if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + break; + + default : + break loop2; + } + } while (true); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "WORD" + + // $ANTLR start "RUSSIAN_SYMBOLS" + public final void mRUSSIAN_SYMBOLS() throws RecognitionException { + try { + int _type = RUSSIAN_SYMBOLS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:459:5: ( ( '\\u0400' .. '\\u04FF' | '\\u0500' .. '\\u052F' ) ) + // JPA.g:459:7: ( '\\u0400' .. '\\u04FF' | '\\u0500' .. '\\u052F' ) + { + if ( (input.LA(1)>='\u0400' && input.LA(1)<='\u052F') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol"); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "RUSSIAN_SYMBOLS" + + // $ANTLR start "NAMED_PARAMETER" + public final void mNAMED_PARAMETER() throws RecognitionException { + try { + int _type = NAMED_PARAMETER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:462:5: ( ':' ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* ) + // JPA.g:462:7: ':' ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* + { + match(':'); + if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + // JPA.g:462:34: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )* + loop3: + do { + int alt3=2; + int LA3_0 = input.LA(1); + + if ( (LA3_0=='$'||(LA3_0>='0' && LA3_0<='9')||(LA3_0>='A' && LA3_0<='Z')||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')) ) { + alt3=1; + } + + + switch (alt3) { + case 1 : + // JPA.g: + { + if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + break; + + default : + break loop3; + } + } while (true); + + // JPA.g:462:72: ( ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ )* + loop5: + do { + int alt5=2; + int LA5_0 = input.LA(1); + + if ( (LA5_0=='.') ) { + alt5=1; + } + + + switch (alt5) { + case 1 : + // JPA.g:462:73: ( '.' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ + { + // JPA.g:462:73: ( '.' ) + // JPA.g:462:74: '.' + { + match('.'); + + } + + // JPA.g:462:79: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' )+ + int cnt4=0; + loop4: + do { + int alt4=2; + int LA4_0 = input.LA(1); + + if ( (LA4_0=='$'||(LA4_0>='0' && LA4_0<='9')||(LA4_0>='A' && LA4_0<='Z')||LA4_0=='_'||(LA4_0>='a' && LA4_0<='z')) ) { + alt4=1; + } + + + switch (alt4) { + case 1 : + // JPA.g: + { + if ( input.LA(1)=='$'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + break; + + default : + if ( cnt4 >= 1 ) break loop4; + EarlyExitException eee = + new EarlyExitException(4, input); + throw eee; + } + cnt4++; + } while (true); + + + } + break; + + default : + break loop5; + } + } while (true); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "NAMED_PARAMETER" + + // $ANTLR start "WS" + public final void mWS() throws RecognitionException { + try { + int _type = WS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:464:5: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) ) + // JPA.g:464:7: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) + { + if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||(input.LA(1)>='\f' && input.LA(1)<='\r')||input.LA(1)==' ' ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + _channel=HIDDEN; + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "WS" + + // $ANTLR start "COMMENT" + public final void mCOMMENT() throws RecognitionException { + try { + int _type = COMMENT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:468:5: ( '/*' ( . )* '*/' ) + // JPA.g:468:7: '/*' ( . )* '*/' + { + match("/*"); + + // JPA.g:468:12: ( . )* + loop6: + do { + int alt6=2; + int LA6_0 = input.LA(1); + + if ( (LA6_0=='*') ) { + int LA6_1 = input.LA(2); + + if ( (LA6_1=='/') ) { + alt6=2; + } + else if ( ((LA6_1>='\u0000' && LA6_1<='.')||(LA6_1>='0' && LA6_1<='\uFFFF')) ) { + alt6=1; + } + + + } + else if ( ((LA6_0>='\u0000' && LA6_0<=')')||(LA6_0>='+' && LA6_0<='\uFFFF')) ) { + alt6=1; + } + + + switch (alt6) { + case 1 : + // JPA.g:468:12: . + { + matchAny(); + + } + break; + + default : + break loop6; + } + } while (true); + + match("*/"); + + _channel=HIDDEN; + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "COMMENT" + + // $ANTLR start "LINE_COMMENT" + public final void mLINE_COMMENT() throws RecognitionException { + try { + int _type = LINE_COMMENT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:471:5: ( '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' ) + // JPA.g:471:7: '//' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' + { + match("//"); + + // JPA.g:471:12: (~ ( '\\n' | '\\r' ) )* + loop7: + do { + int alt7=2; + int LA7_0 = input.LA(1); + + if ( ((LA7_0>='\u0000' && LA7_0<='\t')||(LA7_0>='\u000B' && LA7_0<='\f')||(LA7_0>='\u000E' && LA7_0<='\uFFFF')) ) { + alt7=1; + } + + + switch (alt7) { + case 1 : + // JPA.g:471:12: ~ ( '\\n' | '\\r' ) + { + if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='\uFFFF') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + break; + + default : + break loop7; + } + } while (true); + + // JPA.g:471:26: ( '\\r' )? + int alt8=2; + int LA8_0 = input.LA(1); + + if ( (LA8_0=='\r') ) { + alt8=1; + } + switch (alt8) { + case 1 : + // JPA.g:471:26: '\\r' + { + match('\r'); + + } + break; + + } + + match('\n'); + _channel=HIDDEN; + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "LINE_COMMENT" + + // $ANTLR start "ESCAPE_CHARACTER" + public final void mESCAPE_CHARACTER() throws RecognitionException { + try { + int _type = ESCAPE_CHARACTER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:474:5: ( '\\'' (~ ( '\\'' | '\\\\' ) ) '\\'' ) + // JPA.g:474:7: '\\'' (~ ( '\\'' | '\\\\' ) ) '\\'' + { + match('\''); + // JPA.g:474:12: (~ ( '\\'' | '\\\\' ) ) + // JPA.g:474:13: ~ ( '\\'' | '\\\\' ) + { + if ( (input.LA(1)>='\u0000' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFF') ) { + input.consume(); + + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse;} + + + } + + match('\''); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "ESCAPE_CHARACTER" + + // $ANTLR start "INT_NUMERAL" + public final void mINT_NUMERAL() throws RecognitionException { + try { + int _type = INT_NUMERAL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // JPA.g:477:5: ( ( '0' .. '9' )+ ) + // JPA.g:477:7: ( '0' .. '9' )+ + { + // JPA.g:477:7: ( '0' .. '9' )+ + int cnt9=0; + loop9: + do { + int alt9=2; + int LA9_0 = input.LA(1); + + if ( ((LA9_0>='0' && LA9_0<='9')) ) { + alt9=1; + } + + + switch (alt9) { + case 1 : + // JPA.g:477:8: '0' .. '9' + { + matchRange('0','9'); + + } + break; + + default : + if ( cnt9 >= 1 ) break loop9; + EarlyExitException eee = + new EarlyExitException(9, input); + throw eee; + } + cnt9++; + } while (true); + + + } + + state.type = _type; + state.channel = _channel; + } + finally { + } + } + // $ANTLR end "INT_NUMERAL" + + public void mTokens() throws RecognitionException { + // JPA.g:1:8: ( HAVING | ASC | DESC | AVG | MAX | MIN | SUM | COUNT | OR | AND | LPAREN | RPAREN | DISTINCT | LEFT | OUTER | INNER | JOIN | FETCH | ORDER | GROUP | BY | T__52 | T__53 | T__54 | T__55 | T__56 | T__57 | T__58 | T__59 | T__60 | T__61 | T__62 | T__63 | T__64 | T__65 | T__66 | T__67 | T__68 | T__69 | T__70 | T__71 | T__72 | T__73 | T__74 | T__75 | T__76 | T__77 | T__78 | T__79 | T__80 | T__81 | T__82 | T__83 | T__84 | T__85 | T__86 | T__87 | T__88 | T__89 | T__90 | T__91 | T__92 | T__93 | T__94 | T__95 | T__96 | T__97 | T__98 | T__99 | T__100 | T__101 | T__102 | T__103 | T__104 | T__105 | T__106 | T__107 | T__108 | T__109 | T__110 | T__111 | T__112 | T__113 | T__114 | T__115 | T__116 | T__117 | T__118 | T__119 | TRIM_CHARACTER | STRINGLITERAL | WORD | RUSSIAN_SYMBOLS | NAMED_PARAMETER | WS | COMMENT | LINE_COMMENT | ESCAPE_CHARACTER | INT_NUMERAL ) + int alt10=99; + alt10 = dfa10.predict(input); + switch (alt10) { + case 1 : + // JPA.g:1:10: HAVING + { + mHAVING(); + + } + break; + case 2 : + // JPA.g:1:17: ASC + { + mASC(); + + } + break; + case 3 : + // JPA.g:1:21: DESC + { + mDESC(); + + } + break; + case 4 : + // JPA.g:1:26: AVG + { + mAVG(); + + } + break; + case 5 : + // JPA.g:1:30: MAX + { + mMAX(); + + } + break; + case 6 : + // JPA.g:1:34: MIN + { + mMIN(); + + } + break; + case 7 : + // JPA.g:1:38: SUM + { + mSUM(); + + } + break; + case 8 : + // JPA.g:1:42: COUNT + { + mCOUNT(); + + } + break; + case 9 : + // JPA.g:1:48: OR + { + mOR(); + + } + break; + case 10 : + // JPA.g:1:51: AND + { + mAND(); + + } + break; + case 11 : + // JPA.g:1:55: LPAREN + { + mLPAREN(); + + } + break; + case 12 : + // JPA.g:1:62: RPAREN + { + mRPAREN(); + + } + break; + case 13 : + // JPA.g:1:69: DISTINCT + { + mDISTINCT(); + + } + break; + case 14 : + // JPA.g:1:78: LEFT + { + mLEFT(); + + } + break; + case 15 : + // JPA.g:1:83: OUTER + { + mOUTER(); + + } + break; + case 16 : + // JPA.g:1:89: INNER + { + mINNER(); + + } + break; + case 17 : + // JPA.g:1:95: JOIN + { + mJOIN(); + + } + break; + case 18 : + // JPA.g:1:100: FETCH + { + mFETCH(); + + } + break; + case 19 : + // JPA.g:1:106: ORDER + { + mORDER(); + + } + break; + case 20 : + // JPA.g:1:112: GROUP + { + mGROUP(); + + } + break; + case 21 : + // JPA.g:1:118: BY + { + mBY(); + + } + break; + case 22 : + // JPA.g:1:121: T__52 + { + mT__52(); + + } + break; + case 23 : + // JPA.g:1:127: T__53 + { + mT__53(); + + } + break; + case 24 : + // JPA.g:1:133: T__54 + { + mT__54(); + + } + break; + case 25 : + // JPA.g:1:139: T__55 + { + mT__55(); + + } + break; + case 26 : + // JPA.g:1:145: T__56 + { + mT__56(); + + } + break; + case 27 : + // JPA.g:1:151: T__57 + { + mT__57(); + + } + break; + case 28 : + // JPA.g:1:157: T__58 + { + mT__58(); + + } + break; + case 29 : + // JPA.g:1:163: T__59 + { + mT__59(); + + } + break; + case 30 : + // JPA.g:1:169: T__60 + { + mT__60(); + + } + break; + case 31 : + // JPA.g:1:175: T__61 + { + mT__61(); + + } + break; + case 32 : + // JPA.g:1:181: T__62 + { + mT__62(); + + } + break; + case 33 : + // JPA.g:1:187: T__63 + { + mT__63(); + + } + break; + case 34 : + // JPA.g:1:193: T__64 + { + mT__64(); + + } + break; + case 35 : + // JPA.g:1:199: T__65 + { + mT__65(); + + } + break; + case 36 : + // JPA.g:1:205: T__66 + { + mT__66(); + + } + break; + case 37 : + // JPA.g:1:211: T__67 + { + mT__67(); + + } + break; + case 38 : + // JPA.g:1:217: T__68 + { + mT__68(); + + } + break; + case 39 : + // JPA.g:1:223: T__69 + { + mT__69(); + + } + break; + case 40 : + // JPA.g:1:229: T__70 + { + mT__70(); + + } + break; + case 41 : + // JPA.g:1:235: T__71 + { + mT__71(); + + } + break; + case 42 : + // JPA.g:1:241: T__72 + { + mT__72(); + + } + break; + case 43 : + // JPA.g:1:247: T__73 + { + mT__73(); + + } + break; + case 44 : + // JPA.g:1:253: T__74 + { + mT__74(); + + } + break; + case 45 : + // JPA.g:1:259: T__75 + { + mT__75(); + + } + break; + case 46 : + // JPA.g:1:265: T__76 + { + mT__76(); + + } + break; + case 47 : + // JPA.g:1:271: T__77 + { + mT__77(); + + } + break; + case 48 : + // JPA.g:1:277: T__78 + { + mT__78(); + + } + break; + case 49 : + // JPA.g:1:283: T__79 + { + mT__79(); + + } + break; + case 50 : + // JPA.g:1:289: T__80 + { + mT__80(); + + } + break; + case 51 : + // JPA.g:1:295: T__81 + { + mT__81(); + + } + break; + case 52 : + // JPA.g:1:301: T__82 + { + mT__82(); + + } + break; + case 53 : + // JPA.g:1:307: T__83 + { + mT__83(); + + } + break; + case 54 : + // JPA.g:1:313: T__84 + { + mT__84(); + + } + break; + case 55 : + // JPA.g:1:319: T__85 + { + mT__85(); + + } + break; + case 56 : + // JPA.g:1:325: T__86 + { + mT__86(); + + } + break; + case 57 : + // JPA.g:1:331: T__87 + { + mT__87(); + + } + break; + case 58 : + // JPA.g:1:337: T__88 + { + mT__88(); + + } + break; + case 59 : + // JPA.g:1:343: T__89 + { + mT__89(); + + } + break; + case 60 : + // JPA.g:1:349: T__90 + { + mT__90(); + + } + break; + case 61 : + // JPA.g:1:355: T__91 + { + mT__91(); + + } + break; + case 62 : + // JPA.g:1:361: T__92 + { + mT__92(); + + } + break; + case 63 : + // JPA.g:1:367: T__93 + { + mT__93(); + + } + break; + case 64 : + // JPA.g:1:373: T__94 + { + mT__94(); + + } + break; + case 65 : + // JPA.g:1:379: T__95 + { + mT__95(); + + } + break; + case 66 : + // JPA.g:1:385: T__96 + { + mT__96(); + + } + break; + case 67 : + // JPA.g:1:391: T__97 + { + mT__97(); + + } + break; + case 68 : + // JPA.g:1:397: T__98 + { + mT__98(); + + } + break; + case 69 : + // JPA.g:1:403: T__99 + { + mT__99(); + + } + break; + case 70 : + // JPA.g:1:409: T__100 + { + mT__100(); + + } + break; + case 71 : + // JPA.g:1:416: T__101 + { + mT__101(); + + } + break; + case 72 : + // JPA.g:1:423: T__102 + { + mT__102(); + + } + break; + case 73 : + // JPA.g:1:430: T__103 + { + mT__103(); + + } + break; + case 74 : + // JPA.g:1:437: T__104 + { + mT__104(); + + } + break; + case 75 : + // JPA.g:1:444: T__105 + { + mT__105(); + + } + break; + case 76 : + // JPA.g:1:451: T__106 + { + mT__106(); + + } + break; + case 77 : + // JPA.g:1:458: T__107 + { + mT__107(); + + } + break; + case 78 : + // JPA.g:1:465: T__108 + { + mT__108(); + + } + break; + case 79 : + // JPA.g:1:472: T__109 + { + mT__109(); + + } + break; + case 80 : + // JPA.g:1:479: T__110 + { + mT__110(); + + } + break; + case 81 : + // JPA.g:1:486: T__111 + { + mT__111(); + + } + break; + case 82 : + // JPA.g:1:493: T__112 + { + mT__112(); + + } + break; + case 83 : + // JPA.g:1:500: T__113 + { + mT__113(); + + } + break; + case 84 : + // JPA.g:1:507: T__114 + { + mT__114(); + + } + break; + case 85 : + // JPA.g:1:514: T__115 + { + mT__115(); + + } + break; + case 86 : + // JPA.g:1:521: T__116 + { + mT__116(); + + } + break; + case 87 : + // JPA.g:1:528: T__117 + { + mT__117(); + + } + break; + case 88 : + // JPA.g:1:535: T__118 + { + mT__118(); + + } + break; + case 89 : + // JPA.g:1:542: T__119 + { + mT__119(); + + } + break; + case 90 : + // JPA.g:1:549: TRIM_CHARACTER + { + mTRIM_CHARACTER(); + + } + break; + case 91 : + // JPA.g:1:564: STRINGLITERAL + { + mSTRINGLITERAL(); + + } + break; + case 92 : + // JPA.g:1:578: WORD + { + mWORD(); + + } + break; + case 93 : + // JPA.g:1:583: RUSSIAN_SYMBOLS + { + mRUSSIAN_SYMBOLS(); + + } + break; + case 94 : + // JPA.g:1:599: NAMED_PARAMETER + { + mNAMED_PARAMETER(); + + } + break; + case 95 : + // JPA.g:1:615: WS + { + mWS(); + + } + break; + case 96 : + // JPA.g:1:618: COMMENT + { + mCOMMENT(); + + } + break; + case 97 : + // JPA.g:1:626: LINE_COMMENT + { + mLINE_COMMENT(); + + } + break; + case 98 : + // JPA.g:1:639: ESCAPE_CHARACTER + { + mESCAPE_CHARACTER(); + + } + break; + case 99 : + // JPA.g:1:656: INT_NUMERAL + { + mINT_NUMERAL(); + + } + break; + + } + + } + + + protected DFA10 dfa10 = new DFA10(this); + static final String DFA10_eotS = + "\1\uffff\7\47\1\106\1\uffff\6\47\2\uffff\2\47\3\uffff\2\47\1\uffff"+ + "\1\140\1\142\1\uffff\1\145\2\47\1\53\3\uffff\2\47\6\uffff\2\47\1"+ + "\162\22\47\1\u008b\2\47\1\u008e\2\uffff\3\47\1\u0096\1\u0097\4\47"+ + "\1\u009c\6\47\3\uffff\4\47\10\uffff\2\47\1\uffff\2\47\4\uffff\2"+ + "\47\1\u00b2\1\uffff\1\u00b3\1\u00b4\1\u00b5\1\u00b6\1\u00b7\2\47"+ + "\1\u00ba\1\u00bb\1\u00bd\1\47\1\u00bf\1\47\1\u00c1\12\47\1\uffff"+ + "\2\47\1\uffff\7\47\2\uffff\4\47\1\uffff\2\47\1\u00db\1\u00dc\1\u00dd"+ + "\2\47\1\uffff\11\47\2\uffff\1\47\1\u00ec\6\uffff\1\u00ed\1\47\2"+ + "\uffff\1\47\1\uffff\1\47\1\uffff\1\47\1\uffff\3\47\1\u00f5\1\u00f6"+ + "\1\u00f7\6\47\1\u00fe\2\47\1\u0101\3\47\1\u0105\1\47\1\u0107\2\47"+ + "\1\u010a\3\uffff\1\u010b\1\47\1\uffff\1\u010e\3\47\1\u0112\2\47"+ + "\1\u0115\1\47\1\uffff\1\47\2\uffff\2\47\1\u011a\4\47\3\uffff\1\u011f"+ + "\2\47\1\u0122\1\u0123\1\47\1\uffff\2\47\1\uffff\1\47\1\u0128\1\u0129"+ + "\1\uffff\1\u012a\1\uffff\1\u012b\1\47\2\uffff\1\u012d\2\uffff\1"+ + "\47\1\u0132\1\47\1\uffff\1\47\1\u0135\1\uffff\1\u0136\1\u0137\1"+ + "\47\1\u0139\1\uffff\1\u013a\1\47\1\u013c\1\u013d\1\uffff\1\u013e"+ + "\1\47\2\uffff\1\u0140\1\u0141\1\47\1\u0143\4\uffff\1\47\4\uffff"+ + "\1\u0145\1\uffff\1\u0146\1\47\3\uffff\1\47\2\uffff\1\47\3\uffff"+ + "\1\47\2\uffff\1\u014b\1\uffff\1\u014c\2\uffff\1\47\1\u014e\2\47"+ + "\2\uffff\1\u0152\1\uffff\1\u0153\2\47\2\uffff\4\47\1\u015a\1\u015c"+ + "\1\uffff\1\47\1\uffff\3\47\1\u0161\1\uffff"; + static final String DFA10_eofS = + "\u0162\uffff"; + static final String DFA10_minS = + "\1\11\1\101\1\102\2\101\1\105\1\117\1\102\1\123\1\uffff\1\105\1"+ + "\116\1\117\1\105\1\122\1\105\2\uffff\1\105\1\110\1\102\2\uffff\1"+ + "\105\1\115\1\uffff\2\75\1\uffff\1\52\1\122\1\120\1\170\3\uffff\1"+ + "\162\1\141\1\0\5\uffff\1\126\1\125\1\44\1\107\1\104\1\114\3\123"+ + "\1\131\1\130\1\116\1\104\1\115\1\102\1\103\1\115\1\122\1\132\1\116"+ + "\1\122\1\44\1\124\1\112\1\44\2\uffff\1\101\1\113\1\103\2\44\1\111"+ + "\1\124\2\117\1\44\2\124\1\127\1\124\1\114\1\105\1\uffff\1\101\1"+ + "\uffff\1\101\1\103\1\120\1\111\10\uffff\1\101\1\120\1\uffff\1\165"+ + "\1\154\2\0\2\uffff\1\111\1\122\1\44\1\uffff\5\44\1\103\1\124\3\44"+ + "\1\124\1\44\1\102\1\44\1\123\1\105\1\117\1\105\1\124\1\105\1\116"+ + "\1\103\1\122\1\105\1\uffff\2\105\1\uffff\1\124\1\107\1\104\1\105"+ + "\1\101\2\105\2\uffff\1\116\1\103\1\115\1\125\1\uffff\1\127\1\110"+ + "\3\44\1\114\1\122\1\124\1\122\1\101\1\124\1\123\1\115\1\111\1\105"+ + "\1\145\1\163\2\uffff\1\116\1\44\6\uffff\1\44\1\111\2\uffff\1\124"+ + "\1\uffff\1\110\1\uffff\1\105\1\uffff\1\124\1\103\1\116\3\44\1\124"+ + "\1\101\1\105\2\122\1\103\1\44\1\124\1\111\1\44\1\124\2\122\1\44"+ + "\1\110\1\44\1\120\1\105\1\44\3\uffff\1\44\2\105\1\44\1\120\1\131"+ + "\1\124\1\44\1\114\1\122\1\44\1\145\1\uffff\1\107\2\uffff\1\116\1"+ + "\105\1\44\2\122\1\124\1\104\3\uffff\1\44\1\124\1\116\2\44\1\124"+ + "\1\uffff\1\110\1\116\1\uffff\1\105\2\44\1\uffff\1\44\1\uffff\1\44"+ + "\1\105\2\uffff\1\44\1\101\1\uffff\1\105\1\44\1\123\1\uffff\1\111"+ + "\1\44\1\uffff\2\44\1\103\1\44\1\uffff\1\44\1\111\2\44\1\uffff\1"+ + "\44\1\124\2\uffff\2\44\1\107\1\44\4\uffff\1\116\4\uffff\1\44\1\uffff"+ + "\1\44\1\116\3\uffff\1\124\2\uffff\1\116\3\uffff\1\137\2\uffff\1"+ + "\44\1\uffff\1\44\2\uffff\1\107\1\44\1\107\1\104\2\uffff\1\44\1\uffff"+ + "\1\44\1\101\1\111\2\uffff\1\124\1\115\2\105\2\44\1\uffff\1\124\1"+ + "\uffff\1\101\1\115\1\120\1\44\1\uffff"; + static final String DFA10_maxS = + "\1\u052f\1\117\1\126\1\111\1\117\3\125\1\123\1\uffff\1\117\1\123"+ + "\1\117\2\122\1\131\2\uffff\1\125\1\110\1\124\2\uffff\1\105\1\130"+ + "\1\uffff\1\76\1\75\1\uffff\1\57\1\122\1\120\1\170\3\uffff\1\162"+ + "\1\141\1\uffff\5\uffff\1\126\1\125\1\172\1\107\1\131\1\114\3\123"+ + "\1\131\1\130\2\116\2\115\1\114\1\115\1\122\1\132\1\125\1\122\1\172"+ + "\1\124\1\112\1\172\2\uffff\1\116\1\113\1\127\2\172\1\111\1\124\2"+ + "\117\1\172\2\124\2\127\1\114\1\105\1\uffff\1\101\1\uffff\1\101\1"+ + "\103\1\120\1\111\10\uffff\1\111\1\120\1\uffff\1\165\1\154\2\uffff"+ + "\2\uffff\1\111\1\122\1\172\1\uffff\5\172\1\103\1\124\3\172\1\124"+ + "\1\172\1\102\1\172\1\123\1\105\1\117\1\105\1\124\1\105\1\116\1\103"+ + "\1\122\1\105\1\uffff\2\105\1\uffff\1\124\1\107\1\104\1\105\1\101"+ + "\2\105\2\uffff\1\116\1\103\1\115\1\125\1\uffff\1\127\1\110\3\172"+ + "\1\114\1\122\1\124\1\122\1\101\1\124\1\123\1\115\1\111\1\105\1\145"+ + "\1\163\2\uffff\1\116\1\172\6\uffff\1\172\1\111\2\uffff\1\124\1\uffff"+ + "\1\110\1\uffff\1\105\1\uffff\1\124\1\103\1\116\3\172\1\124\1\101"+ + "\1\105\2\122\1\103\1\172\1\124\1\111\1\172\1\124\2\122\1\172\1\110"+ + "\1\172\1\120\1\105\1\172\3\uffff\1\172\2\105\1\172\1\120\1\131\1"+ + "\124\1\172\1\114\1\122\1\172\1\145\1\uffff\1\107\2\uffff\1\116\1"+ + "\105\1\172\2\122\1\124\1\104\3\uffff\1\172\1\124\1\116\2\172\1\124"+ + "\1\uffff\1\110\1\116\1\uffff\1\105\2\172\1\uffff\1\172\1\uffff\1"+ + "\172\1\105\2\uffff\1\172\1\105\1\uffff\1\105\1\172\1\123\1\uffff"+ + "\1\111\1\172\1\uffff\2\172\1\103\1\172\1\uffff\1\172\1\111\2\172"+ + "\1\uffff\1\172\1\124\2\uffff\2\172\1\107\1\172\4\uffff\1\116\4\uffff"+ + "\1\172\1\uffff\1\172\1\116\3\uffff\1\124\2\uffff\1\116\3\uffff\1"+ + "\137\2\uffff\1\172\1\uffff\1\172\2\uffff\1\107\1\172\1\107\1\124"+ + "\2\uffff\1\172\1\uffff\1\172\1\101\1\111\2\uffff\1\124\1\115\2\105"+ + "\2\172\1\uffff\1\124\1\uffff\1\101\1\115\1\120\1\172\1\uffff"; + static final String DFA10_acceptS = + "\11\uffff\1\14\6\uffff\1\30\1\33\3\uffff\1\43\1\44\2\uffff\1\73"+ + "\2\uffff\1\101\4\uffff\1\125\1\126\1\127\3\uffff\1\134\1\135\1\136"+ + "\1\137\1\143\31\uffff\1\32\1\13\20\uffff\1\41\1\uffff\1\56\4\uffff"+ + "\1\74\1\100\1\77\1\76\1\75\1\140\1\141\1\102\2\uffff\1\124\4\uffff"+ + "\1\142\1\133\3\uffff\1\31\30\uffff\1\11\2\uffff\1\66\7\uffff\1\34"+ + "\1\62\4\uffff\1\25\21\uffff\1\132\1\133\2\uffff\1\2\1\4\1\12\1\71"+ + "\1\70\1\105\2\uffff\1\47\1\5\1\uffff\1\6\1\uffff\1\107\1\uffff\1"+ + "\7\31\uffff\1\36\1\40\1\42\14\uffff\1\132\1\uffff\1\50\1\3\7\uffff"+ + "\1\72\1\106\1\110\6\uffff\1\16\2\uffff\1\60\3\uffff\1\21\1\uffff"+ + "\1\27\2\uffff\1\123\1\63\2\uffff\1\45\3\uffff\1\116\2\uffff\1\130"+ + "\4\uffff\1\46\4\uffff\1\10\2\uffff\1\23\1\17\4\uffff\1\117\1\20"+ + "\1\22\1\24\1\uffff\1\37\1\53\1\54\1\55\1\uffff\1\64\2\uffff\1\120"+ + "\1\131\1\1\1\uffff\1\51\1\65\1\uffff\1\26\1\52\1\114\1\uffff\1\35"+ + "\1\103\1\uffff\1\104\1\uffff\1\61\1\67\4\uffff\1\121\1\57\1\uffff"+ + "\1\15\3\uffff\1\122\1\115\6\uffff\1\111\1\uffff\1\112\4\uffff\1"+ + "\113"; + static final String DFA10_specialS = + "\46\uffff\1\1\104\uffff\1\2\1\0\u00f5\uffff}>"; + static final String[] DFA10_transitionS = { + "\2\52\1\uffff\2\52\22\uffff\1\52\3\uffff\1\42\2\uffff\1\46"+ + "\1\10\1\11\1\34\1\25\1\20\1\26\1\21\1\35\1\40\11\53\1\51\1\uffff"+ + "\1\32\1\31\1\33\1\41\1\24\1\2\1\17\1\6\1\3\1\30\1\15\1\16\1"+ + "\1\1\13\1\14\1\47\1\12\1\4\1\22\1\7\3\47\1\5\1\36\1\37\1\47"+ + "\1\23\1\47\1\27\1\47\4\uffff\1\47\1\uffff\5\47\1\45\15\47\1"+ + "\44\6\47\2\uffff\1\43\u0382\uffff\u0130\50", + "\1\54\15\uffff\1\55", + "\1\62\11\uffff\1\61\1\uffff\1\60\4\uffff\1\56\2\uffff\1\57", + "\1\65\3\uffff\1\63\3\uffff\1\64", + "\1\66\3\uffff\1\71\3\uffff\1\67\5\uffff\1\70", + "\1\73\3\uffff\1\76\5\uffff\1\74\1\uffff\1\75\3\uffff\1\72", + "\1\77\5\uffff\1\100", + "\1\103\3\uffff\1\104\13\uffff\1\101\2\uffff\1\102", + "\1\105", + "", + "\1\107\3\uffff\1\110\5\uffff\1\111", + "\1\112\4\uffff\1\113", + "\1\114", + "\1\115\14\uffff\1\116", + "\1\117", + "\1\121\11\uffff\1\122\11\uffff\1\120", + "", + "", + "\1\123\11\uffff\1\124\5\uffff\1\125", + "\1\126", + "\1\127\1\uffff\1\130\17\uffff\1\131", + "", + "", + "\1\132", + "\1\134\5\uffff\1\133\4\uffff\1\135", + "", + "\1\137\1\136", + "\1\141", + "", + "\1\143\4\uffff\1\144", + "\1\146", + "\1\147", + "\1\150", + "", + "", + "", + "\1\151", + "\1\152", + "\42\154\1\155\4\154\1\156\6\154\1\153\55\154\1\156\uffa3\154", + "", + "", + "", + "", + "", + "\1\157", + "\1\160", + "\1\47\13\uffff\12\47\7\uffff\2\47\1\161\27\47\4\uffff\1\47"+ + "\1\uffff\32\47", + "\1\163", + "\1\164\24\uffff\1\165", + "\1\166", + "\1\167", + "\1\170", + "\1\171", + "\1\172", + "\1\173", + "\1\174", + "\1\176\11\uffff\1\175", + "\1\177", + "\1\u0081\12\uffff\1\u0080", + "\1\u0083\10\uffff\1\u0082", + "\1\u0084", + "\1\u0085", + "\1\u0086", + "\1\u0088\6\uffff\1\u0087", + "\1\u0089", + "\1\47\13\uffff\12\47\7\uffff\3\47\1\u008a\26\47\4\uffff\1"+ + "\47\1\uffff\32\47", + "\1\u008c", + "\1\u008d", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "", + "\1\u0091\4\uffff\1\u008f\7\uffff\1\u0090", + "\1\u0092", + "\1\u0093\23\uffff\1\u0094", + "\1\47\13\uffff\12\47\7\uffff\15\47\1\u0095\14\47\4\uffff\1"+ + "\47\1\uffff\32\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0098", + "\1\u0099", + "\1\u009a", + "\1\u009b", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u009d", + "\1\u009e", + "\1\u009f", + "\1\u00a0\2\uffff\1\u00a1", + "\1\u00a2", + "\1\u00a3", + "", + "\1\u00a4", + "", + "\1\u00a5", + "\1\u00a6", + "\1\u00a7", + "\1\u00a8", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u00aa\7\uffff\1\u00a9", + "\1\u00ab", + "", + "\1\u00ac", + "\1\u00ad", + "\42\156\1\uffff\4\156\1\u00ae\uffd8\156", + "\42\156\1\uffff\4\156\1\u00af\uffd8\156", + "", + "", + "\1\u00b0", + "\1\u00b1", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00b8", + "\1\u00b9", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\24\47\1\u00bc\5\47\4\uffff\1"+ + "\47\1\uffff\32\47", + "\1\u00be", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00c0", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00c2", + "\1\u00c3", + "\1\u00c4", + "\1\u00c5", + "\1\u00c6", + "\1\u00c7", + "\1\u00c8", + "\1\u00c9", + "\1\u00ca", + "\1\u00cb", + "", + "\1\u00cc", + "\1\u00cd", + "", + "\1\u00ce", + "\1\u00cf", + "\1\u00d0", + "\1\u00d1", + "\1\u00d2", + "\1\u00d3", + "\1\u00d4", + "", + "", + "\1\u00d5", + "\1\u00d6", + "\1\u00d7", + "\1\u00d8", + "", + "\1\u00d9", + "\1\u00da", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00de", + "\1\u00df", + "\1\u00e0", + "\1\u00e1", + "\1\u00e2", + "\1\u00e3", + "\1\u00e4", + "\1\u00e5", + "\1\u00e6", + "\1\u00e7", + "\1\u00e8", + "\1\u00e9", + "", + "", + "\1\u00eb", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "", + "", + "", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00ee", + "", + "", + "\1\u00ef", + "", + "\1\u00f0", + "", + "\1\u00f1", + "", + "\1\u00f2", + "\1\u00f3", + "\1\u00f4", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00f8", + "\1\u00f9", + "\1\u00fa", + "\1\u00fb", + "\1\u00fc", + "\1\u00fd", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u00ff", + "\1\u0100", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0102", + "\1\u0103", + "\1\u0104", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0106", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0108", + "\1\u0109", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u010c", + "\1\u010d", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u010f", + "\1\u0110", + "\1\u0111", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0113", + "\1\u0114", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0116", + "", + "\1\u0117", + "", + "", + "\1\u0118", + "\1\u0119", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u011b", + "\1\u011c", + "\1\u011d", + "\1\u011e", + "", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0120", + "\1\u0121", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0124", + "", + "\1\u0125", + "\1\u0126", + "", + "\1\u0127", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u012c", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u012f\1\u012e\2\uffff\1\u0130", + "", + "\1\u0131", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0133", + "", + "\1\u0134", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0138", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u013b", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u013f", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0142", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "", + "", + "", + "\1\u0144", + "", + "", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0147", + "", + "", + "", + "\1\u0148", + "", + "", + "\1\u0149", + "", + "", + "", + "\1\u014a", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "", + "\1\u014d", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u014f", + "\1\u0150\17\uffff\1\u0151", + "", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\u0154", + "\1\u0155", + "", + "", + "\1\u0156", + "\1\u0157", + "\1\u0158", + "\1\u0159", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "\1\47\13\uffff\12\47\7\uffff\22\47\1\u015b\7\47\4\uffff\1"+ + "\47\1\uffff\32\47", + "", + "\1\u015d", + "", + "\1\u015e", + "\1\u015f", + "\1\u0160", + "\1\47\13\uffff\12\47\7\uffff\32\47\4\uffff\1\47\1\uffff\32"+ + "\47", + "" + }; + + static final short[] DFA10_eot = DFA.unpackEncodedString(DFA10_eotS); + static final short[] DFA10_eof = DFA.unpackEncodedString(DFA10_eofS); + static final char[] DFA10_min = DFA.unpackEncodedStringToUnsignedChars(DFA10_minS); + static final char[] DFA10_max = DFA.unpackEncodedStringToUnsignedChars(DFA10_maxS); + static final short[] DFA10_accept = DFA.unpackEncodedString(DFA10_acceptS); + static final short[] DFA10_special = DFA.unpackEncodedString(DFA10_specialS); + static final short[][] DFA10_transition; + + static { + int numStates = DFA10_transitionS.length; + DFA10_transition = new short[numStates][]; + for (int i=0; i='\u0000' && LA10_108<='!')||(LA10_108>='#' && LA10_108<='&')||(LA10_108>='(' && LA10_108<='\uFFFF')) ) {s = 110;} + + if ( s>=0 ) return s; + break; + case 1 : + int LA10_38 = input.LA(1); + + s = -1; + if ( (LA10_38=='.') ) {s = 107;} + + else if ( ((LA10_38>='\u0000' && LA10_38<='!')||(LA10_38>='#' && LA10_38<='&')||(LA10_38>='(' && LA10_38<='-')||(LA10_38>='/' && LA10_38<='[')||(LA10_38>=']' && LA10_38<='\uFFFF')) ) {s = 108;} + + else if ( (LA10_38=='\"') ) {s = 109;} + + else if ( (LA10_38=='\''||LA10_38=='\\') ) {s = 110;} + + if ( s>=0 ) return s; + break; + case 2 : + int LA10_107 = input.LA(1); + + s = -1; + if ( (LA10_107=='\'') ) {s = 174;} + + else if ( ((LA10_107>='\u0000' && LA10_107<='!')||(LA10_107>='#' && LA10_107<='&')||(LA10_107>='(' && LA10_107<='\uFFFF')) ) {s = 110;} + + if ( s>=0 ) return s; + break; + } + NoViableAltException nvae = + new NoViableAltException(getDescription(), 10, _s, input); + error(nvae); + throw nvae; + } + } + + @Override + public void emitErrorMessage(String msg) { + //do nothing + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPAParser.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPAParser.java index 22160d5f12..f16cd54171 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPAParser.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr/JPAParser.java @@ -1,13550 +1,13550 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * 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. - * - */ - -// $ANTLR 3.2 Sep 23, 2009 12:02:23 JPA.g 2012-08-06 14:42:50 - -package com.haulmont.cuba.core.sys.jpql.antlr; - -import com.haulmont.cuba.core.sys.jpql.tree.*; -import org.antlr.runtime.*; -import org.antlr.runtime.tree.CommonTreeAdaptor; -import org.antlr.runtime.tree.RewriteRuleSubtreeStream; -import org.antlr.runtime.tree.RewriteRuleTokenStream; -import org.antlr.runtime.tree.TreeAdaptor; - -public class JPAParser extends Parser { - public static final String[] tokenNames = new String[] { - "", "", "", "", "T_SELECTED_ITEMS", "T_SELECTED_ITEM", "T_SOURCES", "T_SOURCE", "T_SELECTED_FIELD", "T_SELECTED_ENTITY", "T_ID_VAR", "T_JOIN_VAR", "T_COLLECTION_MEMBER", "T_QUERY", "T_CONDITION", "T_SIMPLE_CONDITION", "T_PARAMETER", "T_GROUP_BY", "T_ORDER_BY", "T_ORDER_BY_FIELD", "T_AGGREGATE_EXPR", "HAVING", "ASC", "DESC", "AVG", "MAX", "MIN", "SUM", "COUNT", "OR", "AND", "LPAREN", "RPAREN", "DISTINCT", "LEFT", "OUTER", "INNER", "JOIN", "FETCH", "ORDER", "GROUP", "BY", "INT_NUMERAL", "ESCAPE_CHARACTER", "STRINGLITERAL", "TRIM_CHARACTER", "WORD", "NAMED_PARAMETER", "RUSSIAN_SYMBOLS", "WS", "COMMENT", "LINE_COMMENT", "'SELECT'", "'FROM'", "','", "'AS'", "'(SELECT'", "'.'", "'IN'", "'OBJECT'", "'NEW'", "'WHERE'", "'NOT'", "'@BETWEEN'", "'NOW'", "'+'", "'-'", "'YEAR'", "'MONTH'", "'DAY'", "'HOUR'", "'MINUTE'", "'SECOND'", "'@DATEBEFORE'", "'@DATEAFTER'", "'@DATEEQUALS'", "'@TODAY'", "'BETWEEN'", "'LIKE'", "'ESCAPE'", "'IS'", "'NULL'", "'EMPTY'", "'MEMBER'", "'OF'", "'EXISTS'", "'ALL'", "'ANY'", "'SOME'", "'='", "'<>'", "'>'", "'>='", "'<'", "'<='", "'*'", "'/'", "'LENGTH'", "'LOCATE'", "'ABS'", "'SQRT'", "'MOD'", "'SIZE'", "'CURRENT_DATE'", "'CURRENT_TIME'", "'CURRENT_TIMESTAMP'", "'CONCAT'", "'SUBSTRING'", "'TRIM'", "'LOWER'", "'UPPER'", "'LEADING'", "'TRAILING'", "'BOTH'", "'0x'", "'?'", "'${'", "'}'", "'true'", "'false'" - }; - public static final int T_JOIN_VAR=11; - public static final int T_AGGREGATE_EXPR=20; - public static final int COUNT=28; - public static final int T_ORDER_BY=18; - public static final int EOF=-1; - public static final int WORD=46; - public static final int T__93=93; - public static final int T__94=94; - public static final int RPAREN=32; - public static final int T__91=91; - public static final int T__92=92; - public static final int T__90=90; - public static final int TRIM_CHARACTER=45; - public static final int T_SELECTED_ITEM=5; - public static final int COMMENT=50; - public static final int T__99=99; - public static final int T__98=98; - public static final int T__97=97; - public static final int T__96=96; - public static final int T_QUERY=13; - public static final int T__95=95; - public static final int T__80=80; - public static final int T__81=81; - public static final int T__82=82; - public static final int T__83=83; - public static final int ASC=22; - public static final int LINE_COMMENT=51; - public static final int T__85=85; - public static final int T__84=84; - public static final int T__87=87; - public static final int T__86=86; - public static final int T__89=89; - public static final int T__88=88; - public static final int GROUP=40; - public static final int WS=49; - public static final int T__71=71; - public static final int T__72=72; - public static final int FETCH=38; - public static final int T__70=70; - public static final int T_SELECTED_FIELD=8; - public static final int OR=29; - public static final int T__76=76; - public static final int T__75=75; - public static final int DISTINCT=33; - public static final int T__74=74; - public static final int T__73=73; - public static final int T__79=79; - public static final int T__78=78; - public static final int T__77=77; - public static final int T__68=68; - public static final int T__69=69; - public static final int T__66=66; - public static final int T__67=67; - public static final int T_SELECTED_ITEMS=4; - public static final int T__64=64; - public static final int T__65=65; - public static final int INNER=36; - public static final int T__62=62; - public static final int T__63=63; - public static final int ORDER=39; - public static final int T__118=118; - public static final int T_SOURCE=7; - public static final int T__119=119; - public static final int T__116=116; - public static final int T_ID_VAR=10; - public static final int T__117=117; - public static final int T_SIMPLE_CONDITION=15; - public static final int T__114=114; - public static final int T__115=115; - public static final int MAX=25; - public static final int AND=30; - public static final int SUM=27; - public static final int T__61=61; - public static final int T__60=60; - public static final int RUSSIAN_SYMBOLS=48; - public static final int LPAREN=31; - public static final int T__55=55; - public static final int T__56=56; - public static final int T__57=57; - public static final int T__58=58; - public static final int T__52=52; - public static final int T__53=53; - public static final int T__54=54; - public static final int T__107=107; - public static final int T__108=108; - public static final int T__109=109; - public static final int LEFT=34; - public static final int AVG=24; - public static final int T_ORDER_BY_FIELD=19; - public static final int T__59=59; - public static final int T__103=103; - public static final int T__104=104; - public static final int T__105=105; - public static final int T__106=106; - public static final int T__111=111; - public static final int T__110=110; - public static final int T__113=113; - public static final int T__112=112; - public static final int T_GROUP_BY=17; - public static final int OUTER=35; - public static final int BY=41; - public static final int T_CONDITION=14; - public static final int T_SELECTED_ENTITY=9; - public static final int T__102=102; - public static final int HAVING=21; - public static final int T__101=101; - public static final int MIN=26; - public static final int T__100=100; - public static final int T_PARAMETER=16; - public static final int JOIN=37; - public static final int NAMED_PARAMETER=47; - public static final int ESCAPE_CHARACTER=43; - public static final int INT_NUMERAL=42; - public static final int STRINGLITERAL=44; - public static final int T_COLLECTION_MEMBER=12; - public static final int DESC=23; - public static final int T_SOURCES=6; - - // delegates - // delegators - - - public JPAParser(TokenStream input) { - this(input, new RecognizerSharedState()); - } - public JPAParser(TokenStream input, RecognizerSharedState state) { - super(input, state); - - } - - protected TreeAdaptor adaptor = new CommonTreeAdaptor(); - - public void setTreeAdaptor(TreeAdaptor adaptor) { - this.adaptor = adaptor; - } - public TreeAdaptor getTreeAdaptor() { - return adaptor; - } - - public String[] getTokenNames() { return JPAParser.tokenNames; } - public String getGrammarFileName() { return "JPA.g"; } - - - public static class ql_statement_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "ql_statement" - // JPA.g:85:1: ql_statement : select_statement ; - public final JPAParser.ql_statement_return ql_statement() throws RecognitionException { - JPAParser.ql_statement_return retval = new JPAParser.ql_statement_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.select_statement_return select_statement1 = null; - - - - try { - // JPA.g:86:5: ( select_statement ) - // JPA.g:86:7: select_statement - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_select_statement_in_ql_statement426); - select_statement1=select_statement(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, select_statement1.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "ql_statement" - - public static class select_statement_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "select_statement" - // JPA.g:88:1: select_statement : sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ; - public final JPAParser.select_statement_return select_statement() throws RecognitionException { - JPAParser.select_statement_return retval = new JPAParser.select_statement_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token sl=null; - JPAParser.select_clause_return select_clause2 = null; - - JPAParser.from_clause_return from_clause3 = null; - - JPAParser.where_clause_return where_clause4 = null; - - JPAParser.groupby_clause_return groupby_clause5 = null; - - JPAParser.having_clause_return having_clause6 = null; - - JPAParser.orderby_clause_return orderby_clause7 = null; - - - Object sl_tree=null; - RewriteRuleTokenStream stream_52=new RewriteRuleTokenStream(adaptor,"token 52"); - RewriteRuleSubtreeStream stream_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule select_clause"); - RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); - RewriteRuleSubtreeStream stream_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule from_clause"); - RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); - RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); - RewriteRuleSubtreeStream stream_orderby_clause=new RewriteRuleSubtreeStream(adaptor,"rule orderby_clause"); - try { - // JPA.g:89:5: (sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ) - // JPA.g:89:8: sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? - { - sl=(Token)match(input,52,FOLLOW_52_in_select_statement441); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_52.add(sl); - - pushFollow(FOLLOW_select_clause_in_select_statement443); - select_clause2=select_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_select_clause.add(select_clause2.getTree()); - pushFollow(FOLLOW_from_clause_in_select_statement445); - from_clause3=from_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_from_clause.add(from_clause3.getTree()); - // JPA.g:89:46: ( where_clause )? - int alt1=2; - int LA1_0 = input.LA(1); - - if ( (LA1_0==61) ) { - alt1=1; - } - switch (alt1) { - case 1 : - // JPA.g:89:47: where_clause - { - pushFollow(FOLLOW_where_clause_in_select_statement448); - where_clause4=where_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_where_clause.add(where_clause4.getTree()); - - } - break; - - } - - // JPA.g:89:62: ( groupby_clause )? - int alt2=2; - int LA2_0 = input.LA(1); - - if ( (LA2_0==GROUP) ) { - alt2=1; - } - switch (alt2) { - case 1 : - // JPA.g:89:63: groupby_clause - { - pushFollow(FOLLOW_groupby_clause_in_select_statement453); - groupby_clause5=groupby_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause5.getTree()); - - } - break; - - } - - // JPA.g:89:80: ( having_clause )? - int alt3=2; - int LA3_0 = input.LA(1); - - if ( (LA3_0==HAVING) ) { - alt3=1; - } - switch (alt3) { - case 1 : - // JPA.g:89:81: having_clause - { - pushFollow(FOLLOW_having_clause_in_select_statement458); - having_clause6=having_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_having_clause.add(having_clause6.getTree()); - - } - break; - - } - - // JPA.g:89:96: ( orderby_clause )? - int alt4=2; - int LA4_0 = input.LA(1); - - if ( (LA4_0==ORDER) ) { - alt4=1; - } - switch (alt4) { - case 1 : - // JPA.g:89:97: orderby_clause - { - pushFollow(FOLLOW_orderby_clause_in_select_statement462); - orderby_clause7=orderby_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_orderby_clause.add(orderby_clause7.getTree()); - - } - break; - - } - - - - // AST REWRITE - // elements: orderby_clause, having_clause, groupby_clause, select_clause, from_clause, where_clause - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 90:6: -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) - { - // JPA.g:90:9: ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, sl), root_1); - - // JPA.g:90:35: ( select_clause )? - if ( stream_select_clause.hasNext() ) { - adaptor.addChild(root_1, stream_select_clause.nextTree()); - - } - stream_select_clause.reset(); - adaptor.addChild(root_1, stream_from_clause.nextTree()); - // JPA.g:90:64: ( where_clause )? - if ( stream_where_clause.hasNext() ) { - adaptor.addChild(root_1, stream_where_clause.nextTree()); - - } - stream_where_clause.reset(); - // JPA.g:90:80: ( groupby_clause )? - if ( stream_groupby_clause.hasNext() ) { - adaptor.addChild(root_1, stream_groupby_clause.nextTree()); - - } - stream_groupby_clause.reset(); - // JPA.g:90:98: ( having_clause )? - if ( stream_having_clause.hasNext() ) { - adaptor.addChild(root_1, stream_having_clause.nextTree()); - - } - stream_having_clause.reset(); - // JPA.g:90:115: ( orderby_clause )? - if ( stream_orderby_clause.hasNext() ) { - adaptor.addChild(root_1, stream_orderby_clause.nextTree()); - - } - stream_orderby_clause.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "select_statement" - - public static class from_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "from_clause" - // JPA.g:92:1: from_clause : fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) ; - public final JPAParser.from_clause_return from_clause() throws RecognitionException { - JPAParser.from_clause_return retval = new JPAParser.from_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token fr=null; - Token char_literal9=null; - JPAParser.identification_variable_declaration_return identification_variable_declaration8 = null; - - JPAParser.identification_variable_or_collection_declaration_return identification_variable_or_collection_declaration10 = null; - - - Object fr_tree=null; - Object char_literal9_tree=null; - RewriteRuleTokenStream stream_53=new RewriteRuleTokenStream(adaptor,"token 53"); - RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); - RewriteRuleSubtreeStream stream_identification_variable_or_collection_declaration=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable_or_collection_declaration"); - RewriteRuleSubtreeStream stream_identification_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable_declaration"); - try { - // JPA.g:93:5: (fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) ) - // JPA.g:93:7: fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* - { - fr=(Token)match(input,53,FOLLOW_53_in_from_clause523); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_53.add(fr); - - pushFollow(FOLLOW_identification_variable_declaration_in_from_clause525); - identification_variable_declaration8=identification_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable_declaration.add(identification_variable_declaration8.getTree()); - // JPA.g:93:53: ( ',' identification_variable_or_collection_declaration )* - loop5: - do { - int alt5=2; - int LA5_0 = input.LA(1); - - if ( (LA5_0==54) ) { - alt5=1; - } - - - switch (alt5) { - case 1 : - // JPA.g:93:54: ',' identification_variable_or_collection_declaration - { - char_literal9=(Token)match(input,54,FOLLOW_54_in_from_clause528); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_54.add(char_literal9); - - pushFollow(FOLLOW_identification_variable_or_collection_declaration_in_from_clause530); - identification_variable_or_collection_declaration10=identification_variable_or_collection_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable_or_collection_declaration.add(identification_variable_or_collection_declaration10.getTree()); - - } - break; - - default : - break loop5; - } - } while (true); - - - - // AST REWRITE - // elements: identification_variable_or_collection_declaration, identification_variable_declaration - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 94:5: -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) - { - // JPA.g:94:8: ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new FromNode(T_SOURCES, fr), root_1); - - adaptor.addChild(root_1, stream_identification_variable_declaration.nextTree()); - // JPA.g:94:71: ( identification_variable_or_collection_declaration )* - while ( stream_identification_variable_or_collection_declaration.hasNext() ) { - adaptor.addChild(root_1, stream_identification_variable_or_collection_declaration.nextTree()); - - } - stream_identification_variable_or_collection_declaration.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "from_clause" - - public static class identification_variable_or_collection_declaration_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "identification_variable_or_collection_declaration" - // JPA.g:96:1: identification_variable_or_collection_declaration : ( identification_variable_declaration | collection_member_declaration -> ^( T_SOURCE collection_member_declaration ) ); - public final JPAParser.identification_variable_or_collection_declaration_return identification_variable_or_collection_declaration() throws RecognitionException { - JPAParser.identification_variable_or_collection_declaration_return retval = new JPAParser.identification_variable_or_collection_declaration_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.identification_variable_declaration_return identification_variable_declaration11 = null; - - JPAParser.collection_member_declaration_return collection_member_declaration12 = null; - - - RewriteRuleSubtreeStream stream_collection_member_declaration=new RewriteRuleSubtreeStream(adaptor,"rule collection_member_declaration"); - try { - // JPA.g:97:5: ( identification_variable_declaration | collection_member_declaration -> ^( T_SOURCE collection_member_declaration ) ) - int alt6=2; - int LA6_0 = input.LA(1); - - if ( (LA6_0==WORD||LA6_0==56) ) { - alt6=1; - } - else if ( (LA6_0==58) ) { - alt6=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 6, 0, input); - - throw nvae; - } - switch (alt6) { - case 1 : - // JPA.g:97:7: identification_variable_declaration - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_identification_variable_declaration_in_identification_variable_or_collection_declaration563); - identification_variable_declaration11=identification_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable_declaration11.getTree()); - - } - break; - case 2 : - // JPA.g:98:7: collection_member_declaration - { - pushFollow(FOLLOW_collection_member_declaration_in_identification_variable_or_collection_declaration571); - collection_member_declaration12=collection_member_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_collection_member_declaration.add(collection_member_declaration12.getTree()); - - - // AST REWRITE - // elements: collection_member_declaration - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 98:37: -> ^( T_SOURCE collection_member_declaration ) - { - // JPA.g:98:40: ^( T_SOURCE collection_member_declaration ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_1); - - adaptor.addChild(root_1, stream_collection_member_declaration.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "identification_variable_or_collection_declaration" - - public static class identification_variable_declaration_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "identification_variable_declaration" - // JPA.g:100:1: identification_variable_declaration : range_variable_declaration ( joined_clause )* -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) ; - public final JPAParser.identification_variable_declaration_return identification_variable_declaration() throws RecognitionException { - JPAParser.identification_variable_declaration_return retval = new JPAParser.identification_variable_declaration_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.range_variable_declaration_return range_variable_declaration13 = null; - - JPAParser.joined_clause_return joined_clause14 = null; - - - RewriteRuleSubtreeStream stream_joined_clause=new RewriteRuleSubtreeStream(adaptor,"rule joined_clause"); - RewriteRuleSubtreeStream stream_range_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule range_variable_declaration"); - try { - // JPA.g:101:5: ( range_variable_declaration ( joined_clause )* -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) ) - // JPA.g:101:7: range_variable_declaration ( joined_clause )* - { - pushFollow(FOLLOW_range_variable_declaration_in_identification_variable_declaration594); - range_variable_declaration13=range_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_range_variable_declaration.add(range_variable_declaration13.getTree()); - // JPA.g:101:34: ( joined_clause )* - loop7: - do { - int alt7=2; - int LA7_0 = input.LA(1); - - if ( (LA7_0==LEFT||(LA7_0>=INNER && LA7_0<=JOIN)) ) { - alt7=1; - } - - - switch (alt7) { - case 1 : - // JPA.g:0:0: joined_clause - { - pushFollow(FOLLOW_joined_clause_in_identification_variable_declaration596); - joined_clause14=joined_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_joined_clause.add(joined_clause14.getTree()); - - } - break; - - default : - break loop7; - } - } while (true); - - - - // AST REWRITE - // elements: joined_clause, range_variable_declaration - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 102:5: -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) - { - // JPA.g:102:8: ^( T_SOURCE range_variable_declaration ( joined_clause )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_1); - - adaptor.addChild(root_1, stream_range_variable_declaration.nextTree()); - // JPA.g:102:67: ( joined_clause )* - while ( stream_joined_clause.hasNext() ) { - adaptor.addChild(root_1, stream_joined_clause.nextTree()); - - } - stream_joined_clause.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "identification_variable_declaration" - - public static class joined_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "joined_clause" - // JPA.g:104:1: joined_clause : ( join | fetch_join ); - public final JPAParser.joined_clause_return joined_clause() throws RecognitionException { - JPAParser.joined_clause_return retval = new JPAParser.joined_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.join_return join15 = null; - - JPAParser.fetch_join_return fetch_join16 = null; - - - - try { - // JPA.g:105:5: ( join | fetch_join ) - int alt8=2; - switch ( input.LA(1) ) { - case LEFT: - { - int LA8_1 = input.LA(2); - - if ( (LA8_1==OUTER) ) { - int LA8_4 = input.LA(3); - - if ( (LA8_4==JOIN) ) { - int LA8_3 = input.LA(4); - - if ( (LA8_3==FETCH) ) { - alt8=2; - } - else if ( (LA8_3==WORD) ) { - alt8=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 3, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 4, input); - - throw nvae; - } - } - else if ( (LA8_1==JOIN) ) { - int LA8_3 = input.LA(3); - - if ( (LA8_3==FETCH) ) { - alt8=2; - } - else if ( (LA8_3==WORD) ) { - alt8=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 3, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 1, input); - - throw nvae; - } - } - break; - case INNER: - { - int LA8_2 = input.LA(2); - - if ( (LA8_2==JOIN) ) { - int LA8_3 = input.LA(3); - - if ( (LA8_3==FETCH) ) { - alt8=2; - } - else if ( (LA8_3==WORD) ) { - alt8=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 3, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 2, input); - - throw nvae; - } - } - break; - case JOIN: - { - int LA8_3 = input.LA(2); - - if ( (LA8_3==FETCH) ) { - alt8=2; - } - else if ( (LA8_3==WORD) ) { - alt8=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 3, input); - - throw nvae; - } - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 8, 0, input); - - throw nvae; - } - - switch (alt8) { - case 1 : - // JPA.g:105:7: join - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_join_in_joined_clause627); - join15=join(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, join15.getTree()); - - } - break; - case 2 : - // JPA.g:105:14: fetch_join - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_fetch_join_in_joined_clause631); - fetch_join16=fetch_join(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, fetch_join16.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "joined_clause" - - public static class range_variable_declaration_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "range_variable_declaration" - // JPA.g:107:1: range_variable_declaration : range_variable_declaration_source ( 'AS' )? identification_variable -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) ; - public final JPAParser.range_variable_declaration_return range_variable_declaration() throws RecognitionException { - JPAParser.range_variable_declaration_return retval = new JPAParser.range_variable_declaration_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal18=null; - JPAParser.range_variable_declaration_source_return range_variable_declaration_source17 = null; - - JPAParser.identification_variable_return identification_variable19 = null; - - - Object string_literal18_tree=null; - RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_range_variable_declaration_source=new RewriteRuleSubtreeStream(adaptor,"rule range_variable_declaration_source"); - try { - // JPA.g:108:5: ( range_variable_declaration_source ( 'AS' )? identification_variable -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) ) - // JPA.g:108:7: range_variable_declaration_source ( 'AS' )? identification_variable - { - pushFollow(FOLLOW_range_variable_declaration_source_in_range_variable_declaration643); - range_variable_declaration_source17=range_variable_declaration_source(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_range_variable_declaration_source.add(range_variable_declaration_source17.getTree()); - // JPA.g:108:41: ( 'AS' )? - int alt9=2; - int LA9_0 = input.LA(1); - - if ( (LA9_0==55) ) { - alt9=1; - } - switch (alt9) { - case 1 : - // JPA.g:108:42: 'AS' - { - string_literal18=(Token)match(input,55,FOLLOW_55_in_range_variable_declaration646); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_55.add(string_literal18); - - - } - break; - - } - - pushFollow(FOLLOW_identification_variable_in_range_variable_declaration650); - identification_variable19=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable19.getTree()); - - - // AST REWRITE - // elements: range_variable_declaration_source - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 109:7: -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) - { - // JPA.g:109:10: ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new IdentificationVariableNode(T_ID_VAR, (identification_variable19!=null?input.toString(identification_variable19.start,identification_variable19.stop):null)), root_1); - - adaptor.addChild(root_1, stream_range_variable_declaration_source.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "range_variable_declaration" - - public static class range_variable_declaration_source_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "range_variable_declaration_source" - // JPA.g:112:1: range_variable_declaration_source : ( abstract_schema_name | lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ); - public final JPAParser.range_variable_declaration_source_return range_variable_declaration_source() throws RecognitionException { - JPAParser.range_variable_declaration_source_return retval = new JPAParser.range_variable_declaration_source_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token lp=null; - Token rp=null; - JPAParser.abstract_schema_name_return abstract_schema_name20 = null; - - JPAParser.select_clause_return select_clause21 = null; - - JPAParser.from_clause_return from_clause22 = null; - - JPAParser.where_clause_return where_clause23 = null; - - JPAParser.groupby_clause_return groupby_clause24 = null; - - JPAParser.having_clause_return having_clause25 = null; - - JPAParser.orderby_clause_return orderby_clause26 = null; - - - Object lp_tree=null; - Object rp_tree=null; - RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); - RewriteRuleTokenStream stream_56=new RewriteRuleTokenStream(adaptor,"token 56"); - RewriteRuleSubtreeStream stream_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule select_clause"); - RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); - RewriteRuleSubtreeStream stream_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule from_clause"); - RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); - RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); - RewriteRuleSubtreeStream stream_orderby_clause=new RewriteRuleSubtreeStream(adaptor,"rule orderby_clause"); - try { - // JPA.g:113:5: ( abstract_schema_name | lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ) - int alt14=2; - int LA14_0 = input.LA(1); - - if ( (LA14_0==WORD) ) { - alt14=1; - } - else if ( (LA14_0==56) ) { - alt14=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 14, 0, input); - - throw nvae; - } - switch (alt14) { - case 1 : - // JPA.g:113:7: abstract_schema_name - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_abstract_schema_name_in_range_variable_declaration_source686); - abstract_schema_name20=abstract_schema_name(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, abstract_schema_name20.getTree()); - - } - break; - case 2 : - // JPA.g:114:7: lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' - { - lp=(Token)match(input,56,FOLLOW_56_in_range_variable_declaration_source696); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_56.add(lp); - - pushFollow(FOLLOW_select_clause_in_range_variable_declaration_source698); - select_clause21=select_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_select_clause.add(select_clause21.getTree()); - pushFollow(FOLLOW_from_clause_in_range_variable_declaration_source700); - from_clause22=from_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_from_clause.add(from_clause22.getTree()); - // JPA.g:114:46: ( where_clause )? - int alt10=2; - int LA10_0 = input.LA(1); - - if ( (LA10_0==61) ) { - alt10=1; - } - switch (alt10) { - case 1 : - // JPA.g:114:47: where_clause - { - pushFollow(FOLLOW_where_clause_in_range_variable_declaration_source703); - where_clause23=where_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_where_clause.add(where_clause23.getTree()); - - } - break; - - } - - // JPA.g:114:62: ( groupby_clause )? - int alt11=2; - int LA11_0 = input.LA(1); - - if ( (LA11_0==GROUP) ) { - alt11=1; - } - switch (alt11) { - case 1 : - // JPA.g:114:63: groupby_clause - { - pushFollow(FOLLOW_groupby_clause_in_range_variable_declaration_source708); - groupby_clause24=groupby_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause24.getTree()); - - } - break; - - } - - // JPA.g:114:80: ( having_clause )? - int alt12=2; - int LA12_0 = input.LA(1); - - if ( (LA12_0==HAVING) ) { - alt12=1; - } - switch (alt12) { - case 1 : - // JPA.g:114:81: having_clause - { - pushFollow(FOLLOW_having_clause_in_range_variable_declaration_source713); - having_clause25=having_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_having_clause.add(having_clause25.getTree()); - - } - break; - - } - - // JPA.g:114:96: ( orderby_clause )? - int alt13=2; - int LA13_0 = input.LA(1); - - if ( (LA13_0==ORDER) ) { - alt13=1; - } - switch (alt13) { - case 1 : - // JPA.g:114:97: orderby_clause - { - pushFollow(FOLLOW_orderby_clause_in_range_variable_declaration_source717); - orderby_clause26=orderby_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_orderby_clause.add(orderby_clause26.getTree()); - - } - break; - - } - - rp=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_range_variable_declaration_source723); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_RPAREN.add(rp); - - - - // AST REWRITE - // elements: select_clause, having_clause, groupby_clause, from_clause, where_clause, orderby_clause - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 115:6: -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) - { - // JPA.g:115:9: ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, lp, rp), root_1); - - // JPA.g:115:40: ( select_clause )? - if ( stream_select_clause.hasNext() ) { - adaptor.addChild(root_1, stream_select_clause.nextTree()); - - } - stream_select_clause.reset(); - adaptor.addChild(root_1, stream_from_clause.nextTree()); - // JPA.g:115:69: ( where_clause )? - if ( stream_where_clause.hasNext() ) { - adaptor.addChild(root_1, stream_where_clause.nextTree()); - - } - stream_where_clause.reset(); - // JPA.g:115:85: ( groupby_clause )? - if ( stream_groupby_clause.hasNext() ) { - adaptor.addChild(root_1, stream_groupby_clause.nextTree()); - - } - stream_groupby_clause.reset(); - // JPA.g:115:103: ( having_clause )? - if ( stream_having_clause.hasNext() ) { - adaptor.addChild(root_1, stream_having_clause.nextTree()); - - } - stream_having_clause.reset(); - // JPA.g:115:120: ( orderby_clause )? - if ( stream_orderby_clause.hasNext() ) { - adaptor.addChild(root_1, stream_orderby_clause.nextTree()); - - } - stream_orderby_clause.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "range_variable_declaration_source" - - public static class join_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "join" - // JPA.g:118:1: join : join_spec join_association_path_expression ( 'AS' )? identification_variable -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) ; - public final JPAParser.join_return join() throws RecognitionException { - JPAParser.join_return retval = new JPAParser.join_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal29=null; - JPAParser.join_spec_return join_spec27 = null; - - JPAParser.join_association_path_expression_return join_association_path_expression28 = null; - - JPAParser.identification_variable_return identification_variable30 = null; - - - Object string_literal29_tree=null; - RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_join_association_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule join_association_path_expression"); - RewriteRuleSubtreeStream stream_join_spec=new RewriteRuleSubtreeStream(adaptor,"rule join_spec"); - try { - // JPA.g:119:5: ( join_spec join_association_path_expression ( 'AS' )? identification_variable -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) ) - // JPA.g:119:7: join_spec join_association_path_expression ( 'AS' )? identification_variable - { - pushFollow(FOLLOW_join_spec_in_join786); - join_spec27=join_spec(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_join_spec.add(join_spec27.getTree()); - pushFollow(FOLLOW_join_association_path_expression_in_join788); - join_association_path_expression28=join_association_path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_join_association_path_expression.add(join_association_path_expression28.getTree()); - // JPA.g:119:50: ( 'AS' )? - int alt15=2; - int LA15_0 = input.LA(1); - - if ( (LA15_0==55) ) { - alt15=1; - } - switch (alt15) { - case 1 : - // JPA.g:119:51: 'AS' - { - string_literal29=(Token)match(input,55,FOLLOW_55_in_join791); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_55.add(string_literal29); - - - } - break; - - } - - pushFollow(FOLLOW_identification_variable_in_join795); - identification_variable30=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable30.getTree()); - - - // AST REWRITE - // elements: join_association_path_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 120:7: -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) - { - // JPA.g:120:10: ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new JoinVariableNode(T_JOIN_VAR, (join_spec27!=null?input.toString(join_spec27.start,join_spec27.stop):null), (identification_variable30!=null?input.toString(identification_variable30.start,identification_variable30.stop):null)), root_1); - - adaptor.addChild(root_1, stream_join_association_path_expression.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "join" - - public static class fetch_join_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "fetch_join" - // JPA.g:123:1: fetch_join : join_spec 'FETCH' join_association_path_expression ; - public final JPAParser.fetch_join_return fetch_join() throws RecognitionException { - JPAParser.fetch_join_return retval = new JPAParser.fetch_join_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal32=null; - JPAParser.join_spec_return join_spec31 = null; - - JPAParser.join_association_path_expression_return join_association_path_expression33 = null; - - - Object string_literal32_tree=null; - - try { - // JPA.g:124:5: ( join_spec 'FETCH' join_association_path_expression ) - // JPA.g:124:7: join_spec 'FETCH' join_association_path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_join_spec_in_fetch_join833); - join_spec31=join_spec(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, join_spec31.getTree()); - string_literal32=(Token)match(input,FETCH,FOLLOW_FETCH_in_fetch_join835); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal32_tree = (Object)adaptor.create(string_literal32); - adaptor.addChild(root_0, string_literal32_tree); - } - pushFollow(FOLLOW_join_association_path_expression_in_fetch_join837); - join_association_path_expression33=join_association_path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, join_association_path_expression33.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "fetch_join" - - public static class join_spec_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "join_spec" - // JPA.g:126:1: join_spec : ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' ; - public final JPAParser.join_spec_return join_spec() throws RecognitionException { - JPAParser.join_spec_return retval = new JPAParser.join_spec_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal34=null; - Token string_literal35=null; - Token string_literal36=null; - Token string_literal37=null; - - Object string_literal34_tree=null; - Object string_literal35_tree=null; - Object string_literal36_tree=null; - Object string_literal37_tree=null; - - try { - // JPA.g:127:5: ( ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' ) - // JPA.g:127:6: ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:127:6: ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? - int alt17=3; - int LA17_0 = input.LA(1); - - if ( (LA17_0==LEFT) ) { - alt17=1; - } - else if ( (LA17_0==INNER) ) { - alt17=2; - } - switch (alt17) { - case 1 : - // JPA.g:127:7: ( 'LEFT' ) ( 'OUTER' )? - { - // JPA.g:127:7: ( 'LEFT' ) - // JPA.g:127:8: 'LEFT' - { - string_literal34=(Token)match(input,LEFT,FOLLOW_LEFT_in_join_spec850); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal34_tree = (Object)adaptor.create(string_literal34); - adaptor.addChild(root_0, string_literal34_tree); - } - - } - - // JPA.g:127:16: ( 'OUTER' )? - int alt16=2; - int LA16_0 = input.LA(1); - - if ( (LA16_0==OUTER) ) { - alt16=1; - } - switch (alt16) { - case 1 : - // JPA.g:127:17: 'OUTER' - { - string_literal35=(Token)match(input,OUTER,FOLLOW_OUTER_in_join_spec854); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal35_tree = (Object)adaptor.create(string_literal35); - adaptor.addChild(root_0, string_literal35_tree); - } - - } - break; - - } - - - } - break; - case 2 : - // JPA.g:127:29: 'INNER' - { - string_literal36=(Token)match(input,INNER,FOLLOW_INNER_in_join_spec860); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal36_tree = (Object)adaptor.create(string_literal36); - adaptor.addChild(root_0, string_literal36_tree); - } - - } - break; - - } - - string_literal37=(Token)match(input,JOIN,FOLLOW_JOIN_in_join_spec865); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal37_tree = (Object)adaptor.create(string_literal37); - adaptor.addChild(root_0, string_literal37_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "join_spec" - - public static class join_association_path_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "join_association_path_expression" - // JPA.g:129:1: join_association_path_expression : identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ; - public final JPAParser.join_association_path_expression_return join_association_path_expression() throws RecognitionException { - JPAParser.join_association_path_expression_return retval = new JPAParser.join_association_path_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal39=null; - Token char_literal41=null; - JPAParser.identification_variable_return identification_variable38 = null; - - JPAParser.field_return field40 = null; - - JPAParser.field_return field42 = null; - - - Object char_literal39_tree=null; - Object char_literal41_tree=null; - RewriteRuleTokenStream stream_57=new RewriteRuleTokenStream(adaptor,"token 57"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_field=new RewriteRuleSubtreeStream(adaptor,"rule field"); - try { - // JPA.g:130:5: ( identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ) - // JPA.g:130:7: identification_variable '.' ( field '.' )* ( field )? - { - pushFollow(FOLLOW_identification_variable_in_join_association_path_expression877); - identification_variable38=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable38.getTree()); - char_literal39=(Token)match(input,57,FOLLOW_57_in_join_association_path_expression879); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_57.add(char_literal39); - - // JPA.g:130:35: ( field '.' )* - loop18: - do { - int alt18=2; - int LA18_0 = input.LA(1); - - if ( (LA18_0==WORD) ) { - int LA18_1 = input.LA(2); - - if ( (LA18_1==57) ) { - alt18=1; - } - - - } - else if ( (LA18_0==GROUP) ) { - int LA18_3 = input.LA(2); - - if ( (LA18_3==57) ) { - alt18=1; - } - - - } - - - switch (alt18) { - case 1 : - // JPA.g:130:36: field '.' - { - pushFollow(FOLLOW_field_in_join_association_path_expression882); - field40=field(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_field.add(field40.getTree()); - char_literal41=(Token)match(input,57,FOLLOW_57_in_join_association_path_expression883); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_57.add(char_literal41); - - - } - break; - - default : - break loop18; - } - } while (true); - - // JPA.g:130:47: ( field )? - int alt19=2; - int LA19_0 = input.LA(1); - - if ( (LA19_0==WORD) ) { - int LA19_1 = input.LA(2); - - if ( (synpred20_JPA()) ) { - alt19=1; - } - } - else if ( (LA19_0==GROUP) ) { - int LA19_3 = input.LA(2); - - if ( (LA19_3==EOF||LA19_3==HAVING||LA19_3==RPAREN||LA19_3==LEFT||(LA19_3>=INNER && LA19_3<=JOIN)||(LA19_3>=ORDER && LA19_3<=GROUP)||LA19_3==WORD||(LA19_3>=54 && LA19_3<=55)||LA19_3==61) ) { - alt19=1; - } - } - switch (alt19) { - case 1 : - // JPA.g:0:0: field - { - pushFollow(FOLLOW_field_in_join_association_path_expression887); - field42=field(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_field.add(field42.getTree()); - - } - break; - - } - - - - // AST REWRITE - // elements: field - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 131:5: -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) - { - // JPA.g:131:8: ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_FIELD, (identification_variable38!=null?input.toString(identification_variable38.start,identification_variable38.stop):null)), root_1); - - // JPA.g:131:68: ( field )* - while ( stream_field.hasNext() ) { - adaptor.addChild(root_1, stream_field.nextTree()); - - } - stream_field.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "join_association_path_expression" - - public static class collection_member_declaration_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "collection_member_declaration" - // JPA.g:134:1: collection_member_declaration : 'IN' '(' path_expression ')' ( 'AS' )? identification_variable -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) ; - public final JPAParser.collection_member_declaration_return collection_member_declaration() throws RecognitionException { - JPAParser.collection_member_declaration_return retval = new JPAParser.collection_member_declaration_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal43=null; - Token char_literal44=null; - Token char_literal46=null; - Token string_literal47=null; - JPAParser.path_expression_return path_expression45 = null; - - JPAParser.identification_variable_return identification_variable48 = null; - - - Object string_literal43_tree=null; - Object char_literal44_tree=null; - Object char_literal46_tree=null; - Object string_literal47_tree=null; - RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); - RewriteRuleTokenStream stream_58=new RewriteRuleTokenStream(adaptor,"token 58"); - RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); - RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); - try { - // JPA.g:135:5: ( 'IN' '(' path_expression ')' ( 'AS' )? identification_variable -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) ) - // JPA.g:135:7: 'IN' '(' path_expression ')' ( 'AS' )? identification_variable - { - string_literal43=(Token)match(input,58,FOLLOW_58_in_collection_member_declaration924); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_58.add(string_literal43); - - char_literal44=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_collection_member_declaration925); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_LPAREN.add(char_literal44); - - pushFollow(FOLLOW_path_expression_in_collection_member_declaration927); - path_expression45=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_path_expression.add(path_expression45.getTree()); - char_literal46=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_collection_member_declaration929); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_RPAREN.add(char_literal46); - - // JPA.g:135:35: ( 'AS' )? - int alt20=2; - int LA20_0 = input.LA(1); - - if ( (LA20_0==55) ) { - alt20=1; - } - switch (alt20) { - case 1 : - // JPA.g:135:36: 'AS' - { - string_literal47=(Token)match(input,55,FOLLOW_55_in_collection_member_declaration932); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_55.add(string_literal47); - - - } - break; - - } - - pushFollow(FOLLOW_identification_variable_in_collection_member_declaration936); - identification_variable48=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable48.getTree()); - - - // AST REWRITE - // elements: path_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 136:5: -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) - { - // JPA.g:136:8: ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new CollectionMemberNode(T_COLLECTION_MEMBER, (identification_variable48!=null?input.toString(identification_variable48.start,identification_variable48.stop):null)), root_1); - - adaptor.addChild(root_1, stream_path_expression.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "collection_member_declaration" - - public static class path_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "path_expression" - // JPA.g:139:1: path_expression : identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ; - public final JPAParser.path_expression_return path_expression() throws RecognitionException { - JPAParser.path_expression_return retval = new JPAParser.path_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal50=null; - Token char_literal52=null; - JPAParser.identification_variable_return identification_variable49 = null; - - JPAParser.field_return field51 = null; - - JPAParser.field_return field53 = null; - - - Object char_literal50_tree=null; - Object char_literal52_tree=null; - RewriteRuleTokenStream stream_57=new RewriteRuleTokenStream(adaptor,"token 57"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_field=new RewriteRuleSubtreeStream(adaptor,"rule field"); - try { - // JPA.g:140:5: ( identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ) - // JPA.g:140:8: identification_variable '.' ( field '.' )* ( field )? - { - pushFollow(FOLLOW_identification_variable_in_path_expression971); - identification_variable49=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable49.getTree()); - char_literal50=(Token)match(input,57,FOLLOW_57_in_path_expression973); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_57.add(char_literal50); - - // JPA.g:140:36: ( field '.' )* - loop21: - do { - int alt21=2; - int LA21_0 = input.LA(1); - - if ( (LA21_0==GROUP) ) { - int LA21_1 = input.LA(2); - - if ( (LA21_1==57) ) { - alt21=1; - } - - - } - else if ( (LA21_0==WORD) ) { - int LA21_3 = input.LA(2); - - if ( (LA21_3==57) ) { - alt21=1; - } - - - } - - - switch (alt21) { - case 1 : - // JPA.g:140:37: field '.' - { - pushFollow(FOLLOW_field_in_path_expression976); - field51=field(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_field.add(field51.getTree()); - char_literal52=(Token)match(input,57,FOLLOW_57_in_path_expression977); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_57.add(char_literal52); - - - } - break; - - default : - break loop21; - } - } while (true); - - // JPA.g:140:48: ( field )? - int alt22=2; - int LA22_0 = input.LA(1); - - if ( (LA22_0==GROUP) ) { - int LA22_1 = input.LA(2); - - if ( (LA22_1==EOF||(LA22_1>=HAVING && LA22_1<=DESC)||(LA22_1>=OR && LA22_1<=AND)||LA22_1==RPAREN||(LA22_1>=ORDER && LA22_1<=GROUP)||LA22_1==WORD||(LA22_1>=53 && LA22_1<=55)||LA22_1==58||LA22_1==62||(LA22_1>=65 && LA22_1<=66)||(LA22_1>=77 && LA22_1<=78)||LA22_1==80||LA22_1==83||(LA22_1>=89 && LA22_1<=96)) ) { - alt22=1; - } - } - else if ( (LA22_0==WORD) ) { - int LA22_3 = input.LA(2); - - if ( (synpred23_JPA()) ) { - alt22=1; - } - } - switch (alt22) { - case 1 : - // JPA.g:140:49: field - { - pushFollow(FOLLOW_field_in_path_expression982); - field53=field(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_field.add(field53.getTree()); - - } - break; - - } - - - - // AST REWRITE - // elements: field - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 141:5: -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) - { - // JPA.g:141:8: ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_FIELD, (identification_variable49!=null?input.toString(identification_variable49.start,identification_variable49.stop):null)), root_1); - - // JPA.g:141:68: ( field )* - while ( stream_field.hasNext() ) { - adaptor.addChild(root_1, stream_field.nextTree()); - - } - stream_field.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "path_expression" - - public static class select_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "select_clause" - // JPA.g:144:1: select_clause : ( 'DISTINCT' )? select_expression ( ',' select_expression )* -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) ; - public final JPAParser.select_clause_return select_clause() throws RecognitionException { - JPAParser.select_clause_return retval = new JPAParser.select_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal54=null; - Token char_literal56=null; - JPAParser.select_expression_return select_expression55 = null; - - JPAParser.select_expression_return select_expression57 = null; - - - Object string_literal54_tree=null; - Object char_literal56_tree=null; - RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); - RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); - RewriteRuleSubtreeStream stream_select_expression=new RewriteRuleSubtreeStream(adaptor,"rule select_expression"); - try { - // JPA.g:145:5: ( ( 'DISTINCT' )? select_expression ( ',' select_expression )* -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) ) - // JPA.g:145:7: ( 'DISTINCT' )? select_expression ( ',' select_expression )* - { - // JPA.g:145:7: ( 'DISTINCT' )? - int alt23=2; - int LA23_0 = input.LA(1); - - if ( (LA23_0==DISTINCT) ) { - alt23=1; - } - switch (alt23) { - case 1 : - // JPA.g:145:8: 'DISTINCT' - { - string_literal54=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_select_clause1021); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal54); - - - } - break; - - } - - pushFollow(FOLLOW_select_expression_in_select_clause1025); - select_expression55=select_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_select_expression.add(select_expression55.getTree()); - // JPA.g:145:39: ( ',' select_expression )* - loop24: - do { - int alt24=2; - int LA24_0 = input.LA(1); - - if ( (LA24_0==54) ) { - alt24=1; - } - - - switch (alt24) { - case 1 : - // JPA.g:145:40: ',' select_expression - { - char_literal56=(Token)match(input,54,FOLLOW_54_in_select_clause1028); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_54.add(char_literal56); - - pushFollow(FOLLOW_select_expression_in_select_clause1030); - select_expression57=select_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_select_expression.add(select_expression57.getTree()); - - } - break; - - default : - break loop24; - } - } while (true); - - - - // AST REWRITE - // elements: DISTINCT, select_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 146:5: -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) - { - // JPA.g:146:8: ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(T_SELECTED_ITEMS, "T_SELECTED_ITEMS"), root_1); - - // JPA.g:146:27: ( 'DISTINCT' )? - if ( stream_DISTINCT.hasNext() ) { - adaptor.addChild(root_1, stream_DISTINCT.nextNode()); - - } - stream_DISTINCT.reset(); - // JPA.g:146:41: ( ^( T_SELECTED_ITEM[] select_expression ) )* - while ( stream_select_expression.hasNext() ) { - // JPA.g:146:41: ^( T_SELECTED_ITEM[] select_expression ) - { - Object root_2 = (Object)adaptor.nil(); - root_2 = (Object)adaptor.becomeRoot(new SelectedItemNode(T_SELECTED_ITEM), root_2); - - adaptor.addChild(root_2, stream_select_expression.nextTree()); - - adaptor.addChild(root_1, root_2); - } - - } - stream_select_expression.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "select_clause" - - public static class select_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "select_expression" - // JPA.g:149:1: select_expression : ( path_expression | aggregate_expression | identification_variable -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) | 'OBJECT' '(' identification_variable ')' | constructor_expression ); - public final JPAParser.select_expression_return select_expression() throws RecognitionException { - JPAParser.select_expression_return retval = new JPAParser.select_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal61=null; - Token char_literal62=null; - Token char_literal64=null; - JPAParser.path_expression_return path_expression58 = null; - - JPAParser.aggregate_expression_return aggregate_expression59 = null; - - JPAParser.identification_variable_return identification_variable60 = null; - - JPAParser.identification_variable_return identification_variable63 = null; - - JPAParser.constructor_expression_return constructor_expression65 = null; - - - Object string_literal61_tree=null; - Object char_literal62_tree=null; - Object char_literal64_tree=null; - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - try { - // JPA.g:150:5: ( path_expression | aggregate_expression | identification_variable -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) | 'OBJECT' '(' identification_variable ')' | constructor_expression ) - int alt25=5; - switch ( input.LA(1) ) { - case WORD: - { - int LA25_1 = input.LA(2); - - if ( (LA25_1==EOF||(LA25_1>=53 && LA25_1<=54)) ) { - alt25=3; - } - else if ( (LA25_1==57) ) { - alt25=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 25, 1, input); - - throw nvae; - } - } - break; - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - { - alt25=2; - } - break; - case 59: - { - alt25=4; - } - break; - case 60: - { - alt25=5; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 25, 0, input); - - throw nvae; - } - - switch (alt25) { - case 1 : - // JPA.g:150:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_select_expression1075); - path_expression58=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression58.getTree()); - - } - break; - case 2 : - // JPA.g:151:7: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_select_expression1083); - aggregate_expression59=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression59.getTree()); - - } - break; - case 3 : - // JPA.g:152:7: identification_variable - { - pushFollow(FOLLOW_identification_variable_in_select_expression1091); - identification_variable60=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable60.getTree()); - - - // AST REWRITE - // elements: - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 152:31: -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) - { - // JPA.g:152:34: ^( T_SELECTED_ENTITY[$identification_variable.text] ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_ENTITY, (identification_variable60!=null?input.toString(identification_variable60.start,identification_variable60.stop):null)), root_1); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 4 : - // JPA.g:153:7: 'OBJECT' '(' identification_variable ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal61=(Token)match(input,59,FOLLOW_59_in_select_expression1109); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal61_tree = (Object)adaptor.create(string_literal61); - adaptor.addChild(root_0, string_literal61_tree); - } - char_literal62=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_select_expression1111); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal62_tree = (Object)adaptor.create(char_literal62); - adaptor.addChild(root_0, char_literal62_tree); - } - pushFollow(FOLLOW_identification_variable_in_select_expression1112); - identification_variable63=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable63.getTree()); - char_literal64=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_select_expression1113); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal64_tree = (Object)adaptor.create(char_literal64); - adaptor.addChild(root_0, char_literal64_tree); - } - - } - break; - case 5 : - // JPA.g:154:7: constructor_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_constructor_expression_in_select_expression1121); - constructor_expression65=constructor_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_expression65.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "select_expression" - - public static class constructor_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "constructor_expression" - // JPA.g:156:1: constructor_expression : 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' ; - public final JPAParser.constructor_expression_return constructor_expression() throws RecognitionException { - JPAParser.constructor_expression_return retval = new JPAParser.constructor_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal66=null; - Token char_literal68=null; - Token char_literal70=null; - Token char_literal72=null; - JPAParser.constructor_name_return constructor_name67 = null; - - JPAParser.constructor_item_return constructor_item69 = null; - - JPAParser.constructor_item_return constructor_item71 = null; - - - Object string_literal66_tree=null; - Object char_literal68_tree=null; - Object char_literal70_tree=null; - Object char_literal72_tree=null; - - try { - // JPA.g:157:5: ( 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' ) - // JPA.g:157:7: 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal66=(Token)match(input,60,FOLLOW_60_in_constructor_expression1133); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal66_tree = (Object)adaptor.create(string_literal66); - adaptor.addChild(root_0, string_literal66_tree); - } - pushFollow(FOLLOW_constructor_name_in_constructor_expression1135); - constructor_name67=constructor_name(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_name67.getTree()); - char_literal68=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_constructor_expression1137); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal68_tree = (Object)adaptor.create(char_literal68); - adaptor.addChild(root_0, char_literal68_tree); - } - pushFollow(FOLLOW_constructor_item_in_constructor_expression1139); - constructor_item69=constructor_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_item69.getTree()); - // JPA.g:157:51: ( ',' constructor_item )* - loop26: - do { - int alt26=2; - int LA26_0 = input.LA(1); - - if ( (LA26_0==54) ) { - alt26=1; - } - - - switch (alt26) { - case 1 : - // JPA.g:157:52: ',' constructor_item - { - char_literal70=(Token)match(input,54,FOLLOW_54_in_constructor_expression1142); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal70_tree = (Object)adaptor.create(char_literal70); - adaptor.addChild(root_0, char_literal70_tree); - } - pushFollow(FOLLOW_constructor_item_in_constructor_expression1144); - constructor_item71=constructor_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_item71.getTree()); - - } - break; - - default : - break loop26; - } - } while (true); - - char_literal72=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_constructor_expression1148); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal72_tree = (Object)adaptor.create(char_literal72); - adaptor.addChild(root_0, char_literal72_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "constructor_expression" - - public static class constructor_item_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "constructor_item" - // JPA.g:159:1: constructor_item : ( path_expression | aggregate_expression ); - public final JPAParser.constructor_item_return constructor_item() throws RecognitionException { - JPAParser.constructor_item_return retval = new JPAParser.constructor_item_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression73 = null; - - JPAParser.aggregate_expression_return aggregate_expression74 = null; - - - - try { - // JPA.g:160:5: ( path_expression | aggregate_expression ) - int alt27=2; - int LA27_0 = input.LA(1); - - if ( (LA27_0==WORD) ) { - alt27=1; - } - else if ( ((LA27_0>=AVG && LA27_0<=COUNT)) ) { - alt27=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 27, 0, input); - - throw nvae; - } - switch (alt27) { - case 1 : - // JPA.g:160:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_constructor_item1160); - path_expression73=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression73.getTree()); - - } - break; - case 2 : - // JPA.g:160:25: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_constructor_item1164); - aggregate_expression74=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression74.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "constructor_item" - - public static class aggregate_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "aggregate_expression" - // JPA.g:162:1: aggregate_expression : ( aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) | 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) ); - public final JPAParser.aggregate_expression_return aggregate_expression() throws RecognitionException { - JPAParser.aggregate_expression_return retval = new JPAParser.aggregate_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal76=null; - Token string_literal77=null; - Token char_literal79=null; - Token string_literal80=null; - Token char_literal81=null; - Token string_literal82=null; - Token char_literal84=null; - JPAParser.aggregate_expression_function_name_return aggregate_expression_function_name75 = null; - - JPAParser.path_expression_return path_expression78 = null; - - JPAParser.identification_variable_return identification_variable83 = null; - - - Object char_literal76_tree=null; - Object string_literal77_tree=null; - Object char_literal79_tree=null; - Object string_literal80_tree=null; - Object char_literal81_tree=null; - Object string_literal82_tree=null; - Object char_literal84_tree=null; - RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); - RewriteRuleTokenStream stream_COUNT=new RewriteRuleTokenStream(adaptor,"token COUNT"); - RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); - RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); - RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); - RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); - RewriteRuleSubtreeStream stream_aggregate_expression_function_name=new RewriteRuleSubtreeStream(adaptor,"rule aggregate_expression_function_name"); - try { - // JPA.g:163:5: ( aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) | 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) ) - int alt30=2; - int LA30_0 = input.LA(1); - - if ( (LA30_0==COUNT) ) { - int LA30_1 = input.LA(2); - - if ( (LA30_1==LPAREN) ) { - int LA30_3 = input.LA(3); - - if ( (LA30_3==DISTINCT) ) { - int LA30_4 = input.LA(4); - - if ( (LA30_4==WORD) ) { - int LA30_5 = input.LA(5); - - if ( (LA30_5==57) ) { - alt30=1; - } - else if ( (LA30_5==RPAREN) ) { - alt30=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 5, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 4, input); - - throw nvae; - } - } - else if ( (LA30_3==WORD) ) { - int LA30_5 = input.LA(4); - - if ( (LA30_5==57) ) { - alt30=1; - } - else if ( (LA30_5==RPAREN) ) { - alt30=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 5, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 3, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 1, input); - - throw nvae; - } - } - else if ( ((LA30_0>=AVG && LA30_0<=SUM)) ) { - alt30=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 30, 0, input); - - throw nvae; - } - switch (alt30) { - case 1 : - // JPA.g:163:7: aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' - { - pushFollow(FOLLOW_aggregate_expression_function_name_in_aggregate_expression1176); - aggregate_expression_function_name75=aggregate_expression_function_name(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_aggregate_expression_function_name.add(aggregate_expression_function_name75.getTree()); - char_literal76=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_aggregate_expression1178); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_LPAREN.add(char_literal76); - - // JPA.g:163:46: ( 'DISTINCT' )? - int alt28=2; - int LA28_0 = input.LA(1); - - if ( (LA28_0==DISTINCT) ) { - alt28=1; - } - switch (alt28) { - case 1 : - // JPA.g:163:47: 'DISTINCT' - { - string_literal77=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_aggregate_expression1181); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal77); - - - } - break; - - } - - pushFollow(FOLLOW_path_expression_in_aggregate_expression1185); - path_expression78=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_path_expression.add(path_expression78.getTree()); - char_literal79=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_aggregate_expression1186); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_RPAREN.add(char_literal79); - - - - // AST REWRITE - // elements: aggregate_expression_function_name, path_expression, LPAREN, RPAREN, DISTINCT - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 164:5: -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) - { - // JPA.g:164:8: ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new AggregateExpressionNode(T_AGGREGATE_EXPR), root_1); - - adaptor.addChild(root_1, stream_aggregate_expression_function_name.nextTree()); - adaptor.addChild(root_1, stream_LPAREN.nextNode()); - // JPA.g:164:93: ( 'DISTINCT' )? - if ( stream_DISTINCT.hasNext() ) { - adaptor.addChild(root_1, stream_DISTINCT.nextNode()); - - } - stream_DISTINCT.reset(); - adaptor.addChild(root_1, stream_path_expression.nextTree()); - adaptor.addChild(root_1, stream_RPAREN.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 2 : - // JPA.g:165:7: 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' - { - string_literal80=(Token)match(input,COUNT,FOLLOW_COUNT_in_aggregate_expression1220); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_COUNT.add(string_literal80); - - char_literal81=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_aggregate_expression1222); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_LPAREN.add(char_literal81); - - // JPA.g:165:19: ( 'DISTINCT' )? - int alt29=2; - int LA29_0 = input.LA(1); - - if ( (LA29_0==DISTINCT) ) { - alt29=1; - } - switch (alt29) { - case 1 : - // JPA.g:165:20: 'DISTINCT' - { - string_literal82=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_aggregate_expression1225); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal82); - - - } - break; - - } - - pushFollow(FOLLOW_identification_variable_in_aggregate_expression1229); - identification_variable83=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable83.getTree()); - char_literal84=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_aggregate_expression1231); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_RPAREN.add(char_literal84); - - - - // AST REWRITE - // elements: DISTINCT, identification_variable, COUNT, LPAREN, RPAREN - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 166:5: -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) - { - // JPA.g:166:8: ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new AggregateExpressionNode(T_AGGREGATE_EXPR), root_1); - - adaptor.addChild(root_1, stream_COUNT.nextNode()); - adaptor.addChild(root_1, stream_LPAREN.nextNode()); - // JPA.g:166:66: ( 'DISTINCT' )? - if ( stream_DISTINCT.hasNext() ) { - adaptor.addChild(root_1, stream_DISTINCT.nextNode()); - - } - stream_DISTINCT.reset(); - adaptor.addChild(root_1, stream_identification_variable.nextTree()); - adaptor.addChild(root_1, stream_RPAREN.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "aggregate_expression" - - public static class aggregate_expression_function_name_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "aggregate_expression_function_name" - // JPA.g:168:1: aggregate_expression_function_name : ( 'AVG' | 'MAX' | 'MIN' | 'SUM' | 'COUNT' ); - public final JPAParser.aggregate_expression_function_name_return aggregate_expression_function_name() throws RecognitionException { - JPAParser.aggregate_expression_function_name_return retval = new JPAParser.aggregate_expression_function_name_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set85=null; - - Object set85_tree=null; - - try { - // JPA.g:169:5: ( 'AVG' | 'MAX' | 'MIN' | 'SUM' | 'COUNT' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set85=(Token)input.LT(1); - if ( (input.LA(1)>=AVG && input.LA(1)<=COUNT) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set85)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "aggregate_expression_function_name" - - public static class where_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "where_clause" - // JPA.g:171:1: where_clause : (wh= 'WHERE' conditional_expression -> ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) ); - public final JPAParser.where_clause_return where_clause() throws RecognitionException { - JPAParser.where_clause_return retval = new JPAParser.where_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token wh=null; - Token string_literal87=null; - JPAParser.conditional_expression_return conditional_expression86 = null; - - JPAParser.path_expression_return path_expression88 = null; - - - Object wh_tree=null; - Object string_literal87_tree=null; - RewriteRuleTokenStream stream_61=new RewriteRuleTokenStream(adaptor,"token 61"); - RewriteRuleSubtreeStream stream_conditional_expression=new RewriteRuleSubtreeStream(adaptor,"rule conditional_expression"); - RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); - try { - // JPA.g:172:5: (wh= 'WHERE' conditional_expression -> ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) ) - int alt31=2; - alt31 = dfa31.predict(input); - switch (alt31) { - case 1 : - // JPA.g:172:7: wh= 'WHERE' conditional_expression - { - wh=(Token)match(input,61,FOLLOW_61_in_where_clause1299); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_61.add(wh); - - pushFollow(FOLLOW_conditional_expression_in_where_clause1301); - conditional_expression86=conditional_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_conditional_expression.add(conditional_expression86.getTree()); - - - // AST REWRITE - // elements: conditional_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 172:40: -> ^( T_CONDITION[$wh] conditional_expression ) - { - // JPA.g:172:43: ^( T_CONDITION[$wh] conditional_expression ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new WhereNode(T_CONDITION, wh), root_1); - - adaptor.addChild(root_1, stream_conditional_expression.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 2 : - // JPA.g:173:7: 'WHERE' path_expression - { - string_literal87=(Token)match(input,61,FOLLOW_61_in_where_clause1320); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_61.add(string_literal87); - - pushFollow(FOLLOW_path_expression_in_where_clause1322); - path_expression88=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_path_expression.add(path_expression88.getTree()); - - - // AST REWRITE - // elements: path_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 173:31: -> ^( T_CONDITION[$wh] path_expression ) - { - // JPA.g:173:34: ^( T_CONDITION[$wh] path_expression ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new WhereNode(T_CONDITION, wh), root_1); - - adaptor.addChild(root_1, stream_path_expression.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "where_clause" - - public static class groupby_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "groupby_clause" - // JPA.g:175:1: groupby_clause : 'GROUP' 'BY' groupby_item ( ',' groupby_item )* -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) ; - public final JPAParser.groupby_clause_return groupby_clause() throws RecognitionException { - JPAParser.groupby_clause_return retval = new JPAParser.groupby_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal89=null; - Token string_literal90=null; - Token char_literal92=null; - JPAParser.groupby_item_return groupby_item91 = null; - - JPAParser.groupby_item_return groupby_item93 = null; - - - Object string_literal89_tree=null; - Object string_literal90_tree=null; - Object char_literal92_tree=null; - RewriteRuleTokenStream stream_GROUP=new RewriteRuleTokenStream(adaptor,"token GROUP"); - RewriteRuleTokenStream stream_BY=new RewriteRuleTokenStream(adaptor,"token BY"); - RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); - RewriteRuleSubtreeStream stream_groupby_item=new RewriteRuleSubtreeStream(adaptor,"rule groupby_item"); - try { - // JPA.g:176:5: ( 'GROUP' 'BY' groupby_item ( ',' groupby_item )* -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) ) - // JPA.g:176:7: 'GROUP' 'BY' groupby_item ( ',' groupby_item )* - { - string_literal89=(Token)match(input,GROUP,FOLLOW_GROUP_in_groupby_clause1346); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_GROUP.add(string_literal89); - - string_literal90=(Token)match(input,BY,FOLLOW_BY_in_groupby_clause1348); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_BY.add(string_literal90); - - pushFollow(FOLLOW_groupby_item_in_groupby_clause1350); - groupby_item91=groupby_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_groupby_item.add(groupby_item91.getTree()); - // JPA.g:176:33: ( ',' groupby_item )* - loop32: - do { - int alt32=2; - int LA32_0 = input.LA(1); - - if ( (LA32_0==54) ) { - alt32=1; - } - - - switch (alt32) { - case 1 : - // JPA.g:176:34: ',' groupby_item - { - char_literal92=(Token)match(input,54,FOLLOW_54_in_groupby_clause1353); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_54.add(char_literal92); - - pushFollow(FOLLOW_groupby_item_in_groupby_clause1355); - groupby_item93=groupby_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_groupby_item.add(groupby_item93.getTree()); - - } - break; - - default : - break loop32; - } - } while (true); - - - - // AST REWRITE - // elements: BY, groupby_item, GROUP - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 177:5: -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) - { - // JPA.g:177:8: ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new GroupByNode(T_GROUP_BY), root_1); - - adaptor.addChild(root_1, stream_GROUP.nextNode()); - adaptor.addChild(root_1, stream_BY.nextNode()); - // JPA.g:177:49: ( groupby_item )* - while ( stream_groupby_item.hasNext() ) { - adaptor.addChild(root_1, stream_groupby_item.nextTree()); - - } - stream_groupby_item.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "groupby_clause" - - public static class groupby_item_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "groupby_item" - // JPA.g:180:1: groupby_item : ( path_expression | identification_variable ); - public final JPAParser.groupby_item_return groupby_item() throws RecognitionException { - JPAParser.groupby_item_return retval = new JPAParser.groupby_item_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression94 = null; - - JPAParser.identification_variable_return identification_variable95 = null; - - - - try { - // JPA.g:181:5: ( path_expression | identification_variable ) - int alt33=2; - int LA33_0 = input.LA(1); - - if ( (LA33_0==WORD) ) { - int LA33_1 = input.LA(2); - - if ( (LA33_1==EOF||LA33_1==HAVING||LA33_1==RPAREN||LA33_1==ORDER||LA33_1==54) ) { - alt33=2; - } - else if ( (LA33_1==57) ) { - alt33=1; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 33, 1, input); - - throw nvae; - } - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 33, 0, input); - - throw nvae; - } - switch (alt33) { - case 1 : - // JPA.g:181:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_groupby_item1395); - path_expression94=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression94.getTree()); - - } - break; - case 2 : - // JPA.g:181:25: identification_variable - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_identification_variable_in_groupby_item1399); - identification_variable95=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable95.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "groupby_item" - - public static class having_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "having_clause" - // JPA.g:183:1: having_clause : 'HAVING' conditional_expression ; - public final JPAParser.having_clause_return having_clause() throws RecognitionException { - JPAParser.having_clause_return retval = new JPAParser.having_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal96=null; - JPAParser.conditional_expression_return conditional_expression97 = null; - - - Object string_literal96_tree=null; - - try { - // JPA.g:184:5: ( 'HAVING' conditional_expression ) - // JPA.g:184:7: 'HAVING' conditional_expression - { - root_0 = (Object)adaptor.nil(); - - string_literal96=(Token)match(input,HAVING,FOLLOW_HAVING_in_having_clause1411); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal96_tree = (Object)adaptor.create(string_literal96); - adaptor.addChild(root_0, string_literal96_tree); - } - pushFollow(FOLLOW_conditional_expression_in_having_clause1413); - conditional_expression97=conditional_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_expression97.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "having_clause" - - public static class orderby_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "orderby_clause" - // JPA.g:186:1: orderby_clause : 'ORDER' 'BY' orderby_item ( ',' orderby_item )* -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) ; - public final JPAParser.orderby_clause_return orderby_clause() throws RecognitionException { - JPAParser.orderby_clause_return retval = new JPAParser.orderby_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal98=null; - Token string_literal99=null; - Token char_literal101=null; - JPAParser.orderby_item_return orderby_item100 = null; - - JPAParser.orderby_item_return orderby_item102 = null; - - - Object string_literal98_tree=null; - Object string_literal99_tree=null; - Object char_literal101_tree=null; - RewriteRuleTokenStream stream_BY=new RewriteRuleTokenStream(adaptor,"token BY"); - RewriteRuleTokenStream stream_ORDER=new RewriteRuleTokenStream(adaptor,"token ORDER"); - RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); - RewriteRuleSubtreeStream stream_orderby_item=new RewriteRuleSubtreeStream(adaptor,"rule orderby_item"); - try { - // JPA.g:187:5: ( 'ORDER' 'BY' orderby_item ( ',' orderby_item )* -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) ) - // JPA.g:187:7: 'ORDER' 'BY' orderby_item ( ',' orderby_item )* - { - string_literal98=(Token)match(input,ORDER,FOLLOW_ORDER_in_orderby_clause1425); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_ORDER.add(string_literal98); - - string_literal99=(Token)match(input,BY,FOLLOW_BY_in_orderby_clause1427); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_BY.add(string_literal99); - - pushFollow(FOLLOW_orderby_item_in_orderby_clause1429); - orderby_item100=orderby_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_orderby_item.add(orderby_item100.getTree()); - // JPA.g:187:33: ( ',' orderby_item )* - loop34: - do { - int alt34=2; - int LA34_0 = input.LA(1); - - if ( (LA34_0==54) ) { - alt34=1; - } - - - switch (alt34) { - case 1 : - // JPA.g:187:34: ',' orderby_item - { - char_literal101=(Token)match(input,54,FOLLOW_54_in_orderby_clause1432); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_54.add(char_literal101); - - pushFollow(FOLLOW_orderby_item_in_orderby_clause1434); - orderby_item102=orderby_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_orderby_item.add(orderby_item102.getTree()); - - } - break; - - default : - break loop34; - } - } while (true); - - - - // AST REWRITE - // elements: BY, orderby_item, ORDER - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 188:5: -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) - { - // JPA.g:188:8: ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new OrderByNode(T_ORDER_BY), root_1); - - adaptor.addChild(root_1, stream_ORDER.nextNode()); - adaptor.addChild(root_1, stream_BY.nextNode()); - // JPA.g:188:49: ( orderby_item )* - while ( stream_orderby_item.hasNext() ) { - adaptor.addChild(root_1, stream_orderby_item.nextTree()); - - } - stream_orderby_item.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "orderby_clause" - - public static class orderby_item_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "orderby_item" - // JPA.g:190:1: orderby_item : ( path_expression ( 'ASC' )? -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) ); - public final JPAParser.orderby_item_return orderby_item() throws RecognitionException { - JPAParser.orderby_item_return retval = new JPAParser.orderby_item_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal104=null; - Token string_literal106=null; - JPAParser.path_expression_return path_expression103 = null; - - JPAParser.path_expression_return path_expression105 = null; - - - Object string_literal104_tree=null; - Object string_literal106_tree=null; - RewriteRuleTokenStream stream_DESC=new RewriteRuleTokenStream(adaptor,"token DESC"); - RewriteRuleTokenStream stream_ASC=new RewriteRuleTokenStream(adaptor,"token ASC"); - RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); - try { - // JPA.g:191:5: ( path_expression ( 'ASC' )? -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) ) - int alt36=2; - alt36 = dfa36.predict(input); - switch (alt36) { - case 1 : - // JPA.g:191:7: path_expression ( 'ASC' )? - { - pushFollow(FOLLOW_path_expression_in_orderby_item1469); - path_expression103=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_path_expression.add(path_expression103.getTree()); - // JPA.g:191:25: ( 'ASC' )? - int alt35=2; - int LA35_0 = input.LA(1); - - if ( (LA35_0==ASC) ) { - alt35=1; - } - switch (alt35) { - case 1 : - // JPA.g:191:26: 'ASC' - { - string_literal104=(Token)match(input,ASC,FOLLOW_ASC_in_orderby_item1474); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_ASC.add(string_literal104); - - - } - break; - - } - - - - // AST REWRITE - // elements: ASC, path_expression - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 192:6: -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) - { - // JPA.g:192:9: ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new OrderByFieldNode(T_ORDER_BY_FIELD), root_1); - - adaptor.addChild(root_1, stream_path_expression.nextTree()); - // JPA.g:192:64: ( 'ASC' )? - if ( stream_ASC.hasNext() ) { - adaptor.addChild(root_1, stream_ASC.nextNode()); - - } - stream_ASC.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 2 : - // JPA.g:193:7: path_expression 'DESC' - { - pushFollow(FOLLOW_path_expression_in_orderby_item1506); - path_expression105=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_path_expression.add(path_expression105.getTree()); - string_literal106=(Token)match(input,DESC,FOLLOW_DESC_in_orderby_item1510); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_DESC.add(string_literal106); - - - - // AST REWRITE - // elements: path_expression, DESC - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 194:5: -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) - { - // JPA.g:194:8: ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new OrderByFieldNode(T_ORDER_BY_FIELD), root_1); - - adaptor.addChild(root_1, stream_path_expression.nextTree()); - adaptor.addChild(root_1, stream_DESC.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "orderby_item" - - public static class subquery_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "subquery" - // JPA.g:196:1: subquery : lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) ; - public final JPAParser.subquery_return subquery() throws RecognitionException { - JPAParser.subquery_return retval = new JPAParser.subquery_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token lp=null; - Token rp=null; - JPAParser.simple_select_clause_return simple_select_clause107 = null; - - JPAParser.subquery_from_clause_return subquery_from_clause108 = null; - - JPAParser.where_clause_return where_clause109 = null; - - JPAParser.groupby_clause_return groupby_clause110 = null; - - JPAParser.having_clause_return having_clause111 = null; - - - Object lp_tree=null; - Object rp_tree=null; - RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); - RewriteRuleTokenStream stream_56=new RewriteRuleTokenStream(adaptor,"token 56"); - RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); - RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); - RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); - RewriteRuleSubtreeStream stream_subquery_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule subquery_from_clause"); - RewriteRuleSubtreeStream stream_simple_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule simple_select_clause"); - try { - // JPA.g:197:5: (lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) ) - // JPA.g:197:7: lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' - { - lp=(Token)match(input,56,FOLLOW_56_in_subquery1542); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_56.add(lp); - - pushFollow(FOLLOW_simple_select_clause_in_subquery1544); - simple_select_clause107=simple_select_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_simple_select_clause.add(simple_select_clause107.getTree()); - pushFollow(FOLLOW_subquery_from_clause_in_subquery1546); - subquery_from_clause108=subquery_from_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_subquery_from_clause.add(subquery_from_clause108.getTree()); - // JPA.g:197:62: ( where_clause )? - int alt37=2; - int LA37_0 = input.LA(1); - - if ( (LA37_0==61) ) { - alt37=1; - } - switch (alt37) { - case 1 : - // JPA.g:197:63: where_clause - { - pushFollow(FOLLOW_where_clause_in_subquery1549); - where_clause109=where_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_where_clause.add(where_clause109.getTree()); - - } - break; - - } - - // JPA.g:197:78: ( groupby_clause )? - int alt38=2; - int LA38_0 = input.LA(1); - - if ( (LA38_0==GROUP) ) { - alt38=1; - } - switch (alt38) { - case 1 : - // JPA.g:197:79: groupby_clause - { - pushFollow(FOLLOW_groupby_clause_in_subquery1554); - groupby_clause110=groupby_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause110.getTree()); - - } - break; - - } - - // JPA.g:197:96: ( having_clause )? - int alt39=2; - int LA39_0 = input.LA(1); - - if ( (LA39_0==HAVING) ) { - alt39=1; - } - switch (alt39) { - case 1 : - // JPA.g:197:97: having_clause - { - pushFollow(FOLLOW_having_clause_in_subquery1559); - having_clause111=having_clause(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_having_clause.add(having_clause111.getTree()); - - } - break; - - } - - rp=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_subquery1565); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_RPAREN.add(rp); - - - - // AST REWRITE - // elements: where_clause, simple_select_clause, groupby_clause, subquery_from_clause, having_clause - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 198:6: -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) - { - // JPA.g:198:9: ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, lp, rp), root_1); - - adaptor.addChild(root_1, stream_simple_select_clause.nextTree()); - adaptor.addChild(root_1, stream_subquery_from_clause.nextTree()); - // JPA.g:198:81: ( where_clause )? - if ( stream_where_clause.hasNext() ) { - adaptor.addChild(root_1, stream_where_clause.nextTree()); - - } - stream_where_clause.reset(); - // JPA.g:198:97: ( groupby_clause )? - if ( stream_groupby_clause.hasNext() ) { - adaptor.addChild(root_1, stream_groupby_clause.nextTree()); - - } - stream_groupby_clause.reset(); - // JPA.g:198:115: ( having_clause )? - if ( stream_having_clause.hasNext() ) { - adaptor.addChild(root_1, stream_having_clause.nextTree()); - - } - stream_having_clause.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "subquery" - - public static class subquery_from_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "subquery_from_clause" - // JPA.g:200:1: subquery_from_clause : fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) ; - public final JPAParser.subquery_from_clause_return subquery_from_clause() throws RecognitionException { - JPAParser.subquery_from_clause_return retval = new JPAParser.subquery_from_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token fr=null; - Token char_literal113=null; - JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration112 = null; - - JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration114 = null; - - - Object fr_tree=null; - Object char_literal113_tree=null; - RewriteRuleTokenStream stream_53=new RewriteRuleTokenStream(adaptor,"token 53"); - RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); - RewriteRuleSubtreeStream stream_subselect_identification_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule subselect_identification_variable_declaration"); - try { - // JPA.g:201:5: (fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) ) - // JPA.g:201:7: fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* - { - fr=(Token)match(input,53,FOLLOW_53_in_subquery_from_clause1614); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_53.add(fr); - - pushFollow(FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1616); - subselect_identification_variable_declaration112=subselect_identification_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_subselect_identification_variable_declaration.add(subselect_identification_variable_declaration112.getTree()); - // JPA.g:201:63: ( ',' subselect_identification_variable_declaration )* - loop40: - do { - int alt40=2; - int LA40_0 = input.LA(1); - - if ( (LA40_0==54) ) { - alt40=1; - } - - - switch (alt40) { - case 1 : - // JPA.g:201:64: ',' subselect_identification_variable_declaration - { - char_literal113=(Token)match(input,54,FOLLOW_54_in_subquery_from_clause1619); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_54.add(char_literal113); - - pushFollow(FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1621); - subselect_identification_variable_declaration114=subselect_identification_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_subselect_identification_variable_declaration.add(subselect_identification_variable_declaration114.getTree()); - - } - break; - - default : - break loop40; - } - } while (true); - - - - // AST REWRITE - // elements: subselect_identification_variable_declaration - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 202:5: -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) - { - // JPA.g:202:8: ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new FromNode(T_SOURCES, fr), root_1); - - // JPA.g:202:35: ( ^( T_SOURCE subselect_identification_variable_declaration ) )* - while ( stream_subselect_identification_variable_declaration.hasNext() ) { - // JPA.g:202:35: ^( T_SOURCE subselect_identification_variable_declaration ) - { - Object root_2 = (Object)adaptor.nil(); - root_2 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_2); - - adaptor.addChild(root_2, stream_subselect_identification_variable_declaration.nextTree()); - - adaptor.addChild(root_1, root_2); - } - - } - stream_subselect_identification_variable_declaration.reset(); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "subquery_from_clause" - - public static class subselect_identification_variable_declaration_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "subselect_identification_variable_declaration" - // JPA.g:204:1: subselect_identification_variable_declaration : ( identification_variable_declaration | association_path_expression ( 'AS' )? identification_variable | collection_member_declaration ); - public final JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration() throws RecognitionException { - JPAParser.subselect_identification_variable_declaration_return retval = new JPAParser.subselect_identification_variable_declaration_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal117=null; - JPAParser.identification_variable_declaration_return identification_variable_declaration115 = null; - - JPAParser.association_path_expression_return association_path_expression116 = null; - - JPAParser.identification_variable_return identification_variable118 = null; - - JPAParser.collection_member_declaration_return collection_member_declaration119 = null; - - - Object string_literal117_tree=null; - - try { - // JPA.g:205:5: ( identification_variable_declaration | association_path_expression ( 'AS' )? identification_variable | collection_member_declaration ) - int alt42=3; - switch ( input.LA(1) ) { - case WORD: - { - int LA42_1 = input.LA(2); - - if ( (LA42_1==WORD||LA42_1==55) ) { - alt42=1; - } - else if ( (LA42_1==57) ) { - alt42=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 42, 1, input); - - throw nvae; - } - } - break; - case 56: - { - alt42=1; - } - break; - case 58: - { - alt42=3; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 42, 0, input); - - throw nvae; - } - - switch (alt42) { - case 1 : - // JPA.g:205:7: identification_variable_declaration - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_identification_variable_declaration_in_subselect_identification_variable_declaration1659); - identification_variable_declaration115=identification_variable_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable_declaration115.getTree()); - - } - break; - case 2 : - // JPA.g:206:7: association_path_expression ( 'AS' )? identification_variable - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_association_path_expression_in_subselect_identification_variable_declaration1667); - association_path_expression116=association_path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, association_path_expression116.getTree()); - // JPA.g:206:35: ( 'AS' )? - int alt41=2; - int LA41_0 = input.LA(1); - - if ( (LA41_0==55) ) { - alt41=1; - } - switch (alt41) { - case 1 : - // JPA.g:206:36: 'AS' - { - string_literal117=(Token)match(input,55,FOLLOW_55_in_subselect_identification_variable_declaration1670); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal117_tree = (Object)adaptor.create(string_literal117); - adaptor.addChild(root_0, string_literal117_tree); - } - - } - break; - - } - - pushFollow(FOLLOW_identification_variable_in_subselect_identification_variable_declaration1674); - identification_variable118=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable118.getTree()); - - } - break; - case 3 : - // JPA.g:207:7: collection_member_declaration - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_collection_member_declaration_in_subselect_identification_variable_declaration1682); - collection_member_declaration119=collection_member_declaration(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, collection_member_declaration119.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "subselect_identification_variable_declaration" - - public static class association_path_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "association_path_expression" - // JPA.g:209:1: association_path_expression : path_expression ; - public final JPAParser.association_path_expression_return association_path_expression() throws RecognitionException { - JPAParser.association_path_expression_return retval = new JPAParser.association_path_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression120 = null; - - - - try { - // JPA.g:210:5: ( path_expression ) - // JPA.g:210:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_association_path_expression1694); - path_expression120=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression120.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "association_path_expression" - - public static class simple_select_clause_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "simple_select_clause" - // JPA.g:212:1: simple_select_clause : ( 'DISTINCT' )? simple_select_expression -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) ; - public final JPAParser.simple_select_clause_return simple_select_clause() throws RecognitionException { - JPAParser.simple_select_clause_return retval = new JPAParser.simple_select_clause_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal121=null; - JPAParser.simple_select_expression_return simple_select_expression122 = null; - - - Object string_literal121_tree=null; - RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); - RewriteRuleSubtreeStream stream_simple_select_expression=new RewriteRuleSubtreeStream(adaptor,"rule simple_select_expression"); - try { - // JPA.g:213:5: ( ( 'DISTINCT' )? simple_select_expression -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) ) - // JPA.g:213:7: ( 'DISTINCT' )? simple_select_expression - { - // JPA.g:213:7: ( 'DISTINCT' )? - int alt43=2; - int LA43_0 = input.LA(1); - - if ( (LA43_0==DISTINCT) ) { - alt43=1; - } - switch (alt43) { - case 1 : - // JPA.g:213:8: 'DISTINCT' - { - string_literal121=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_simple_select_clause1707); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal121); - - - } - break; - - } - - pushFollow(FOLLOW_simple_select_expression_in_simple_select_clause1711); - simple_select_expression122=simple_select_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_simple_select_expression.add(simple_select_expression122.getTree()); - - - // AST REWRITE - // elements: simple_select_expression, DISTINCT - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 214:5: -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) - { - // JPA.g:214:8: ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(T_SELECTED_ITEMS, "T_SELECTED_ITEMS"), root_1); - - // JPA.g:214:27: ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) - { - Object root_2 = (Object)adaptor.nil(); - root_2 = (Object)adaptor.becomeRoot(new SelectedItemNode(T_SELECTED_ITEM), root_2); - - // JPA.g:214:65: ( 'DISTINCT' )? - if ( stream_DISTINCT.hasNext() ) { - adaptor.addChild(root_2, stream_DISTINCT.nextNode()); - - } - stream_DISTINCT.reset(); - adaptor.addChild(root_2, stream_simple_select_expression.nextTree()); - - adaptor.addChild(root_1, root_2); - } - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "simple_select_clause" - - public static class simple_select_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "simple_select_expression" - // JPA.g:216:1: simple_select_expression : ( path_expression | aggregate_expression | identification_variable ); - public final JPAParser.simple_select_expression_return simple_select_expression() throws RecognitionException { - JPAParser.simple_select_expression_return retval = new JPAParser.simple_select_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression123 = null; - - JPAParser.aggregate_expression_return aggregate_expression124 = null; - - JPAParser.identification_variable_return identification_variable125 = null; - - - - try { - // JPA.g:217:5: ( path_expression | aggregate_expression | identification_variable ) - int alt44=3; - int LA44_0 = input.LA(1); - - if ( (LA44_0==WORD) ) { - int LA44_1 = input.LA(2); - - if ( (LA44_1==57) ) { - alt44=1; - } - else if ( (LA44_1==53) ) { - alt44=3; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 44, 1, input); - - throw nvae; - } - } - else if ( ((LA44_0>=AVG && LA44_0<=COUNT)) ) { - alt44=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 44, 0, input); - - throw nvae; - } - switch (alt44) { - case 1 : - // JPA.g:217:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_simple_select_expression1748); - path_expression123=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression123.getTree()); - - } - break; - case 2 : - // JPA.g:218:7: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_simple_select_expression1756); - aggregate_expression124=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression124.getTree()); - - } - break; - case 3 : - // JPA.g:219:7: identification_variable - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_identification_variable_in_simple_select_expression1764); - identification_variable125=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable125.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "simple_select_expression" - - public static class conditional_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "conditional_expression" - // JPA.g:221:1: conditional_expression : ( conditional_term ) ( 'OR' conditional_term )* ; - public final JPAParser.conditional_expression_return conditional_expression() throws RecognitionException { - JPAParser.conditional_expression_return retval = new JPAParser.conditional_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal127=null; - JPAParser.conditional_term_return conditional_term126 = null; - - JPAParser.conditional_term_return conditional_term128 = null; - - - Object string_literal127_tree=null; - - try { - // JPA.g:222:5: ( ( conditional_term ) ( 'OR' conditional_term )* ) - // JPA.g:222:7: ( conditional_term ) ( 'OR' conditional_term )* - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:222:7: ( conditional_term ) - // JPA.g:222:8: conditional_term - { - pushFollow(FOLLOW_conditional_term_in_conditional_expression1777); - conditional_term126=conditional_term(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_term126.getTree()); - - } - - // JPA.g:222:26: ( 'OR' conditional_term )* - loop45: - do { - int alt45=2; - int LA45_0 = input.LA(1); - - if ( (LA45_0==OR) ) { - alt45=1; - } - - - switch (alt45) { - case 1 : - // JPA.g:222:27: 'OR' conditional_term - { - string_literal127=(Token)match(input,OR,FOLLOW_OR_in_conditional_expression1781); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal127_tree = (Object)adaptor.create(string_literal127); - adaptor.addChild(root_0, string_literal127_tree); - } - pushFollow(FOLLOW_conditional_term_in_conditional_expression1783); - conditional_term128=conditional_term(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_term128.getTree()); - - } - break; - - default : - break loop45; - } - } while (true); - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "conditional_expression" - - public static class conditional_term_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "conditional_term" - // JPA.g:224:1: conditional_term : ( conditional_factor ) ( 'AND' conditional_factor )* ; - public final JPAParser.conditional_term_return conditional_term() throws RecognitionException { - JPAParser.conditional_term_return retval = new JPAParser.conditional_term_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal130=null; - JPAParser.conditional_factor_return conditional_factor129 = null; - - JPAParser.conditional_factor_return conditional_factor131 = null; - - - Object string_literal130_tree=null; - - try { - // JPA.g:225:5: ( ( conditional_factor ) ( 'AND' conditional_factor )* ) - // JPA.g:225:7: ( conditional_factor ) ( 'AND' conditional_factor )* - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:225:7: ( conditional_factor ) - // JPA.g:225:8: conditional_factor - { - pushFollow(FOLLOW_conditional_factor_in_conditional_term1798); - conditional_factor129=conditional_factor(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_factor129.getTree()); - - } - - // JPA.g:225:28: ( 'AND' conditional_factor )* - loop46: - do { - int alt46=2; - int LA46_0 = input.LA(1); - - if ( (LA46_0==AND) ) { - alt46=1; - } - - - switch (alt46) { - case 1 : - // JPA.g:225:29: 'AND' conditional_factor - { - string_literal130=(Token)match(input,AND,FOLLOW_AND_in_conditional_term1802); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal130_tree = (Object)adaptor.create(string_literal130); - adaptor.addChild(root_0, string_literal130_tree); - } - pushFollow(FOLLOW_conditional_factor_in_conditional_term1804); - conditional_factor131=conditional_factor(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_factor131.getTree()); - - } - break; - - default : - break loop46; - } - } while (true); - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "conditional_term" - - public static class conditional_factor_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "conditional_factor" - // JPA.g:227:1: conditional_factor : ( ( 'NOT' )? simple_cond_expression -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' ); - public final JPAParser.conditional_factor_return conditional_factor() throws RecognitionException { - JPAParser.conditional_factor_return retval = new JPAParser.conditional_factor_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal132=null; - Token char_literal134=null; - Token char_literal136=null; - JPAParser.simple_cond_expression_return simple_cond_expression133 = null; - - JPAParser.conditional_expression_return conditional_expression135 = null; - - - Object string_literal132_tree=null; - Object char_literal134_tree=null; - Object char_literal136_tree=null; - RewriteRuleTokenStream stream_62=new RewriteRuleTokenStream(adaptor,"token 62"); - RewriteRuleSubtreeStream stream_simple_cond_expression=new RewriteRuleSubtreeStream(adaptor,"rule simple_cond_expression"); - try { - // JPA.g:228:5: ( ( 'NOT' )? simple_cond_expression -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' ) - int alt48=2; - alt48 = dfa48.predict(input); - switch (alt48) { - case 1 : - // JPA.g:228:7: ( 'NOT' )? simple_cond_expression - { - // JPA.g:228:7: ( 'NOT' )? - int alt47=2; - int LA47_0 = input.LA(1); - - if ( (LA47_0==62) ) { - int LA47_1 = input.LA(2); - - if ( (synpred57_JPA()) ) { - alt47=1; - } - } - switch (alt47) { - case 1 : - // JPA.g:228:8: 'NOT' - { - string_literal132=(Token)match(input,62,FOLLOW_62_in_conditional_factor1823); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_62.add(string_literal132); - - - } - break; - - } - - pushFollow(FOLLOW_simple_cond_expression_in_conditional_factor1827); - simple_cond_expression133=simple_cond_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) stream_simple_cond_expression.add(simple_cond_expression133.getTree()); - - - // AST REWRITE - // elements: simple_cond_expression, 62 - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 228:39: -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) - { - // JPA.g:228:42: ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new SimpleConditionNode(T_SIMPLE_CONDITION), root_1); - - // JPA.g:228:86: ( 'NOT' )? - if ( stream_62.hasNext() ) { - adaptor.addChild(root_1, stream_62.nextNode()); - - } - stream_62.reset(); - adaptor.addChild(root_1, stream_simple_cond_expression.nextTree()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 2 : - // JPA.g:229:7: '(' conditional_expression ')' - { - root_0 = (Object)adaptor.nil(); - - char_literal134=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_conditional_factor1852); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal134_tree = (Object)adaptor.create(char_literal134); - adaptor.addChild(root_0, char_literal134_tree); - } - pushFollow(FOLLOW_conditional_expression_in_conditional_factor1853); - conditional_expression135=conditional_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_expression135.getTree()); - char_literal136=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_conditional_factor1854); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal136_tree = (Object)adaptor.create(char_literal136); - adaptor.addChild(root_0, char_literal136_tree); - } - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "conditional_factor" - - public static class simple_cond_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "simple_cond_expression" - // JPA.g:231:1: simple_cond_expression : ( comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression | date_macro_expression ); - public final JPAParser.simple_cond_expression_return simple_cond_expression() throws RecognitionException { - JPAParser.simple_cond_expression_return retval = new JPAParser.simple_cond_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.comparison_expression_return comparison_expression137 = null; - - JPAParser.between_expression_return between_expression138 = null; - - JPAParser.like_expression_return like_expression139 = null; - - JPAParser.in_expression_return in_expression140 = null; - - JPAParser.null_comparison_expression_return null_comparison_expression141 = null; - - JPAParser.empty_collection_comparison_expression_return empty_collection_comparison_expression142 = null; - - JPAParser.collection_member_expression_return collection_member_expression143 = null; - - JPAParser.exists_expression_return exists_expression144 = null; - - JPAParser.date_macro_expression_return date_macro_expression145 = null; - - - - try { - // JPA.g:232:5: ( comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression | date_macro_expression ) - int alt49=9; - alt49 = dfa49.predict(input); - switch (alt49) { - case 1 : - // JPA.g:232:7: comparison_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_comparison_expression_in_simple_cond_expression1866); - comparison_expression137=comparison_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_expression137.getTree()); - - } - break; - case 2 : - // JPA.g:233:7: between_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_between_expression_in_simple_cond_expression1874); - between_expression138=between_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, between_expression138.getTree()); - - } - break; - case 3 : - // JPA.g:234:7: like_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_like_expression_in_simple_cond_expression1882); - like_expression139=like_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, like_expression139.getTree()); - - } - break; - case 4 : - // JPA.g:235:7: in_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_in_expression_in_simple_cond_expression1890); - in_expression140=in_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, in_expression140.getTree()); - - } - break; - case 5 : - // JPA.g:236:7: null_comparison_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_null_comparison_expression_in_simple_cond_expression1898); - null_comparison_expression141=null_comparison_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, null_comparison_expression141.getTree()); - - } - break; - case 6 : - // JPA.g:237:7: empty_collection_comparison_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_empty_collection_comparison_expression_in_simple_cond_expression1906); - empty_collection_comparison_expression142=empty_collection_comparison_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, empty_collection_comparison_expression142.getTree()); - - } - break; - case 7 : - // JPA.g:238:7: collection_member_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_collection_member_expression_in_simple_cond_expression1914); - collection_member_expression143=collection_member_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, collection_member_expression143.getTree()); - - } - break; - case 8 : - // JPA.g:239:7: exists_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_exists_expression_in_simple_cond_expression1922); - exists_expression144=exists_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, exists_expression144.getTree()); - - } - break; - case 9 : - // JPA.g:240:7: date_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_macro_expression_in_simple_cond_expression1930); - date_macro_expression145=date_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_macro_expression145.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "simple_cond_expression" - - public static class date_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_macro_expression" - // JPA.g:242:1: date_macro_expression : ( date_between_macro_expression | date_before_macro_expression | date_after_macro_expression | date_equals_macro_expression | date_today_macro_expression ); - public final JPAParser.date_macro_expression_return date_macro_expression() throws RecognitionException { - JPAParser.date_macro_expression_return retval = new JPAParser.date_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.date_between_macro_expression_return date_between_macro_expression146 = null; - - JPAParser.date_before_macro_expression_return date_before_macro_expression147 = null; - - JPAParser.date_after_macro_expression_return date_after_macro_expression148 = null; - - JPAParser.date_equals_macro_expression_return date_equals_macro_expression149 = null; - - JPAParser.date_today_macro_expression_return date_today_macro_expression150 = null; - - - - try { - // JPA.g:243:5: ( date_between_macro_expression | date_before_macro_expression | date_after_macro_expression | date_equals_macro_expression | date_today_macro_expression ) - int alt50=5; - switch ( input.LA(1) ) { - case 63: - { - alt50=1; - } - break; - case 73: - { - alt50=2; - } - break; - case 74: - { - alt50=3; - } - break; - case 75: - { - alt50=4; - } - break; - case 76: - { - alt50=5; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 50, 0, input); - - throw nvae; - } - - switch (alt50) { - case 1 : - // JPA.g:243:7: date_between_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_between_macro_expression_in_date_macro_expression1942); - date_between_macro_expression146=date_between_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_between_macro_expression146.getTree()); - - } - break; - case 2 : - // JPA.g:244:7: date_before_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_before_macro_expression_in_date_macro_expression1950); - date_before_macro_expression147=date_before_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_before_macro_expression147.getTree()); - - } - break; - case 3 : - // JPA.g:245:7: date_after_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_after_macro_expression_in_date_macro_expression1958); - date_after_macro_expression148=date_after_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_after_macro_expression148.getTree()); - - } - break; - case 4 : - // JPA.g:246:7: date_equals_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_equals_macro_expression_in_date_macro_expression1966); - date_equals_macro_expression149=date_equals_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_equals_macro_expression149.getTree()); - - } - break; - case 5 : - // JPA.g:247:7: date_today_macro_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_date_today_macro_expression_in_date_macro_expression1974); - date_today_macro_expression150=date_today_macro_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, date_today_macro_expression150.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_macro_expression" - - public static class date_between_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_between_macro_expression" - // JPA.g:249:1: date_between_macro_expression : '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' ; - public final JPAParser.date_between_macro_expression_return date_between_macro_expression() throws RecognitionException { - JPAParser.date_between_macro_expression_return retval = new JPAParser.date_between_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal151=null; - Token char_literal152=null; - Token char_literal154=null; - Token string_literal155=null; - Token set156=null; - Token INT_NUMERAL157=null; - Token char_literal158=null; - Token string_literal159=null; - Token set160=null; - Token INT_NUMERAL161=null; - Token char_literal162=null; - Token set163=null; - Token char_literal164=null; - JPAParser.path_expression_return path_expression153 = null; - - - Object string_literal151_tree=null; - Object char_literal152_tree=null; - Object char_literal154_tree=null; - Object string_literal155_tree=null; - Object set156_tree=null; - Object INT_NUMERAL157_tree=null; - Object char_literal158_tree=null; - Object string_literal159_tree=null; - Object set160_tree=null; - Object INT_NUMERAL161_tree=null; - Object char_literal162_tree=null; - Object set163_tree=null; - Object char_literal164_tree=null; - - try { - // JPA.g:250:5: ( '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' ) - // JPA.g:250:7: '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal151=(Token)match(input,63,FOLLOW_63_in_date_between_macro_expression1986); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal151_tree = (Object)adaptor.create(string_literal151); - adaptor.addChild(root_0, string_literal151_tree); - } - char_literal152=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_between_macro_expression1988); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal152_tree = (Object)adaptor.create(char_literal152); - adaptor.addChild(root_0, char_literal152_tree); - } - pushFollow(FOLLOW_path_expression_in_date_between_macro_expression1990); - path_expression153=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression153.getTree()); - char_literal154=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression1992); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal154_tree = (Object)adaptor.create(char_literal154); - adaptor.addChild(root_0, char_literal154_tree); - } - string_literal155=(Token)match(input,64,FOLLOW_64_in_date_between_macro_expression1994); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal155_tree = (Object)adaptor.create(string_literal155); - adaptor.addChild(root_0, string_literal155_tree); - } - // JPA.g:250:48: ( ( '+' | '-' ) INT_NUMERAL )? - int alt51=2; - int LA51_0 = input.LA(1); - - if ( ((LA51_0>=65 && LA51_0<=66)) ) { - alt51=1; - } - switch (alt51) { - case 1 : - // JPA.g:250:49: ( '+' | '-' ) INT_NUMERAL - { - set156=(Token)input.LT(1); - if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set156)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - INT_NUMERAL157=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_date_between_macro_expression2005); if (state.failed) return retval; - if ( state.backtracking==0 ) { - INT_NUMERAL157_tree = (Object)adaptor.create(INT_NUMERAL157); - adaptor.addChild(root_0, INT_NUMERAL157_tree); - } - - } - break; - - } - - char_literal158=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression2009); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal158_tree = (Object)adaptor.create(char_literal158); - adaptor.addChild(root_0, char_literal158_tree); - } - string_literal159=(Token)match(input,64,FOLLOW_64_in_date_between_macro_expression2011); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal159_tree = (Object)adaptor.create(string_literal159); - adaptor.addChild(root_0, string_literal159_tree); - } - // JPA.g:250:85: ( ( '+' | '-' ) INT_NUMERAL )? - int alt52=2; - int LA52_0 = input.LA(1); - - if ( ((LA52_0>=65 && LA52_0<=66)) ) { - alt52=1; - } - switch (alt52) { - case 1 : - // JPA.g:250:86: ( '+' | '-' ) INT_NUMERAL - { - set160=(Token)input.LT(1); - if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set160)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - INT_NUMERAL161=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_date_between_macro_expression2022); if (state.failed) return retval; - if ( state.backtracking==0 ) { - INT_NUMERAL161_tree = (Object)adaptor.create(INT_NUMERAL161); - adaptor.addChild(root_0, INT_NUMERAL161_tree); - } - - } - break; - - } - - char_literal162=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression2026); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal162_tree = (Object)adaptor.create(char_literal162); - adaptor.addChild(root_0, char_literal162_tree); - } - set163=(Token)input.LT(1); - if ( (input.LA(1)>=67 && input.LA(1)<=72) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set163)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - char_literal164=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_between_macro_expression2051); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal164_tree = (Object)adaptor.create(char_literal164); - adaptor.addChild(root_0, char_literal164_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_between_macro_expression" - - public static class date_before_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_before_macro_expression" - // JPA.g:252:1: date_before_macro_expression : '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; - public final JPAParser.date_before_macro_expression_return date_before_macro_expression() throws RecognitionException { - JPAParser.date_before_macro_expression_return retval = new JPAParser.date_before_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal165=null; - Token char_literal166=null; - Token char_literal168=null; - Token char_literal171=null; - JPAParser.path_expression_return path_expression167 = null; - - JPAParser.path_expression_return path_expression169 = null; - - JPAParser.input_parameter_return input_parameter170 = null; - - - Object string_literal165_tree=null; - Object char_literal166_tree=null; - Object char_literal168_tree=null; - Object char_literal171_tree=null; - - try { - // JPA.g:253:5: ( '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) - // JPA.g:253:7: '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal165=(Token)match(input,73,FOLLOW_73_in_date_before_macro_expression2063); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal165_tree = (Object)adaptor.create(string_literal165); - adaptor.addChild(root_0, string_literal165_tree); - } - char_literal166=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_before_macro_expression2065); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal166_tree = (Object)adaptor.create(char_literal166); - adaptor.addChild(root_0, char_literal166_tree); - } - pushFollow(FOLLOW_path_expression_in_date_before_macro_expression2067); - path_expression167=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression167.getTree()); - char_literal168=(Token)match(input,54,FOLLOW_54_in_date_before_macro_expression2069); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal168_tree = (Object)adaptor.create(char_literal168); - adaptor.addChild(root_0, char_literal168_tree); - } - // JPA.g:253:45: ( path_expression | input_parameter ) - int alt53=2; - int LA53_0 = input.LA(1); - - if ( (LA53_0==WORD) ) { - alt53=1; - } - else if ( (LA53_0==NAMED_PARAMETER||(LA53_0>=115 && LA53_0<=116)) ) { - alt53=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 53, 0, input); - - throw nvae; - } - switch (alt53) { - case 1 : - // JPA.g:253:46: path_expression - { - pushFollow(FOLLOW_path_expression_in_date_before_macro_expression2072); - path_expression169=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression169.getTree()); - - } - break; - case 2 : - // JPA.g:253:64: input_parameter - { - pushFollow(FOLLOW_input_parameter_in_date_before_macro_expression2076); - input_parameter170=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter170.getTree()); - - } - break; - - } - - char_literal171=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_before_macro_expression2079); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal171_tree = (Object)adaptor.create(char_literal171); - adaptor.addChild(root_0, char_literal171_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_before_macro_expression" - - public static class date_after_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_after_macro_expression" - // JPA.g:255:1: date_after_macro_expression : '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; - public final JPAParser.date_after_macro_expression_return date_after_macro_expression() throws RecognitionException { - JPAParser.date_after_macro_expression_return retval = new JPAParser.date_after_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal172=null; - Token char_literal173=null; - Token char_literal175=null; - Token char_literal178=null; - JPAParser.path_expression_return path_expression174 = null; - - JPAParser.path_expression_return path_expression176 = null; - - JPAParser.input_parameter_return input_parameter177 = null; - - - Object string_literal172_tree=null; - Object char_literal173_tree=null; - Object char_literal175_tree=null; - Object char_literal178_tree=null; - - try { - // JPA.g:256:5: ( '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) - // JPA.g:256:7: '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal172=(Token)match(input,74,FOLLOW_74_in_date_after_macro_expression2091); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal172_tree = (Object)adaptor.create(string_literal172); - adaptor.addChild(root_0, string_literal172_tree); - } - char_literal173=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_after_macro_expression2093); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal173_tree = (Object)adaptor.create(char_literal173); - adaptor.addChild(root_0, char_literal173_tree); - } - pushFollow(FOLLOW_path_expression_in_date_after_macro_expression2095); - path_expression174=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression174.getTree()); - char_literal175=(Token)match(input,54,FOLLOW_54_in_date_after_macro_expression2097); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal175_tree = (Object)adaptor.create(char_literal175); - adaptor.addChild(root_0, char_literal175_tree); - } - // JPA.g:256:44: ( path_expression | input_parameter ) - int alt54=2; - int LA54_0 = input.LA(1); - - if ( (LA54_0==WORD) ) { - alt54=1; - } - else if ( (LA54_0==NAMED_PARAMETER||(LA54_0>=115 && LA54_0<=116)) ) { - alt54=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 54, 0, input); - - throw nvae; - } - switch (alt54) { - case 1 : - // JPA.g:256:45: path_expression - { - pushFollow(FOLLOW_path_expression_in_date_after_macro_expression2100); - path_expression176=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression176.getTree()); - - } - break; - case 2 : - // JPA.g:256:63: input_parameter - { - pushFollow(FOLLOW_input_parameter_in_date_after_macro_expression2104); - input_parameter177=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter177.getTree()); - - } - break; - - } - - char_literal178=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_after_macro_expression2107); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal178_tree = (Object)adaptor.create(char_literal178); - adaptor.addChild(root_0, char_literal178_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_after_macro_expression" - - public static class date_equals_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_equals_macro_expression" - // JPA.g:258:1: date_equals_macro_expression : '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; - public final JPAParser.date_equals_macro_expression_return date_equals_macro_expression() throws RecognitionException { - JPAParser.date_equals_macro_expression_return retval = new JPAParser.date_equals_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal179=null; - Token char_literal180=null; - Token char_literal182=null; - Token char_literal185=null; - JPAParser.path_expression_return path_expression181 = null; - - JPAParser.path_expression_return path_expression183 = null; - - JPAParser.input_parameter_return input_parameter184 = null; - - - Object string_literal179_tree=null; - Object char_literal180_tree=null; - Object char_literal182_tree=null; - Object char_literal185_tree=null; - - try { - // JPA.g:259:5: ( '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) - // JPA.g:259:7: '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal179=(Token)match(input,75,FOLLOW_75_in_date_equals_macro_expression2119); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal179_tree = (Object)adaptor.create(string_literal179); - adaptor.addChild(root_0, string_literal179_tree); - } - char_literal180=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_equals_macro_expression2121); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal180_tree = (Object)adaptor.create(char_literal180); - adaptor.addChild(root_0, char_literal180_tree); - } - pushFollow(FOLLOW_path_expression_in_date_equals_macro_expression2123); - path_expression181=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression181.getTree()); - char_literal182=(Token)match(input,54,FOLLOW_54_in_date_equals_macro_expression2125); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal182_tree = (Object)adaptor.create(char_literal182); - adaptor.addChild(root_0, char_literal182_tree); - } - // JPA.g:259:45: ( path_expression | input_parameter ) - int alt55=2; - int LA55_0 = input.LA(1); - - if ( (LA55_0==WORD) ) { - alt55=1; - } - else if ( (LA55_0==NAMED_PARAMETER||(LA55_0>=115 && LA55_0<=116)) ) { - alt55=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 55, 0, input); - - throw nvae; - } - switch (alt55) { - case 1 : - // JPA.g:259:46: path_expression - { - pushFollow(FOLLOW_path_expression_in_date_equals_macro_expression2128); - path_expression183=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression183.getTree()); - - } - break; - case 2 : - // JPA.g:259:64: input_parameter - { - pushFollow(FOLLOW_input_parameter_in_date_equals_macro_expression2132); - input_parameter184=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter184.getTree()); - - } - break; - - } - - char_literal185=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_equals_macro_expression2135); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal185_tree = (Object)adaptor.create(char_literal185); - adaptor.addChild(root_0, char_literal185_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_equals_macro_expression" - - public static class date_today_macro_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "date_today_macro_expression" - // JPA.g:261:1: date_today_macro_expression : '@TODAY' '(' path_expression ')' ; - public final JPAParser.date_today_macro_expression_return date_today_macro_expression() throws RecognitionException { - JPAParser.date_today_macro_expression_return retval = new JPAParser.date_today_macro_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal186=null; - Token char_literal187=null; - Token char_literal189=null; - JPAParser.path_expression_return path_expression188 = null; - - - Object string_literal186_tree=null; - Object char_literal187_tree=null; - Object char_literal189_tree=null; - - try { - // JPA.g:262:5: ( '@TODAY' '(' path_expression ')' ) - // JPA.g:262:7: '@TODAY' '(' path_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal186=(Token)match(input,76,FOLLOW_76_in_date_today_macro_expression2147); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal186_tree = (Object)adaptor.create(string_literal186); - adaptor.addChild(root_0, string_literal186_tree); - } - char_literal187=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_today_macro_expression2149); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal187_tree = (Object)adaptor.create(char_literal187); - adaptor.addChild(root_0, char_literal187_tree); - } - pushFollow(FOLLOW_path_expression_in_date_today_macro_expression2151); - path_expression188=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression188.getTree()); - char_literal189=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_today_macro_expression2153); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal189_tree = (Object)adaptor.create(char_literal189); - adaptor.addChild(root_0, char_literal189_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "date_today_macro_expression" - - public static class between_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "between_expression" - // JPA.g:264:1: between_expression : ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression | string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression | datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression ); - public final JPAParser.between_expression_return between_expression() throws RecognitionException { - JPAParser.between_expression_return retval = new JPAParser.between_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal191=null; - Token string_literal192=null; - Token string_literal194=null; - Token string_literal197=null; - Token string_literal198=null; - Token string_literal200=null; - Token string_literal203=null; - Token string_literal204=null; - Token string_literal206=null; - JPAParser.arithmetic_expression_return arithmetic_expression190 = null; - - JPAParser.arithmetic_expression_return arithmetic_expression193 = null; - - JPAParser.arithmetic_expression_return arithmetic_expression195 = null; - - JPAParser.string_expression_return string_expression196 = null; - - JPAParser.string_expression_return string_expression199 = null; - - JPAParser.string_expression_return string_expression201 = null; - - JPAParser.datetime_expression_return datetime_expression202 = null; - - JPAParser.datetime_expression_return datetime_expression205 = null; - - JPAParser.datetime_expression_return datetime_expression207 = null; - - - Object string_literal191_tree=null; - Object string_literal192_tree=null; - Object string_literal194_tree=null; - Object string_literal197_tree=null; - Object string_literal198_tree=null; - Object string_literal200_tree=null; - Object string_literal203_tree=null; - Object string_literal204_tree=null; - Object string_literal206_tree=null; - - try { - // JPA.g:265:5: ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression | string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression | datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression ) - int alt59=3; - alt59 = dfa59.predict(input); - switch (alt59) { - case 1 : - // JPA.g:265:7: arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_arithmetic_expression_in_between_expression2165); - arithmetic_expression190=arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression190.getTree()); - // JPA.g:265:29: ( 'NOT' )? - int alt56=2; - int LA56_0 = input.LA(1); - - if ( (LA56_0==62) ) { - alt56=1; - } - switch (alt56) { - case 1 : - // JPA.g:265:30: 'NOT' - { - string_literal191=(Token)match(input,62,FOLLOW_62_in_between_expression2168); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal191_tree = (Object)adaptor.create(string_literal191); - adaptor.addChild(root_0, string_literal191_tree); - } - - } - break; - - } - - string_literal192=(Token)match(input,77,FOLLOW_77_in_between_expression2172); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal192_tree = (Object)adaptor.create(string_literal192); - adaptor.addChild(root_0, string_literal192_tree); - } - pushFollow(FOLLOW_arithmetic_expression_in_between_expression2174); - arithmetic_expression193=arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression193.getTree()); - string_literal194=(Token)match(input,AND,FOLLOW_AND_in_between_expression2176); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal194_tree = (Object)adaptor.create(string_literal194); - adaptor.addChild(root_0, string_literal194_tree); - } - pushFollow(FOLLOW_arithmetic_expression_in_between_expression2178); - arithmetic_expression195=arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression195.getTree()); - - } - break; - case 2 : - // JPA.g:266:7: string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_string_expression_in_between_expression2186); - string_expression196=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression196.getTree()); - // JPA.g:266:25: ( 'NOT' )? - int alt57=2; - int LA57_0 = input.LA(1); - - if ( (LA57_0==62) ) { - alt57=1; - } - switch (alt57) { - case 1 : - // JPA.g:266:26: 'NOT' - { - string_literal197=(Token)match(input,62,FOLLOW_62_in_between_expression2189); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal197_tree = (Object)adaptor.create(string_literal197); - adaptor.addChild(root_0, string_literal197_tree); - } - - } - break; - - } - - string_literal198=(Token)match(input,77,FOLLOW_77_in_between_expression2193); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal198_tree = (Object)adaptor.create(string_literal198); - adaptor.addChild(root_0, string_literal198_tree); - } - pushFollow(FOLLOW_string_expression_in_between_expression2195); - string_expression199=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression199.getTree()); - string_literal200=(Token)match(input,AND,FOLLOW_AND_in_between_expression2197); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal200_tree = (Object)adaptor.create(string_literal200); - adaptor.addChild(root_0, string_literal200_tree); - } - pushFollow(FOLLOW_string_expression_in_between_expression2199); - string_expression201=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression201.getTree()); - - } - break; - case 3 : - // JPA.g:267:7: datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_datetime_expression_in_between_expression2207); - datetime_expression202=datetime_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression202.getTree()); - // JPA.g:267:27: ( 'NOT' )? - int alt58=2; - int LA58_0 = input.LA(1); - - if ( (LA58_0==62) ) { - alt58=1; - } - switch (alt58) { - case 1 : - // JPA.g:267:28: 'NOT' - { - string_literal203=(Token)match(input,62,FOLLOW_62_in_between_expression2210); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal203_tree = (Object)adaptor.create(string_literal203); - adaptor.addChild(root_0, string_literal203_tree); - } - - } - break; - - } - - string_literal204=(Token)match(input,77,FOLLOW_77_in_between_expression2214); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal204_tree = (Object)adaptor.create(string_literal204); - adaptor.addChild(root_0, string_literal204_tree); - } - pushFollow(FOLLOW_datetime_expression_in_between_expression2216); - datetime_expression205=datetime_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression205.getTree()); - string_literal206=(Token)match(input,AND,FOLLOW_AND_in_between_expression2218); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal206_tree = (Object)adaptor.create(string_literal206); - adaptor.addChild(root_0, string_literal206_tree); - } - pushFollow(FOLLOW_datetime_expression_in_between_expression2220); - datetime_expression207=datetime_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression207.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "between_expression" - - public static class in_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "in_expression" - // JPA.g:269:1: in_expression : path_expression ( 'NOT' )? 'IN' in_expression_right_part ; - public final JPAParser.in_expression_return in_expression() throws RecognitionException { - JPAParser.in_expression_return retval = new JPAParser.in_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal209=null; - Token string_literal210=null; - JPAParser.path_expression_return path_expression208 = null; - - JPAParser.in_expression_right_part_return in_expression_right_part211 = null; - - - Object string_literal209_tree=null; - Object string_literal210_tree=null; - - try { - // JPA.g:270:5: ( path_expression ( 'NOT' )? 'IN' in_expression_right_part ) - // JPA.g:270:7: path_expression ( 'NOT' )? 'IN' in_expression_right_part - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_in_expression2232); - path_expression208=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression208.getTree()); - // JPA.g:270:23: ( 'NOT' )? - int alt60=2; - int LA60_0 = input.LA(1); - - if ( (LA60_0==62) ) { - alt60=1; - } - switch (alt60) { - case 1 : - // JPA.g:270:24: 'NOT' - { - string_literal209=(Token)match(input,62,FOLLOW_62_in_in_expression2235); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal209_tree = (Object)adaptor.create(string_literal209); - adaptor.addChild(root_0, string_literal209_tree); - } - - } - break; - - } - - string_literal210=(Token)match(input,58,FOLLOW_58_in_in_expression2239); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal210_tree = (Object)adaptor.create(string_literal210); - adaptor.addChild(root_0, string_literal210_tree); - } - pushFollow(FOLLOW_in_expression_right_part_in_in_expression2241); - in_expression_right_part211=in_expression_right_part(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, in_expression_right_part211.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "in_expression" - - public static class in_expression_right_part_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "in_expression_right_part" - // JPA.g:272:1: in_expression_right_part : ( '(' in_item ( ',' in_item )* ')' | subquery ); - public final JPAParser.in_expression_right_part_return in_expression_right_part() throws RecognitionException { - JPAParser.in_expression_right_part_return retval = new JPAParser.in_expression_right_part_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal212=null; - Token char_literal214=null; - Token char_literal216=null; - JPAParser.in_item_return in_item213 = null; - - JPAParser.in_item_return in_item215 = null; - - JPAParser.subquery_return subquery217 = null; - - - Object char_literal212_tree=null; - Object char_literal214_tree=null; - Object char_literal216_tree=null; - - try { - // JPA.g:273:5: ( '(' in_item ( ',' in_item )* ')' | subquery ) - int alt62=2; - int LA62_0 = input.LA(1); - - if ( (LA62_0==LPAREN) ) { - alt62=1; - } - else if ( (LA62_0==56) ) { - alt62=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 62, 0, input); - - throw nvae; - } - switch (alt62) { - case 1 : - // JPA.g:273:7: '(' in_item ( ',' in_item )* ')' - { - root_0 = (Object)adaptor.nil(); - - char_literal212=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_in_expression_right_part2253); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal212_tree = (Object)adaptor.create(char_literal212); - adaptor.addChild(root_0, char_literal212_tree); - } - pushFollow(FOLLOW_in_item_in_in_expression_right_part2255); - in_item213=in_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, in_item213.getTree()); - // JPA.g:273:19: ( ',' in_item )* - loop61: - do { - int alt61=2; - int LA61_0 = input.LA(1); - - if ( (LA61_0==54) ) { - alt61=1; - } - - - switch (alt61) { - case 1 : - // JPA.g:273:20: ',' in_item - { - char_literal214=(Token)match(input,54,FOLLOW_54_in_in_expression_right_part2258); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal214_tree = (Object)adaptor.create(char_literal214); - adaptor.addChild(root_0, char_literal214_tree); - } - pushFollow(FOLLOW_in_item_in_in_expression_right_part2260); - in_item215=in_item(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, in_item215.getTree()); - - } - break; - - default : - break loop61; - } - } while (true); - - char_literal216=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_in_expression_right_part2264); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal216_tree = (Object)adaptor.create(char_literal216); - adaptor.addChild(root_0, char_literal216_tree); - } - - } - break; - case 2 : - // JPA.g:274:7: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_in_expression_right_part2272); - subquery217=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery217.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "in_expression_right_part" - - public static class in_item_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "in_item" - // JPA.g:276:1: in_item : ( literal | input_parameter ); - public final JPAParser.in_item_return in_item() throws RecognitionException { - JPAParser.in_item_return retval = new JPAParser.in_item_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.literal_return literal218 = null; - - JPAParser.input_parameter_return input_parameter219 = null; - - - - try { - // JPA.g:277:5: ( literal | input_parameter ) - int alt63=2; - int LA63_0 = input.LA(1); - - if ( (LA63_0==WORD) ) { - alt63=1; - } - else if ( (LA63_0==NAMED_PARAMETER||(LA63_0>=115 && LA63_0<=116)) ) { - alt63=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 63, 0, input); - - throw nvae; - } - switch (alt63) { - case 1 : - // JPA.g:277:7: literal - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_literal_in_in_item2284); - literal218=literal(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, literal218.getTree()); - - } - break; - case 2 : - // JPA.g:278:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_in_item2292); - input_parameter219=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter219.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "in_item" - - public static class like_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "like_expression" - // JPA.g:280:1: like_expression : string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? ; - public final JPAParser.like_expression_return like_expression() throws RecognitionException { - JPAParser.like_expression_return retval = new JPAParser.like_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal221=null; - Token string_literal222=null; - Token string_literal225=null; - Token ESCAPE_CHARACTER226=null; - JPAParser.string_expression_return string_expression220 = null; - - JPAParser.pattern_value_return pattern_value223 = null; - - JPAParser.input_parameter_return input_parameter224 = null; - - - Object string_literal221_tree=null; - Object string_literal222_tree=null; - Object string_literal225_tree=null; - Object ESCAPE_CHARACTER226_tree=null; - - try { - // JPA.g:281:5: ( string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? ) - // JPA.g:281:7: string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_string_expression_in_like_expression2304); - string_expression220=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression220.getTree()); - // JPA.g:281:25: ( 'NOT' )? - int alt64=2; - int LA64_0 = input.LA(1); - - if ( (LA64_0==62) ) { - alt64=1; - } - switch (alt64) { - case 1 : - // JPA.g:281:26: 'NOT' - { - string_literal221=(Token)match(input,62,FOLLOW_62_in_like_expression2307); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal221_tree = (Object)adaptor.create(string_literal221); - adaptor.addChild(root_0, string_literal221_tree); - } - - } - break; - - } - - string_literal222=(Token)match(input,78,FOLLOW_78_in_like_expression2311); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal222_tree = (Object)adaptor.create(string_literal222); - adaptor.addChild(root_0, string_literal222_tree); - } - // JPA.g:281:41: ( pattern_value | input_parameter ) - int alt65=2; - int LA65_0 = input.LA(1); - - if ( (LA65_0==WORD) ) { - alt65=1; - } - else if ( (LA65_0==NAMED_PARAMETER||(LA65_0>=115 && LA65_0<=116)) ) { - alt65=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 65, 0, input); - - throw nvae; - } - switch (alt65) { - case 1 : - // JPA.g:281:42: pattern_value - { - pushFollow(FOLLOW_pattern_value_in_like_expression2314); - pattern_value223=pattern_value(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, pattern_value223.getTree()); - - } - break; - case 2 : - // JPA.g:281:58: input_parameter - { - pushFollow(FOLLOW_input_parameter_in_like_expression2318); - input_parameter224=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter224.getTree()); - - } - break; - - } - - // JPA.g:281:74: ( 'ESCAPE' ESCAPE_CHARACTER )? - int alt66=2; - int LA66_0 = input.LA(1); - - if ( (LA66_0==79) ) { - alt66=1; - } - switch (alt66) { - case 1 : - // JPA.g:281:75: 'ESCAPE' ESCAPE_CHARACTER - { - string_literal225=(Token)match(input,79,FOLLOW_79_in_like_expression2321); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal225_tree = (Object)adaptor.create(string_literal225); - adaptor.addChild(root_0, string_literal225_tree); - } - ESCAPE_CHARACTER226=(Token)match(input,ESCAPE_CHARACTER,FOLLOW_ESCAPE_CHARACTER_in_like_expression2323); if (state.failed) return retval; - if ( state.backtracking==0 ) { - ESCAPE_CHARACTER226_tree = (Object)adaptor.create(ESCAPE_CHARACTER226); - adaptor.addChild(root_0, ESCAPE_CHARACTER226_tree); - } - - } - break; - - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "like_expression" - - public static class null_comparison_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "null_comparison_expression" - // JPA.g:283:1: null_comparison_expression : ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' ; - public final JPAParser.null_comparison_expression_return null_comparison_expression() throws RecognitionException { - JPAParser.null_comparison_expression_return retval = new JPAParser.null_comparison_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal229=null; - Token string_literal230=null; - Token string_literal231=null; - JPAParser.path_expression_return path_expression227 = null; - - JPAParser.input_parameter_return input_parameter228 = null; - - - Object string_literal229_tree=null; - Object string_literal230_tree=null; - Object string_literal231_tree=null; - - try { - // JPA.g:284:5: ( ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' ) - // JPA.g:284:7: ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:284:7: ( path_expression | input_parameter ) - int alt67=2; - int LA67_0 = input.LA(1); - - if ( (LA67_0==WORD) ) { - alt67=1; - } - else if ( (LA67_0==NAMED_PARAMETER||(LA67_0>=115 && LA67_0<=116)) ) { - alt67=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 67, 0, input); - - throw nvae; - } - switch (alt67) { - case 1 : - // JPA.g:284:8: path_expression - { - pushFollow(FOLLOW_path_expression_in_null_comparison_expression2338); - path_expression227=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression227.getTree()); - - } - break; - case 2 : - // JPA.g:284:26: input_parameter - { - pushFollow(FOLLOW_input_parameter_in_null_comparison_expression2342); - input_parameter228=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter228.getTree()); - - } - break; - - } - - string_literal229=(Token)match(input,80,FOLLOW_80_in_null_comparison_expression2345); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal229_tree = (Object)adaptor.create(string_literal229); - adaptor.addChild(root_0, string_literal229_tree); - } - // JPA.g:284:48: ( 'NOT' )? - int alt68=2; - int LA68_0 = input.LA(1); - - if ( (LA68_0==62) ) { - alt68=1; - } - switch (alt68) { - case 1 : - // JPA.g:284:49: 'NOT' - { - string_literal230=(Token)match(input,62,FOLLOW_62_in_null_comparison_expression2348); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal230_tree = (Object)adaptor.create(string_literal230); - adaptor.addChild(root_0, string_literal230_tree); - } - - } - break; - - } - - string_literal231=(Token)match(input,81,FOLLOW_81_in_null_comparison_expression2352); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal231_tree = (Object)adaptor.create(string_literal231); - adaptor.addChild(root_0, string_literal231_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "null_comparison_expression" - - public static class empty_collection_comparison_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "empty_collection_comparison_expression" - // JPA.g:286:1: empty_collection_comparison_expression : path_expression 'IS' ( 'NOT' )? 'EMPTY' ; - public final JPAParser.empty_collection_comparison_expression_return empty_collection_comparison_expression() throws RecognitionException { - JPAParser.empty_collection_comparison_expression_return retval = new JPAParser.empty_collection_comparison_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal233=null; - Token string_literal234=null; - Token string_literal235=null; - JPAParser.path_expression_return path_expression232 = null; - - - Object string_literal233_tree=null; - Object string_literal234_tree=null; - Object string_literal235_tree=null; - - try { - // JPA.g:287:5: ( path_expression 'IS' ( 'NOT' )? 'EMPTY' ) - // JPA.g:287:7: path_expression 'IS' ( 'NOT' )? 'EMPTY' - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_empty_collection_comparison_expression2364); - path_expression232=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression232.getTree()); - string_literal233=(Token)match(input,80,FOLLOW_80_in_empty_collection_comparison_expression2366); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal233_tree = (Object)adaptor.create(string_literal233); - adaptor.addChild(root_0, string_literal233_tree); - } - // JPA.g:287:28: ( 'NOT' )? - int alt69=2; - int LA69_0 = input.LA(1); - - if ( (LA69_0==62) ) { - alt69=1; - } - switch (alt69) { - case 1 : - // JPA.g:287:29: 'NOT' - { - string_literal234=(Token)match(input,62,FOLLOW_62_in_empty_collection_comparison_expression2369); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal234_tree = (Object)adaptor.create(string_literal234); - adaptor.addChild(root_0, string_literal234_tree); - } - - } - break; - - } - - string_literal235=(Token)match(input,82,FOLLOW_82_in_empty_collection_comparison_expression2373); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal235_tree = (Object)adaptor.create(string_literal235); - adaptor.addChild(root_0, string_literal235_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "empty_collection_comparison_expression" - - public static class collection_member_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "collection_member_expression" - // JPA.g:289:1: collection_member_expression : entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression ; - public final JPAParser.collection_member_expression_return collection_member_expression() throws RecognitionException { - JPAParser.collection_member_expression_return retval = new JPAParser.collection_member_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal237=null; - Token string_literal238=null; - Token string_literal239=null; - JPAParser.entity_expression_return entity_expression236 = null; - - JPAParser.path_expression_return path_expression240 = null; - - - Object string_literal237_tree=null; - Object string_literal238_tree=null; - Object string_literal239_tree=null; - - try { - // JPA.g:290:5: ( entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression ) - // JPA.g:290:7: entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_entity_expression_in_collection_member_expression2385); - entity_expression236=entity_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression236.getTree()); - // JPA.g:290:25: ( 'NOT' )? - int alt70=2; - int LA70_0 = input.LA(1); - - if ( (LA70_0==62) ) { - alt70=1; - } - switch (alt70) { - case 1 : - // JPA.g:290:26: 'NOT' - { - string_literal237=(Token)match(input,62,FOLLOW_62_in_collection_member_expression2388); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal237_tree = (Object)adaptor.create(string_literal237); - adaptor.addChild(root_0, string_literal237_tree); - } - - } - break; - - } - - string_literal238=(Token)match(input,83,FOLLOW_83_in_collection_member_expression2392); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal238_tree = (Object)adaptor.create(string_literal238); - adaptor.addChild(root_0, string_literal238_tree); - } - // JPA.g:290:43: ( 'OF' )? - int alt71=2; - int LA71_0 = input.LA(1); - - if ( (LA71_0==84) ) { - alt71=1; - } - switch (alt71) { - case 1 : - // JPA.g:290:44: 'OF' - { - string_literal239=(Token)match(input,84,FOLLOW_84_in_collection_member_expression2395); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal239_tree = (Object)adaptor.create(string_literal239); - adaptor.addChild(root_0, string_literal239_tree); - } - - } - break; - - } - - pushFollow(FOLLOW_path_expression_in_collection_member_expression2399); - path_expression240=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression240.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "collection_member_expression" - - public static class exists_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "exists_expression" - // JPA.g:292:1: exists_expression : ( 'NOT' )? 'EXISTS' subquery ; - public final JPAParser.exists_expression_return exists_expression() throws RecognitionException { - JPAParser.exists_expression_return retval = new JPAParser.exists_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal241=null; - Token string_literal242=null; - JPAParser.subquery_return subquery243 = null; - - - Object string_literal241_tree=null; - Object string_literal242_tree=null; - - try { - // JPA.g:293:5: ( ( 'NOT' )? 'EXISTS' subquery ) - // JPA.g:293:7: ( 'NOT' )? 'EXISTS' subquery - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:293:7: ( 'NOT' )? - int alt72=2; - int LA72_0 = input.LA(1); - - if ( (LA72_0==62) ) { - alt72=1; - } - switch (alt72) { - case 1 : - // JPA.g:293:8: 'NOT' - { - string_literal241=(Token)match(input,62,FOLLOW_62_in_exists_expression2412); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal241_tree = (Object)adaptor.create(string_literal241); - adaptor.addChild(root_0, string_literal241_tree); - } - - } - break; - - } - - string_literal242=(Token)match(input,85,FOLLOW_85_in_exists_expression2416); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal242_tree = (Object)adaptor.create(string_literal242); - adaptor.addChild(root_0, string_literal242_tree); - } - pushFollow(FOLLOW_subquery_in_exists_expression2418); - subquery243=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery243.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "exists_expression" - - public static class all_or_any_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "all_or_any_expression" - // JPA.g:295:1: all_or_any_expression : ( 'ALL' | 'ANY' | 'SOME' ) subquery ; - public final JPAParser.all_or_any_expression_return all_or_any_expression() throws RecognitionException { - JPAParser.all_or_any_expression_return retval = new JPAParser.all_or_any_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set244=null; - JPAParser.subquery_return subquery245 = null; - - - Object set244_tree=null; - - try { - // JPA.g:296:5: ( ( 'ALL' | 'ANY' | 'SOME' ) subquery ) - // JPA.g:296:7: ( 'ALL' | 'ANY' | 'SOME' ) subquery - { - root_0 = (Object)adaptor.nil(); - - set244=(Token)input.LT(1); - if ( (input.LA(1)>=86 && input.LA(1)<=88) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set244)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - pushFollow(FOLLOW_subquery_in_all_or_any_expression2443); - subquery245=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery245.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "all_or_any_expression" - - public static class comparison_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "comparison_expression" - // JPA.g:298:1: comparison_expression : ( string_expression comparison_operator ( string_expression | all_or_any_expression ) | boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) ); - public final JPAParser.comparison_expression_return comparison_expression() throws RecognitionException { - JPAParser.comparison_expression_return retval = new JPAParser.comparison_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set251=null; - Token set255=null; - Token set263=null; - JPAParser.string_expression_return string_expression246 = null; - - JPAParser.comparison_operator_return comparison_operator247 = null; - - JPAParser.string_expression_return string_expression248 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression249 = null; - - JPAParser.boolean_expression_return boolean_expression250 = null; - - JPAParser.boolean_expression_return boolean_expression252 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression253 = null; - - JPAParser.enum_expression_return enum_expression254 = null; - - JPAParser.enum_expression_return enum_expression256 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression257 = null; - - JPAParser.datetime_expression_return datetime_expression258 = null; - - JPAParser.comparison_operator_return comparison_operator259 = null; - - JPAParser.datetime_expression_return datetime_expression260 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression261 = null; - - JPAParser.entity_expression_return entity_expression262 = null; - - JPAParser.entity_expression_return entity_expression264 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression265 = null; - - JPAParser.arithmetic_expression_return arithmetic_expression266 = null; - - JPAParser.comparison_operator_return comparison_operator267 = null; - - JPAParser.arithmetic_expression_return arithmetic_expression268 = null; - - JPAParser.all_or_any_expression_return all_or_any_expression269 = null; - - - Object set251_tree=null; - Object set255_tree=null; - Object set263_tree=null; - - try { - // JPA.g:299:5: ( string_expression comparison_operator ( string_expression | all_or_any_expression ) | boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) ) - int alt79=6; - alt79 = dfa79.predict(input); - switch (alt79) { - case 1 : - // JPA.g:299:7: string_expression comparison_operator ( string_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_string_expression_in_comparison_expression2455); - string_expression246=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression246.getTree()); - pushFollow(FOLLOW_comparison_operator_in_comparison_expression2457); - comparison_operator247=comparison_operator(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator247.getTree()); - // JPA.g:299:45: ( string_expression | all_or_any_expression ) - int alt73=2; - int LA73_0 = input.LA(1); - - if ( ((LA73_0>=AVG && LA73_0<=COUNT)||LA73_0==STRINGLITERAL||(LA73_0>=WORD && LA73_0<=NAMED_PARAMETER)||LA73_0==56||(LA73_0>=106 && LA73_0<=110)||(LA73_0>=115 && LA73_0<=116)) ) { - alt73=1; - } - else if ( ((LA73_0>=86 && LA73_0<=88)) ) { - alt73=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 73, 0, input); - - throw nvae; - } - switch (alt73) { - case 1 : - // JPA.g:299:46: string_expression - { - pushFollow(FOLLOW_string_expression_in_comparison_expression2460); - string_expression248=string_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression248.getTree()); - - } - break; - case 2 : - // JPA.g:299:66: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2464); - all_or_any_expression249=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression249.getTree()); - - } - break; - - } - - - } - break; - case 2 : - // JPA.g:300:7: boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_boolean_expression_in_comparison_expression2473); - boolean_expression250=boolean_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_expression250.getTree()); - set251=(Token)input.LT(1); - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set251)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:300:39: ( boolean_expression | all_or_any_expression ) - int alt74=2; - int LA74_0 = input.LA(1); - - if ( ((LA74_0>=WORD && LA74_0<=NAMED_PARAMETER)||LA74_0==56||(LA74_0>=115 && LA74_0<=116)||(LA74_0>=118 && LA74_0<=119)) ) { - alt74=1; - } - else if ( ((LA74_0>=86 && LA74_0<=88)) ) { - alt74=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 74, 0, input); - - throw nvae; - } - switch (alt74) { - case 1 : - // JPA.g:300:40: boolean_expression - { - pushFollow(FOLLOW_boolean_expression_in_comparison_expression2484); - boolean_expression252=boolean_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_expression252.getTree()); - - } - break; - case 2 : - // JPA.g:300:61: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2488); - all_or_any_expression253=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression253.getTree()); - - } - break; - - } - - - } - break; - case 3 : - // JPA.g:301:7: enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_enum_expression_in_comparison_expression2497); - enum_expression254=enum_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_expression254.getTree()); - set255=(Token)input.LT(1); - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set255)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:301:34: ( enum_expression | all_or_any_expression ) - int alt75=2; - int LA75_0 = input.LA(1); - - if ( ((LA75_0>=WORD && LA75_0<=NAMED_PARAMETER)||LA75_0==56||(LA75_0>=115 && LA75_0<=116)) ) { - alt75=1; - } - else if ( ((LA75_0>=86 && LA75_0<=88)) ) { - alt75=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 75, 0, input); - - throw nvae; - } - switch (alt75) { - case 1 : - // JPA.g:301:35: enum_expression - { - pushFollow(FOLLOW_enum_expression_in_comparison_expression2506); - enum_expression256=enum_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_expression256.getTree()); - - } - break; - case 2 : - // JPA.g:301:53: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2510); - all_or_any_expression257=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression257.getTree()); - - } - break; - - } - - - } - break; - case 4 : - // JPA.g:302:7: datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_datetime_expression_in_comparison_expression2519); - datetime_expression258=datetime_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression258.getTree()); - pushFollow(FOLLOW_comparison_operator_in_comparison_expression2521); - comparison_operator259=comparison_operator(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator259.getTree()); - // JPA.g:302:47: ( datetime_expression | all_or_any_expression ) - int alt76=2; - int LA76_0 = input.LA(1); - - if ( ((LA76_0>=AVG && LA76_0<=COUNT)||(LA76_0>=WORD && LA76_0<=NAMED_PARAMETER)||LA76_0==56||(LA76_0>=103 && LA76_0<=105)||(LA76_0>=115 && LA76_0<=116)) ) { - alt76=1; - } - else if ( ((LA76_0>=86 && LA76_0<=88)) ) { - alt76=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 76, 0, input); - - throw nvae; - } - switch (alt76) { - case 1 : - // JPA.g:302:48: datetime_expression - { - pushFollow(FOLLOW_datetime_expression_in_comparison_expression2524); - datetime_expression260=datetime_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression260.getTree()); - - } - break; - case 2 : - // JPA.g:302:70: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2528); - all_or_any_expression261=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression261.getTree()); - - } - break; - - } - - - } - break; - case 5 : - // JPA.g:303:7: entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_entity_expression_in_comparison_expression2537); - entity_expression262=entity_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression262.getTree()); - set263=(Token)input.LT(1); - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set263)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:303:38: ( entity_expression | all_or_any_expression ) - int alt77=2; - int LA77_0 = input.LA(1); - - if ( ((LA77_0>=WORD && LA77_0<=NAMED_PARAMETER)||(LA77_0>=115 && LA77_0<=116)) ) { - alt77=1; - } - else if ( ((LA77_0>=86 && LA77_0<=88)) ) { - alt77=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 77, 0, input); - - throw nvae; - } - switch (alt77) { - case 1 : - // JPA.g:303:39: entity_expression - { - pushFollow(FOLLOW_entity_expression_in_comparison_expression2548); - entity_expression264=entity_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression264.getTree()); - - } - break; - case 2 : - // JPA.g:303:59: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2552); - all_or_any_expression265=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression265.getTree()); - - } - break; - - } - - - } - break; - case 6 : - // JPA.g:304:7: arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_arithmetic_expression_in_comparison_expression2561); - arithmetic_expression266=arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression266.getTree()); - pushFollow(FOLLOW_comparison_operator_in_comparison_expression2563); - comparison_operator267=comparison_operator(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator267.getTree()); - // JPA.g:304:49: ( arithmetic_expression | all_or_any_expression ) - int alt78=2; - int LA78_0 = input.LA(1); - - if ( ((LA78_0>=AVG && LA78_0<=COUNT)||LA78_0==LPAREN||LA78_0==INT_NUMERAL||(LA78_0>=WORD && LA78_0<=NAMED_PARAMETER)||LA78_0==56||(LA78_0>=65 && LA78_0<=66)||(LA78_0>=97 && LA78_0<=102)||(LA78_0>=114 && LA78_0<=116)) ) { - alt78=1; - } - else if ( ((LA78_0>=86 && LA78_0<=88)) ) { - alt78=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 78, 0, input); - - throw nvae; - } - switch (alt78) { - case 1 : - // JPA.g:304:50: arithmetic_expression - { - pushFollow(FOLLOW_arithmetic_expression_in_comparison_expression2566); - arithmetic_expression268=arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression268.getTree()); - - } - break; - case 2 : - // JPA.g:304:74: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2570); - all_or_any_expression269=all_or_any_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression269.getTree()); - - } - break; - - } - - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "comparison_expression" - - public static class comparison_operator_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "comparison_operator" - // JPA.g:306:1: comparison_operator : ( '=' | '>' | '>=' | '<' | '<=' | '<>' ); - public final JPAParser.comparison_operator_return comparison_operator() throws RecognitionException { - JPAParser.comparison_operator_return retval = new JPAParser.comparison_operator_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set270=null; - - Object set270_tree=null; - - try { - // JPA.g:307:5: ( '=' | '>' | '>=' | '<' | '<=' | '<>' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set270=(Token)input.LT(1); - if ( (input.LA(1)>=89 && input.LA(1)<=94) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set270)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "comparison_operator" - - public static class arithmetic_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "arithmetic_expression" - // JPA.g:314:1: arithmetic_expression : ( simple_arithmetic_expression | subquery ); - public final JPAParser.arithmetic_expression_return arithmetic_expression() throws RecognitionException { - JPAParser.arithmetic_expression_return retval = new JPAParser.arithmetic_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression271 = null; - - JPAParser.subquery_return subquery272 = null; - - - - try { - // JPA.g:315:5: ( simple_arithmetic_expression | subquery ) - int alt80=2; - int LA80_0 = input.LA(1); - - if ( ((LA80_0>=AVG && LA80_0<=COUNT)||LA80_0==LPAREN||LA80_0==INT_NUMERAL||(LA80_0>=WORD && LA80_0<=NAMED_PARAMETER)||(LA80_0>=65 && LA80_0<=66)||(LA80_0>=97 && LA80_0<=102)||(LA80_0>=114 && LA80_0<=116)) ) { - alt80=1; - } - else if ( (LA80_0==56) ) { - alt80=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 80, 0, input); - - throw nvae; - } - switch (alt80) { - case 1 : - // JPA.g:315:7: simple_arithmetic_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_simple_arithmetic_expression_in_arithmetic_expression2635); - simple_arithmetic_expression271=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression271.getTree()); - - } - break; - case 2 : - // JPA.g:316:7: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_arithmetic_expression2643); - subquery272=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery272.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "arithmetic_expression" - - public static class simple_arithmetic_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "simple_arithmetic_expression" - // JPA.g:318:1: simple_arithmetic_expression : ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* ; - public final JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression() throws RecognitionException { - JPAParser.simple_arithmetic_expression_return retval = new JPAParser.simple_arithmetic_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set274=null; - JPAParser.arithmetic_term_return arithmetic_term273 = null; - - JPAParser.arithmetic_term_return arithmetic_term275 = null; - - - Object set274_tree=null; - - try { - // JPA.g:319:5: ( ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* ) - // JPA.g:319:7: ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:319:7: ( arithmetic_term ) - // JPA.g:319:8: arithmetic_term - { - pushFollow(FOLLOW_arithmetic_term_in_simple_arithmetic_expression2656); - arithmetic_term273=arithmetic_term(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_term273.getTree()); - - } - - // JPA.g:319:25: ( ( '+' | '-' ) arithmetic_term )* - loop81: - do { - int alt81=2; - int LA81_0 = input.LA(1); - - if ( ((LA81_0>=65 && LA81_0<=66)) ) { - alt81=1; - } - - - switch (alt81) { - case 1 : - // JPA.g:319:26: ( '+' | '-' ) arithmetic_term - { - set274=(Token)input.LT(1); - if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set274)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - pushFollow(FOLLOW_arithmetic_term_in_simple_arithmetic_expression2670); - arithmetic_term275=arithmetic_term(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_term275.getTree()); - - } - break; - - default : - break loop81; - } - } while (true); - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "simple_arithmetic_expression" - - public static class arithmetic_term_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "arithmetic_term" - // JPA.g:321:1: arithmetic_term : ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* ; - public final JPAParser.arithmetic_term_return arithmetic_term() throws RecognitionException { - JPAParser.arithmetic_term_return retval = new JPAParser.arithmetic_term_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set277=null; - JPAParser.arithmetic_factor_return arithmetic_factor276 = null; - - JPAParser.arithmetic_factor_return arithmetic_factor278 = null; - - - Object set277_tree=null; - - try { - // JPA.g:322:5: ( ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* ) - // JPA.g:322:7: ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:322:7: ( arithmetic_factor ) - // JPA.g:322:8: arithmetic_factor - { - pushFollow(FOLLOW_arithmetic_factor_in_arithmetic_term2685); - arithmetic_factor276=arithmetic_factor(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_factor276.getTree()); - - } - - // JPA.g:322:27: ( ( '*' | '/' ) arithmetic_factor )* - loop82: - do { - int alt82=2; - int LA82_0 = input.LA(1); - - if ( ((LA82_0>=95 && LA82_0<=96)) ) { - alt82=1; - } - - - switch (alt82) { - case 1 : - // JPA.g:322:28: ( '*' | '/' ) arithmetic_factor - { - set277=(Token)input.LT(1); - if ( (input.LA(1)>=95 && input.LA(1)<=96) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set277)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - pushFollow(FOLLOW_arithmetic_factor_in_arithmetic_term2699); - arithmetic_factor278=arithmetic_factor(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_factor278.getTree()); - - } - break; - - default : - break loop82; - } - } while (true); - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "arithmetic_term" - - public static class arithmetic_factor_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "arithmetic_factor" - // JPA.g:324:1: arithmetic_factor : ( '+' | '-' )? arithmetic_primary ; - public final JPAParser.arithmetic_factor_return arithmetic_factor() throws RecognitionException { - JPAParser.arithmetic_factor_return retval = new JPAParser.arithmetic_factor_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set279=null; - JPAParser.arithmetic_primary_return arithmetic_primary280 = null; - - - Object set279_tree=null; - - try { - // JPA.g:325:5: ( ( '+' | '-' )? arithmetic_primary ) - // JPA.g:325:7: ( '+' | '-' )? arithmetic_primary - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:325:7: ( '+' | '-' )? - int alt83=2; - int LA83_0 = input.LA(1); - - if ( ((LA83_0>=65 && LA83_0<=66)) ) { - alt83=1; - } - switch (alt83) { - case 1 : - // JPA.g: - { - set279=(Token)input.LT(1); - if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set279)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - break; - - } - - pushFollow(FOLLOW_arithmetic_primary_in_arithmetic_factor2724); - arithmetic_primary280=arithmetic_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_primary280.getTree()); - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "arithmetic_factor" - - public static class arithmetic_primary_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "arithmetic_primary" - // JPA.g:327:1: arithmetic_primary : ( path_expression | numeric_literal | '(' simple_arithmetic_expression ')' | input_parameter | functions_returning_numerics | aggregate_expression ); - public final JPAParser.arithmetic_primary_return arithmetic_primary() throws RecognitionException { - JPAParser.arithmetic_primary_return retval = new JPAParser.arithmetic_primary_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal283=null; - Token char_literal285=null; - JPAParser.path_expression_return path_expression281 = null; - - JPAParser.numeric_literal_return numeric_literal282 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression284 = null; - - JPAParser.input_parameter_return input_parameter286 = null; - - JPAParser.functions_returning_numerics_return functions_returning_numerics287 = null; - - JPAParser.aggregate_expression_return aggregate_expression288 = null; - - - Object char_literal283_tree=null; - Object char_literal285_tree=null; - - try { - // JPA.g:328:5: ( path_expression | numeric_literal | '(' simple_arithmetic_expression ')' | input_parameter | functions_returning_numerics | aggregate_expression ) - int alt84=6; - switch ( input.LA(1) ) { - case WORD: - { - alt84=1; - } - break; - case INT_NUMERAL: - case 114: - { - alt84=2; - } - break; - case LPAREN: - { - alt84=3; - } - break; - case NAMED_PARAMETER: - case 115: - case 116: - { - alt84=4; - } - break; - case 97: - case 98: - case 99: - case 100: - case 101: - case 102: - { - alt84=5; - } - break; - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - { - alt84=6; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 84, 0, input); - - throw nvae; - } - - switch (alt84) { - case 1 : - // JPA.g:328:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_arithmetic_primary2736); - path_expression281=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression281.getTree()); - - } - break; - case 2 : - // JPA.g:329:7: numeric_literal - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_numeric_literal_in_arithmetic_primary2744); - numeric_literal282=numeric_literal(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, numeric_literal282.getTree()); - - } - break; - case 3 : - // JPA.g:330:7: '(' simple_arithmetic_expression ')' - { - root_0 = (Object)adaptor.nil(); - - char_literal283=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_arithmetic_primary2752); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal283_tree = (Object)adaptor.create(char_literal283); - adaptor.addChild(root_0, char_literal283_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_arithmetic_primary2753); - simple_arithmetic_expression284=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression284.getTree()); - char_literal285=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_arithmetic_primary2754); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal285_tree = (Object)adaptor.create(char_literal285); - adaptor.addChild(root_0, char_literal285_tree); - } - - } - break; - case 4 : - // JPA.g:331:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_arithmetic_primary2762); - input_parameter286=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter286.getTree()); - - } - break; - case 5 : - // JPA.g:332:7: functions_returning_numerics - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_functions_returning_numerics_in_arithmetic_primary2770); - functions_returning_numerics287=functions_returning_numerics(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_numerics287.getTree()); - - } - break; - case 6 : - // JPA.g:333:7: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_arithmetic_primary2778); - aggregate_expression288=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression288.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "arithmetic_primary" - - public static class string_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "string_expression" - // JPA.g:335:1: string_expression : ( string_primary | subquery ); - public final JPAParser.string_expression_return string_expression() throws RecognitionException { - JPAParser.string_expression_return retval = new JPAParser.string_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.string_primary_return string_primary289 = null; - - JPAParser.subquery_return subquery290 = null; - - - - try { - // JPA.g:336:5: ( string_primary | subquery ) - int alt85=2; - int LA85_0 = input.LA(1); - - if ( ((LA85_0>=AVG && LA85_0<=COUNT)||LA85_0==STRINGLITERAL||(LA85_0>=WORD && LA85_0<=NAMED_PARAMETER)||(LA85_0>=106 && LA85_0<=110)||(LA85_0>=115 && LA85_0<=116)) ) { - alt85=1; - } - else if ( (LA85_0==56) ) { - alt85=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 85, 0, input); - - throw nvae; - } - switch (alt85) { - case 1 : - // JPA.g:336:7: string_primary - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_string_primary_in_string_expression2790); - string_primary289=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary289.getTree()); - - } - break; - case 2 : - // JPA.g:336:24: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_string_expression2794); - subquery290=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery290.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "string_expression" - - public static class string_primary_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "string_primary" - // JPA.g:338:1: string_primary : ( path_expression | STRINGLITERAL | input_parameter | functions_returning_strings | aggregate_expression ); - public final JPAParser.string_primary_return string_primary() throws RecognitionException { - JPAParser.string_primary_return retval = new JPAParser.string_primary_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token STRINGLITERAL292=null; - JPAParser.path_expression_return path_expression291 = null; - - JPAParser.input_parameter_return input_parameter293 = null; - - JPAParser.functions_returning_strings_return functions_returning_strings294 = null; - - JPAParser.aggregate_expression_return aggregate_expression295 = null; - - - Object STRINGLITERAL292_tree=null; - - try { - // JPA.g:339:5: ( path_expression | STRINGLITERAL | input_parameter | functions_returning_strings | aggregate_expression ) - int alt86=5; - switch ( input.LA(1) ) { - case WORD: - { - alt86=1; - } - break; - case STRINGLITERAL: - { - alt86=2; - } - break; - case NAMED_PARAMETER: - case 115: - case 116: - { - alt86=3; - } - break; - case 106: - case 107: - case 108: - case 109: - case 110: - { - alt86=4; - } - break; - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - { - alt86=5; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 86, 0, input); - - throw nvae; - } - - switch (alt86) { - case 1 : - // JPA.g:339:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_string_primary2806); - path_expression291=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression291.getTree()); - - } - break; - case 2 : - // JPA.g:340:7: STRINGLITERAL - { - root_0 = (Object)adaptor.nil(); - - STRINGLITERAL292=(Token)match(input,STRINGLITERAL,FOLLOW_STRINGLITERAL_in_string_primary2814); if (state.failed) return retval; - if ( state.backtracking==0 ) { - STRINGLITERAL292_tree = (Object)adaptor.create(STRINGLITERAL292); - adaptor.addChild(root_0, STRINGLITERAL292_tree); - } - - } - break; - case 3 : - // JPA.g:341:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_string_primary2822); - input_parameter293=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter293.getTree()); - - } - break; - case 4 : - // JPA.g:342:7: functions_returning_strings - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_functions_returning_strings_in_string_primary2830); - functions_returning_strings294=functions_returning_strings(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_strings294.getTree()); - - } - break; - case 5 : - // JPA.g:343:7: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_string_primary2838); - aggregate_expression295=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression295.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "string_primary" - - public static class datetime_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "datetime_expression" - // JPA.g:345:1: datetime_expression : ( datetime_primary | subquery ); - public final JPAParser.datetime_expression_return datetime_expression() throws RecognitionException { - JPAParser.datetime_expression_return retval = new JPAParser.datetime_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.datetime_primary_return datetime_primary296 = null; - - JPAParser.subquery_return subquery297 = null; - - - - try { - // JPA.g:346:5: ( datetime_primary | subquery ) - int alt87=2; - int LA87_0 = input.LA(1); - - if ( ((LA87_0>=AVG && LA87_0<=COUNT)||(LA87_0>=WORD && LA87_0<=NAMED_PARAMETER)||(LA87_0>=103 && LA87_0<=105)||(LA87_0>=115 && LA87_0<=116)) ) { - alt87=1; - } - else if ( (LA87_0==56) ) { - alt87=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 87, 0, input); - - throw nvae; - } - switch (alt87) { - case 1 : - // JPA.g:346:7: datetime_primary - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_datetime_primary_in_datetime_expression2850); - datetime_primary296=datetime_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_primary296.getTree()); - - } - break; - case 2 : - // JPA.g:347:7: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_datetime_expression2858); - subquery297=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery297.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "datetime_expression" - - public static class datetime_primary_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "datetime_primary" - // JPA.g:349:1: datetime_primary : ( path_expression | input_parameter | functions_returning_datetime | aggregate_expression ); - public final JPAParser.datetime_primary_return datetime_primary() throws RecognitionException { - JPAParser.datetime_primary_return retval = new JPAParser.datetime_primary_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression298 = null; - - JPAParser.input_parameter_return input_parameter299 = null; - - JPAParser.functions_returning_datetime_return functions_returning_datetime300 = null; - - JPAParser.aggregate_expression_return aggregate_expression301 = null; - - - - try { - // JPA.g:350:5: ( path_expression | input_parameter | functions_returning_datetime | aggregate_expression ) - int alt88=4; - switch ( input.LA(1) ) { - case WORD: - { - alt88=1; - } - break; - case NAMED_PARAMETER: - case 115: - case 116: - { - alt88=2; - } - break; - case 103: - case 104: - case 105: - { - alt88=3; - } - break; - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - { - alt88=4; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 88, 0, input); - - throw nvae; - } - - switch (alt88) { - case 1 : - // JPA.g:350:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_datetime_primary2870); - path_expression298=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression298.getTree()); - - } - break; - case 2 : - // JPA.g:351:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_datetime_primary2878); - input_parameter299=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter299.getTree()); - - } - break; - case 3 : - // JPA.g:352:7: functions_returning_datetime - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_functions_returning_datetime_in_datetime_primary2886); - functions_returning_datetime300=functions_returning_datetime(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_datetime300.getTree()); - - } - break; - case 4 : - // JPA.g:353:7: aggregate_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_aggregate_expression_in_datetime_primary2894); - aggregate_expression301=aggregate_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression301.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "datetime_primary" - - public static class boolean_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "boolean_expression" - // JPA.g:355:1: boolean_expression : ( boolean_primary | subquery ); - public final JPAParser.boolean_expression_return boolean_expression() throws RecognitionException { - JPAParser.boolean_expression_return retval = new JPAParser.boolean_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.boolean_primary_return boolean_primary302 = null; - - JPAParser.subquery_return subquery303 = null; - - - - try { - // JPA.g:356:5: ( boolean_primary | subquery ) - int alt89=2; - int LA89_0 = input.LA(1); - - if ( ((LA89_0>=WORD && LA89_0<=NAMED_PARAMETER)||(LA89_0>=115 && LA89_0<=116)||(LA89_0>=118 && LA89_0<=119)) ) { - alt89=1; - } - else if ( (LA89_0==56) ) { - alt89=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 89, 0, input); - - throw nvae; - } - switch (alt89) { - case 1 : - // JPA.g:356:7: boolean_primary - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_boolean_primary_in_boolean_expression2906); - boolean_primary302=boolean_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_primary302.getTree()); - - } - break; - case 2 : - // JPA.g:357:7: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_boolean_expression2914); - subquery303=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery303.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "boolean_expression" - - public static class boolean_primary_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "boolean_primary" - // JPA.g:359:1: boolean_primary : ( path_expression | boolean_literal | input_parameter ); - public final JPAParser.boolean_primary_return boolean_primary() throws RecognitionException { - JPAParser.boolean_primary_return retval = new JPAParser.boolean_primary_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression304 = null; - - JPAParser.boolean_literal_return boolean_literal305 = null; - - JPAParser.input_parameter_return input_parameter306 = null; - - - - try { - // JPA.g:360:5: ( path_expression | boolean_literal | input_parameter ) - int alt90=3; - switch ( input.LA(1) ) { - case WORD: - { - alt90=1; - } - break; - case 118: - case 119: - { - alt90=2; - } - break; - case NAMED_PARAMETER: - case 115: - case 116: - { - alt90=3; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 90, 0, input); - - throw nvae; - } - - switch (alt90) { - case 1 : - // JPA.g:360:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_boolean_primary2926); - path_expression304=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression304.getTree()); - - } - break; - case 2 : - // JPA.g:361:7: boolean_literal - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_boolean_literal_in_boolean_primary2934); - boolean_literal305=boolean_literal(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_literal305.getTree()); - - } - break; - case 3 : - // JPA.g:362:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_boolean_primary2942); - input_parameter306=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter306.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "boolean_primary" - - public static class enum_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "enum_expression" - // JPA.g:364:1: enum_expression : ( enum_primary | subquery ); - public final JPAParser.enum_expression_return enum_expression() throws RecognitionException { - JPAParser.enum_expression_return retval = new JPAParser.enum_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.enum_primary_return enum_primary307 = null; - - JPAParser.subquery_return subquery308 = null; - - - - try { - // JPA.g:365:5: ( enum_primary | subquery ) - int alt91=2; - int LA91_0 = input.LA(1); - - if ( ((LA91_0>=WORD && LA91_0<=NAMED_PARAMETER)||(LA91_0>=115 && LA91_0<=116)) ) { - alt91=1; - } - else if ( (LA91_0==56) ) { - alt91=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 91, 0, input); - - throw nvae; - } - switch (alt91) { - case 1 : - // JPA.g:365:7: enum_primary - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_enum_primary_in_enum_expression2954); - enum_primary307=enum_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_primary307.getTree()); - - } - break; - case 2 : - // JPA.g:366:7: subquery - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_subquery_in_enum_expression2962); - subquery308=subquery(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery308.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "enum_expression" - - public static class enum_primary_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "enum_primary" - // JPA.g:368:1: enum_primary : ( path_expression | enum_literal | input_parameter ); - public final JPAParser.enum_primary_return enum_primary() throws RecognitionException { - JPAParser.enum_primary_return retval = new JPAParser.enum_primary_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression309 = null; - - JPAParser.enum_literal_return enum_literal310 = null; - - JPAParser.input_parameter_return input_parameter311 = null; - - - - try { - // JPA.g:369:5: ( path_expression | enum_literal | input_parameter ) - int alt92=3; - int LA92_0 = input.LA(1); - - if ( (LA92_0==WORD) ) { - int LA92_1 = input.LA(2); - - if ( (LA92_1==57) ) { - alt92=1; - } - else if ( (LA92_1==EOF||LA92_1==HAVING||(LA92_1>=OR && LA92_1<=AND)||LA92_1==RPAREN||(LA92_1>=ORDER && LA92_1<=GROUP)||(LA92_1>=89 && LA92_1<=90)) ) { - alt92=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 92, 1, input); - - throw nvae; - } - } - else if ( (LA92_0==NAMED_PARAMETER||(LA92_0>=115 && LA92_0<=116)) ) { - alt92=3; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 92, 0, input); - - throw nvae; - } - switch (alt92) { - case 1 : - // JPA.g:369:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_enum_primary2974); - path_expression309=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression309.getTree()); - - } - break; - case 2 : - // JPA.g:370:7: enum_literal - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_enum_literal_in_enum_primary2982); - enum_literal310=enum_literal(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_literal310.getTree()); - - } - break; - case 3 : - // JPA.g:371:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_enum_primary2990); - input_parameter311=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter311.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "enum_primary" - - public static class entity_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "entity_expression" - // JPA.g:373:1: entity_expression : ( path_expression | simple_entity_expression ); - public final JPAParser.entity_expression_return entity_expression() throws RecognitionException { - JPAParser.entity_expression_return retval = new JPAParser.entity_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.path_expression_return path_expression312 = null; - - JPAParser.simple_entity_expression_return simple_entity_expression313 = null; - - - - try { - // JPA.g:374:5: ( path_expression | simple_entity_expression ) - int alt93=2; - int LA93_0 = input.LA(1); - - if ( (LA93_0==WORD) ) { - int LA93_1 = input.LA(2); - - if ( (LA93_1==57) ) { - alt93=1; - } - else if ( (LA93_1==EOF||LA93_1==HAVING||(LA93_1>=OR && LA93_1<=AND)||LA93_1==RPAREN||(LA93_1>=ORDER && LA93_1<=GROUP)||LA93_1==62||LA93_1==83||(LA93_1>=89 && LA93_1<=90)) ) { - alt93=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 93, 1, input); - - throw nvae; - } - } - else if ( (LA93_0==NAMED_PARAMETER||(LA93_0>=115 && LA93_0<=116)) ) { - alt93=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 93, 0, input); - - throw nvae; - } - switch (alt93) { - case 1 : - // JPA.g:374:7: path_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_path_expression_in_entity_expression3002); - path_expression312=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression312.getTree()); - - } - break; - case 2 : - // JPA.g:375:7: simple_entity_expression - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_simple_entity_expression_in_entity_expression3010); - simple_entity_expression313=simple_entity_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_entity_expression313.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "entity_expression" - - public static class simple_entity_expression_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "simple_entity_expression" - // JPA.g:377:1: simple_entity_expression : ( identification_variable | input_parameter ); - public final JPAParser.simple_entity_expression_return simple_entity_expression() throws RecognitionException { - JPAParser.simple_entity_expression_return retval = new JPAParser.simple_entity_expression_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - JPAParser.identification_variable_return identification_variable314 = null; - - JPAParser.input_parameter_return input_parameter315 = null; - - - - try { - // JPA.g:378:5: ( identification_variable | input_parameter ) - int alt94=2; - int LA94_0 = input.LA(1); - - if ( (LA94_0==WORD) ) { - alt94=1; - } - else if ( (LA94_0==NAMED_PARAMETER||(LA94_0>=115 && LA94_0<=116)) ) { - alt94=2; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 94, 0, input); - - throw nvae; - } - switch (alt94) { - case 1 : - // JPA.g:378:7: identification_variable - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_identification_variable_in_simple_entity_expression3022); - identification_variable314=identification_variable(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable314.getTree()); - - } - break; - case 2 : - // JPA.g:379:7: input_parameter - { - root_0 = (Object)adaptor.nil(); - - pushFollow(FOLLOW_input_parameter_in_simple_entity_expression3030); - input_parameter315=input_parameter(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter315.getTree()); - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "simple_entity_expression" - - public static class functions_returning_numerics_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "functions_returning_numerics" - // JPA.g:381:1: functions_returning_numerics : ( 'LENGTH' '(' string_primary ')' | 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' | 'ABS' '(' simple_arithmetic_expression ')' | 'SQRT' '(' simple_arithmetic_expression ')' | 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'SIZE' '(' path_expression ')' ); - public final JPAParser.functions_returning_numerics_return functions_returning_numerics() throws RecognitionException { - JPAParser.functions_returning_numerics_return retval = new JPAParser.functions_returning_numerics_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal316=null; - Token char_literal317=null; - Token char_literal319=null; - Token string_literal320=null; - Token char_literal321=null; - Token char_literal323=null; - Token char_literal325=null; - Token char_literal327=null; - Token string_literal328=null; - Token char_literal329=null; - Token char_literal331=null; - Token string_literal332=null; - Token char_literal333=null; - Token char_literal335=null; - Token string_literal336=null; - Token char_literal337=null; - Token char_literal339=null; - Token char_literal341=null; - Token string_literal342=null; - Token char_literal343=null; - Token char_literal345=null; - JPAParser.string_primary_return string_primary318 = null; - - JPAParser.string_primary_return string_primary322 = null; - - JPAParser.string_primary_return string_primary324 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression326 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression330 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression334 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression338 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression340 = null; - - JPAParser.path_expression_return path_expression344 = null; - - - Object string_literal316_tree=null; - Object char_literal317_tree=null; - Object char_literal319_tree=null; - Object string_literal320_tree=null; - Object char_literal321_tree=null; - Object char_literal323_tree=null; - Object char_literal325_tree=null; - Object char_literal327_tree=null; - Object string_literal328_tree=null; - Object char_literal329_tree=null; - Object char_literal331_tree=null; - Object string_literal332_tree=null; - Object char_literal333_tree=null; - Object char_literal335_tree=null; - Object string_literal336_tree=null; - Object char_literal337_tree=null; - Object char_literal339_tree=null; - Object char_literal341_tree=null; - Object string_literal342_tree=null; - Object char_literal343_tree=null; - Object char_literal345_tree=null; - - try { - // JPA.g:382:5: ( 'LENGTH' '(' string_primary ')' | 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' | 'ABS' '(' simple_arithmetic_expression ')' | 'SQRT' '(' simple_arithmetic_expression ')' | 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'SIZE' '(' path_expression ')' ) - int alt96=6; - switch ( input.LA(1) ) { - case 97: - { - alt96=1; - } - break; - case 98: - { - alt96=2; - } - break; - case 99: - { - alt96=3; - } - break; - case 100: - { - alt96=4; - } - break; - case 101: - { - alt96=5; - } - break; - case 102: - { - alt96=6; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 96, 0, input); - - throw nvae; - } - - switch (alt96) { - case 1 : - // JPA.g:382:7: 'LENGTH' '(' string_primary ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal316=(Token)match(input,97,FOLLOW_97_in_functions_returning_numerics3042); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal316_tree = (Object)adaptor.create(string_literal316); - adaptor.addChild(root_0, string_literal316_tree); - } - char_literal317=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3044); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal317_tree = (Object)adaptor.create(char_literal317); - adaptor.addChild(root_0, char_literal317_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3045); - string_primary318=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary318.getTree()); - char_literal319=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3046); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal319_tree = (Object)adaptor.create(char_literal319); - adaptor.addChild(root_0, char_literal319_tree); - } - - } - break; - case 2 : - // JPA.g:383:7: 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal320=(Token)match(input,98,FOLLOW_98_in_functions_returning_numerics3054); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal320_tree = (Object)adaptor.create(string_literal320); - adaptor.addChild(root_0, string_literal320_tree); - } - char_literal321=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3056); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal321_tree = (Object)adaptor.create(char_literal321); - adaptor.addChild(root_0, char_literal321_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3057); - string_primary322=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary322.getTree()); - char_literal323=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3058); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal323_tree = (Object)adaptor.create(char_literal323); - adaptor.addChild(root_0, char_literal323_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3060); - string_primary324=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary324.getTree()); - // JPA.g:383:51: ( ',' simple_arithmetic_expression )? - int alt95=2; - int LA95_0 = input.LA(1); - - if ( (LA95_0==54) ) { - alt95=1; - } - switch (alt95) { - case 1 : - // JPA.g:383:52: ',' simple_arithmetic_expression - { - char_literal325=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3062); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal325_tree = (Object)adaptor.create(char_literal325); - adaptor.addChild(root_0, char_literal325_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3064); - simple_arithmetic_expression326=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression326.getTree()); - - } - break; - - } - - char_literal327=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3067); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal327_tree = (Object)adaptor.create(char_literal327); - adaptor.addChild(root_0, char_literal327_tree); - } - - } - break; - case 3 : - // JPA.g:384:7: 'ABS' '(' simple_arithmetic_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal328=(Token)match(input,99,FOLLOW_99_in_functions_returning_numerics3075); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal328_tree = (Object)adaptor.create(string_literal328); - adaptor.addChild(root_0, string_literal328_tree); - } - char_literal329=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3077); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal329_tree = (Object)adaptor.create(char_literal329); - adaptor.addChild(root_0, char_literal329_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3078); - simple_arithmetic_expression330=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression330.getTree()); - char_literal331=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3079); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal331_tree = (Object)adaptor.create(char_literal331); - adaptor.addChild(root_0, char_literal331_tree); - } - - } - break; - case 4 : - // JPA.g:385:7: 'SQRT' '(' simple_arithmetic_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal332=(Token)match(input,100,FOLLOW_100_in_functions_returning_numerics3087); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal332_tree = (Object)adaptor.create(string_literal332); - adaptor.addChild(root_0, string_literal332_tree); - } - char_literal333=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3089); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal333_tree = (Object)adaptor.create(char_literal333); - adaptor.addChild(root_0, char_literal333_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3090); - simple_arithmetic_expression334=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression334.getTree()); - char_literal335=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3091); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal335_tree = (Object)adaptor.create(char_literal335); - adaptor.addChild(root_0, char_literal335_tree); - } - - } - break; - case 5 : - // JPA.g:386:7: 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal336=(Token)match(input,101,FOLLOW_101_in_functions_returning_numerics3099); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal336_tree = (Object)adaptor.create(string_literal336); - adaptor.addChild(root_0, string_literal336_tree); - } - char_literal337=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3101); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal337_tree = (Object)adaptor.create(char_literal337); - adaptor.addChild(root_0, char_literal337_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3102); - simple_arithmetic_expression338=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression338.getTree()); - char_literal339=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3103); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal339_tree = (Object)adaptor.create(char_literal339); - adaptor.addChild(root_0, char_literal339_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3105); - simple_arithmetic_expression340=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression340.getTree()); - char_literal341=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3106); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal341_tree = (Object)adaptor.create(char_literal341); - adaptor.addChild(root_0, char_literal341_tree); - } - - } - break; - case 6 : - // JPA.g:387:7: 'SIZE' '(' path_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal342=(Token)match(input,102,FOLLOW_102_in_functions_returning_numerics3114); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal342_tree = (Object)adaptor.create(string_literal342); - adaptor.addChild(root_0, string_literal342_tree); - } - char_literal343=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3116); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal343_tree = (Object)adaptor.create(char_literal343); - adaptor.addChild(root_0, char_literal343_tree); - } - pushFollow(FOLLOW_path_expression_in_functions_returning_numerics3117); - path_expression344=path_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression344.getTree()); - char_literal345=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3118); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal345_tree = (Object)adaptor.create(char_literal345); - adaptor.addChild(root_0, char_literal345_tree); - } - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "functions_returning_numerics" - - public static class functions_returning_datetime_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "functions_returning_datetime" - // JPA.g:389:1: functions_returning_datetime : ( 'CURRENT_DATE' | 'CURRENT_TIME' | 'CURRENT_TIMESTAMP' ); - public final JPAParser.functions_returning_datetime_return functions_returning_datetime() throws RecognitionException { - JPAParser.functions_returning_datetime_return retval = new JPAParser.functions_returning_datetime_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set346=null; - - Object set346_tree=null; - - try { - // JPA.g:390:5: ( 'CURRENT_DATE' | 'CURRENT_TIME' | 'CURRENT_TIMESTAMP' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set346=(Token)input.LT(1); - if ( (input.LA(1)>=103 && input.LA(1)<=105) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set346)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "functions_returning_datetime" - - public static class functions_returning_strings_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "functions_returning_strings" - // JPA.g:394:1: functions_returning_strings : ( 'CONCAT' '(' string_primary ',' string_primary ')' | 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' | 'LOWER' '(' string_primary ')' | 'UPPER' '(' string_primary ')' ); - public final JPAParser.functions_returning_strings_return functions_returning_strings() throws RecognitionException { - JPAParser.functions_returning_strings_return retval = new JPAParser.functions_returning_strings_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal347=null; - Token char_literal348=null; - Token char_literal350=null; - Token char_literal352=null; - Token string_literal353=null; - Token char_literal354=null; - Token char_literal356=null; - Token char_literal358=null; - Token char_literal360=null; - Token string_literal361=null; - Token char_literal362=null; - Token TRIM_CHARACTER364=null; - Token string_literal365=null; - Token char_literal367=null; - Token string_literal368=null; - Token char_literal369=null; - Token char_literal371=null; - Token string_literal372=null; - Token char_literal373=null; - Token char_literal375=null; - JPAParser.string_primary_return string_primary349 = null; - - JPAParser.string_primary_return string_primary351 = null; - - JPAParser.string_primary_return string_primary355 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression357 = null; - - JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression359 = null; - - JPAParser.trim_specification_return trim_specification363 = null; - - JPAParser.string_primary_return string_primary366 = null; - - JPAParser.string_primary_return string_primary370 = null; - - JPAParser.string_primary_return string_primary374 = null; - - - Object string_literal347_tree=null; - Object char_literal348_tree=null; - Object char_literal350_tree=null; - Object char_literal352_tree=null; - Object string_literal353_tree=null; - Object char_literal354_tree=null; - Object char_literal356_tree=null; - Object char_literal358_tree=null; - Object char_literal360_tree=null; - Object string_literal361_tree=null; - Object char_literal362_tree=null; - Object TRIM_CHARACTER364_tree=null; - Object string_literal365_tree=null; - Object char_literal367_tree=null; - Object string_literal368_tree=null; - Object char_literal369_tree=null; - Object char_literal371_tree=null; - Object string_literal372_tree=null; - Object char_literal373_tree=null; - Object char_literal375_tree=null; - - try { - // JPA.g:395:5: ( 'CONCAT' '(' string_primary ',' string_primary ')' | 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' | 'LOWER' '(' string_primary ')' | 'UPPER' '(' string_primary ')' ) - int alt100=5; - switch ( input.LA(1) ) { - case 106: - { - alt100=1; - } - break; - case 107: - { - alt100=2; - } - break; - case 108: - { - alt100=3; - } - break; - case 109: - { - alt100=4; - } - break; - case 110: - { - alt100=5; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 100, 0, input); - - throw nvae; - } - - switch (alt100) { - case 1 : - // JPA.g:395:7: 'CONCAT' '(' string_primary ',' string_primary ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal347=(Token)match(input,106,FOLLOW_106_in_functions_returning_strings3158); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal347_tree = (Object)adaptor.create(string_literal347); - adaptor.addChild(root_0, string_literal347_tree); - } - char_literal348=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3160); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal348_tree = (Object)adaptor.create(char_literal348); - adaptor.addChild(root_0, char_literal348_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3161); - string_primary349=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary349.getTree()); - char_literal350=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3162); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal350_tree = (Object)adaptor.create(char_literal350); - adaptor.addChild(root_0, char_literal350_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3164); - string_primary351=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary351.getTree()); - char_literal352=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3165); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal352_tree = (Object)adaptor.create(char_literal352); - adaptor.addChild(root_0, char_literal352_tree); - } - - } - break; - case 2 : - // JPA.g:396:7: 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal353=(Token)match(input,107,FOLLOW_107_in_functions_returning_strings3173); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal353_tree = (Object)adaptor.create(string_literal353); - adaptor.addChild(root_0, string_literal353_tree); - } - char_literal354=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3175); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal354_tree = (Object)adaptor.create(char_literal354); - adaptor.addChild(root_0, char_literal354_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3176); - string_primary355=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary355.getTree()); - char_literal356=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3177); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal356_tree = (Object)adaptor.create(char_literal356); - adaptor.addChild(root_0, char_literal356_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3178); - simple_arithmetic_expression357=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression357.getTree()); - char_literal358=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3179); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal358_tree = (Object)adaptor.create(char_literal358); - adaptor.addChild(root_0, char_literal358_tree); - } - pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3181); - simple_arithmetic_expression359=simple_arithmetic_expression(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression359.getTree()); - char_literal360=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3182); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal360_tree = (Object)adaptor.create(char_literal360); - adaptor.addChild(root_0, char_literal360_tree); - } - - } - break; - case 3 : - // JPA.g:397:7: 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal361=(Token)match(input,108,FOLLOW_108_in_functions_returning_strings3190); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal361_tree = (Object)adaptor.create(string_literal361); - adaptor.addChild(root_0, string_literal361_tree); - } - char_literal362=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3192); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal362_tree = (Object)adaptor.create(char_literal362); - adaptor.addChild(root_0, char_literal362_tree); - } - // JPA.g:397:17: ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? - int alt99=2; - int LA99_0 = input.LA(1); - - if ( (LA99_0==TRIM_CHARACTER||LA99_0==53||(LA99_0>=111 && LA99_0<=113)) ) { - alt99=1; - } - switch (alt99) { - case 1 : - // JPA.g:397:18: ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' - { - // JPA.g:397:18: ( trim_specification )? - int alt97=2; - int LA97_0 = input.LA(1); - - if ( ((LA97_0>=111 && LA97_0<=113)) ) { - alt97=1; - } - switch (alt97) { - case 1 : - // JPA.g:397:19: trim_specification - { - pushFollow(FOLLOW_trim_specification_in_functions_returning_strings3195); - trim_specification363=trim_specification(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, trim_specification363.getTree()); - - } - break; - - } - - // JPA.g:397:40: ( TRIM_CHARACTER )? - int alt98=2; - int LA98_0 = input.LA(1); - - if ( (LA98_0==TRIM_CHARACTER) ) { - alt98=1; - } - switch (alt98) { - case 1 : - // JPA.g:397:41: TRIM_CHARACTER - { - TRIM_CHARACTER364=(Token)match(input,TRIM_CHARACTER,FOLLOW_TRIM_CHARACTER_in_functions_returning_strings3200); if (state.failed) return retval; - if ( state.backtracking==0 ) { - TRIM_CHARACTER364_tree = (Object)adaptor.create(TRIM_CHARACTER364); - adaptor.addChild(root_0, TRIM_CHARACTER364_tree); - } - - } - break; - - } - - string_literal365=(Token)match(input,53,FOLLOW_53_in_functions_returning_strings3204); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal365_tree = (Object)adaptor.create(string_literal365); - adaptor.addChild(root_0, string_literal365_tree); - } - - } - break; - - } - - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3208); - string_primary366=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary366.getTree()); - char_literal367=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3209); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal367_tree = (Object)adaptor.create(char_literal367); - adaptor.addChild(root_0, char_literal367_tree); - } - - } - break; - case 4 : - // JPA.g:398:7: 'LOWER' '(' string_primary ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal368=(Token)match(input,109,FOLLOW_109_in_functions_returning_strings3217); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal368_tree = (Object)adaptor.create(string_literal368); - adaptor.addChild(root_0, string_literal368_tree); - } - char_literal369=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3219); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal369_tree = (Object)adaptor.create(char_literal369); - adaptor.addChild(root_0, char_literal369_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3220); - string_primary370=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary370.getTree()); - char_literal371=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3221); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal371_tree = (Object)adaptor.create(char_literal371); - adaptor.addChild(root_0, char_literal371_tree); - } - - } - break; - case 5 : - // JPA.g:399:7: 'UPPER' '(' string_primary ')' - { - root_0 = (Object)adaptor.nil(); - - string_literal372=(Token)match(input,110,FOLLOW_110_in_functions_returning_strings3229); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal372_tree = (Object)adaptor.create(string_literal372); - adaptor.addChild(root_0, string_literal372_tree); - } - char_literal373=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3231); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal373_tree = (Object)adaptor.create(char_literal373); - adaptor.addChild(root_0, char_literal373_tree); - } - pushFollow(FOLLOW_string_primary_in_functions_returning_strings3232); - string_primary374=string_primary(); - - state._fsp--; - if (state.failed) return retval; - if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary374.getTree()); - char_literal375=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3233); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal375_tree = (Object)adaptor.create(char_literal375); - adaptor.addChild(root_0, char_literal375_tree); - } - - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "functions_returning_strings" - - public static class trim_specification_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "trim_specification" - // JPA.g:401:1: trim_specification : ( 'LEADING' | 'TRAILING' | 'BOTH' ); - public final JPAParser.trim_specification_return trim_specification() throws RecognitionException { - JPAParser.trim_specification_return retval = new JPAParser.trim_specification_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set376=null; - - Object set376_tree=null; - - try { - // JPA.g:402:5: ( 'LEADING' | 'TRAILING' | 'BOTH' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set376=(Token)input.LT(1); - if ( (input.LA(1)>=111 && input.LA(1)<=113) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set376)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "trim_specification" - - public static class abstract_schema_name_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "abstract_schema_name" - // JPA.g:407:1: abstract_schema_name : WORD ; - public final JPAParser.abstract_schema_name_return abstract_schema_name() throws RecognitionException { - JPAParser.abstract_schema_name_return retval = new JPAParser.abstract_schema_name_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD377=null; - - Object WORD377_tree=null; - - try { - // JPA.g:408:5: ( WORD ) - // JPA.g:408:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD377=(Token)match(input,WORD,FOLLOW_WORD_in_abstract_schema_name3274); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD377_tree = (Object)adaptor.create(WORD377); - adaptor.addChild(root_0, WORD377_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "abstract_schema_name" - - public static class pattern_value_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "pattern_value" - // JPA.g:411:1: pattern_value : WORD ; - public final JPAParser.pattern_value_return pattern_value() throws RecognitionException { - JPAParser.pattern_value_return retval = new JPAParser.pattern_value_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD378=null; - - Object WORD378_tree=null; - - try { - // JPA.g:412:5: ( WORD ) - // JPA.g:412:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD378=(Token)match(input,WORD,FOLLOW_WORD_in_pattern_value3287); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD378_tree = (Object)adaptor.create(WORD378); - adaptor.addChild(root_0, WORD378_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "pattern_value" - - public static class numeric_literal_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "numeric_literal" - // JPA.g:415:1: numeric_literal : ( '0x' )? INT_NUMERAL ; - public final JPAParser.numeric_literal_return numeric_literal() throws RecognitionException { - JPAParser.numeric_literal_return retval = new JPAParser.numeric_literal_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token string_literal379=null; - Token INT_NUMERAL380=null; - - Object string_literal379_tree=null; - Object INT_NUMERAL380_tree=null; - - try { - // JPA.g:416:5: ( ( '0x' )? INT_NUMERAL ) - // JPA.g:416:7: ( '0x' )? INT_NUMERAL - { - root_0 = (Object)adaptor.nil(); - - // JPA.g:416:7: ( '0x' )? - int alt101=2; - int LA101_0 = input.LA(1); - - if ( (LA101_0==114) ) { - alt101=1; - } - switch (alt101) { - case 1 : - // JPA.g:416:8: '0x' - { - string_literal379=(Token)match(input,114,FOLLOW_114_in_numeric_literal3301); if (state.failed) return retval; - if ( state.backtracking==0 ) { - string_literal379_tree = (Object)adaptor.create(string_literal379); - adaptor.addChild(root_0, string_literal379_tree); - } - - } - break; - - } - - INT_NUMERAL380=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_numeric_literal3305); if (state.failed) return retval; - if ( state.backtracking==0 ) { - INT_NUMERAL380_tree = (Object)adaptor.create(INT_NUMERAL380); - adaptor.addChild(root_0, INT_NUMERAL380_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "numeric_literal" - - public static class input_parameter_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "input_parameter" - // JPA.g:418:1: input_parameter : ( '?' INT_NUMERAL -> ^( T_PARAMETER[] '?' INT_NUMERAL ) | NAMED_PARAMETER -> ^( T_PARAMETER[] NAMED_PARAMETER ) | '${' WORD '}' -> ^( T_PARAMETER[] '${' WORD '}' ) ); - public final JPAParser.input_parameter_return input_parameter() throws RecognitionException { - JPAParser.input_parameter_return retval = new JPAParser.input_parameter_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token char_literal381=null; - Token INT_NUMERAL382=null; - Token NAMED_PARAMETER383=null; - Token string_literal384=null; - Token WORD385=null; - Token char_literal386=null; - - Object char_literal381_tree=null; - Object INT_NUMERAL382_tree=null; - Object NAMED_PARAMETER383_tree=null; - Object string_literal384_tree=null; - Object WORD385_tree=null; - Object char_literal386_tree=null; - RewriteRuleTokenStream stream_116=new RewriteRuleTokenStream(adaptor,"token 116"); - RewriteRuleTokenStream stream_WORD=new RewriteRuleTokenStream(adaptor,"token WORD"); - RewriteRuleTokenStream stream_117=new RewriteRuleTokenStream(adaptor,"token 117"); - RewriteRuleTokenStream stream_115=new RewriteRuleTokenStream(adaptor,"token 115"); - RewriteRuleTokenStream stream_NAMED_PARAMETER=new RewriteRuleTokenStream(adaptor,"token NAMED_PARAMETER"); - RewriteRuleTokenStream stream_INT_NUMERAL=new RewriteRuleTokenStream(adaptor,"token INT_NUMERAL"); - - try { - // JPA.g:419:5: ( '?' INT_NUMERAL -> ^( T_PARAMETER[] '?' INT_NUMERAL ) | NAMED_PARAMETER -> ^( T_PARAMETER[] NAMED_PARAMETER ) | '${' WORD '}' -> ^( T_PARAMETER[] '${' WORD '}' ) ) - int alt102=3; - switch ( input.LA(1) ) { - case 115: - { - alt102=1; - } - break; - case NAMED_PARAMETER: - { - alt102=2; - } - break; - case 116: - { - alt102=3; - } - break; - default: - if (state.backtracking>0) {state.failed=true; return retval;} - NoViableAltException nvae = - new NoViableAltException("", 102, 0, input); - - throw nvae; - } - - switch (alt102) { - case 1 : - // JPA.g:419:7: '?' INT_NUMERAL - { - char_literal381=(Token)match(input,115,FOLLOW_115_in_input_parameter3318); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_115.add(char_literal381); - - INT_NUMERAL382=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_input_parameter3320); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_INT_NUMERAL.add(INT_NUMERAL382); - - - - // AST REWRITE - // elements: 115, INT_NUMERAL - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 419:23: -> ^( T_PARAMETER[] '?' INT_NUMERAL ) - { - // JPA.g:419:26: ^( T_PARAMETER[] '?' INT_NUMERAL ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); - - adaptor.addChild(root_1, stream_115.nextNode()); - adaptor.addChild(root_1, stream_INT_NUMERAL.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 2 : - // JPA.g:420:7: NAMED_PARAMETER - { - NAMED_PARAMETER383=(Token)match(input,NAMED_PARAMETER,FOLLOW_NAMED_PARAMETER_in_input_parameter3343); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_NAMED_PARAMETER.add(NAMED_PARAMETER383); - - - - // AST REWRITE - // elements: NAMED_PARAMETER - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 420:23: -> ^( T_PARAMETER[] NAMED_PARAMETER ) - { - // JPA.g:420:26: ^( T_PARAMETER[] NAMED_PARAMETER ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); - - adaptor.addChild(root_1, stream_NAMED_PARAMETER.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - case 3 : - // JPA.g:421:7: '${' WORD '}' - { - string_literal384=(Token)match(input,116,FOLLOW_116_in_input_parameter3364); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_116.add(string_literal384); - - WORD385=(Token)match(input,WORD,FOLLOW_WORD_in_input_parameter3366); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_WORD.add(WORD385); - - char_literal386=(Token)match(input,117,FOLLOW_117_in_input_parameter3368); if (state.failed) return retval; - if ( state.backtracking==0 ) stream_117.add(char_literal386); - - - - // AST REWRITE - // elements: 117, 116, WORD - // token labels: - // rule labels: retval - // token list labels: - // rule list labels: - // wildcard labels: - if ( state.backtracking==0 ) { - retval.tree = root_0; - RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); - - root_0 = (Object)adaptor.nil(); - // 421:21: -> ^( T_PARAMETER[] '${' WORD '}' ) - { - // JPA.g:421:24: ^( T_PARAMETER[] '${' WORD '}' ) - { - Object root_1 = (Object)adaptor.nil(); - root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); - - adaptor.addChild(root_1, stream_116.nextNode()); - adaptor.addChild(root_1, stream_WORD.nextNode()); - adaptor.addChild(root_1, stream_117.nextNode()); - - adaptor.addChild(root_0, root_1); - } - - } - - retval.tree = root_0;} - } - break; - - } - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "input_parameter" - - public static class literal_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "literal" - // JPA.g:423:1: literal : WORD ; - public final JPAParser.literal_return literal() throws RecognitionException { - JPAParser.literal_return retval = new JPAParser.literal_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD387=null; - - Object WORD387_tree=null; - - try { - // JPA.g:424:5: ( WORD ) - // JPA.g:424:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD387=(Token)match(input,WORD,FOLLOW_WORD_in_literal3396); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD387_tree = (Object)adaptor.create(WORD387); - adaptor.addChild(root_0, WORD387_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "literal" - - public static class constructor_name_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "constructor_name" - // JPA.g:426:1: constructor_name : WORD ; - public final JPAParser.constructor_name_return constructor_name() throws RecognitionException { - JPAParser.constructor_name_return retval = new JPAParser.constructor_name_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD388=null; - - Object WORD388_tree=null; - - try { - // JPA.g:427:5: ( WORD ) - // JPA.g:427:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD388=(Token)match(input,WORD,FOLLOW_WORD_in_constructor_name3408); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD388_tree = (Object)adaptor.create(WORD388); - adaptor.addChild(root_0, WORD388_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "constructor_name" - - public static class enum_literal_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "enum_literal" - // JPA.g:429:1: enum_literal : WORD ; - public final JPAParser.enum_literal_return enum_literal() throws RecognitionException { - JPAParser.enum_literal_return retval = new JPAParser.enum_literal_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD389=null; - - Object WORD389_tree=null; - - try { - // JPA.g:430:5: ( WORD ) - // JPA.g:430:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD389=(Token)match(input,WORD,FOLLOW_WORD_in_enum_literal3452); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD389_tree = (Object)adaptor.create(WORD389); - adaptor.addChild(root_0, WORD389_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "enum_literal" - - public static class boolean_literal_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "boolean_literal" - // JPA.g:432:1: boolean_literal : ( 'true' | 'false' ); - public final JPAParser.boolean_literal_return boolean_literal() throws RecognitionException { - JPAParser.boolean_literal_return retval = new JPAParser.boolean_literal_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set390=null; - - Object set390_tree=null; - - try { - // JPA.g:433:5: ( 'true' | 'false' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set390=(Token)input.LT(1); - if ( (input.LA(1)>=118 && input.LA(1)<=119) ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set390)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "boolean_literal" - - public static class field_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "field" - // JPA.g:437:1: field : ( WORD | 'GROUP' ); - public final JPAParser.field_return field() throws RecognitionException { - JPAParser.field_return retval = new JPAParser.field_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token set391=null; - - Object set391_tree=null; - - try { - // JPA.g:438:5: ( WORD | 'GROUP' ) - // JPA.g: - { - root_0 = (Object)adaptor.nil(); - - set391=(Token)input.LT(1); - if ( input.LA(1)==GROUP||input.LA(1)==WORD ) { - input.consume(); - if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set391)); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return retval;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "field" - - public static class identification_variable_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "identification_variable" - // JPA.g:440:1: identification_variable : WORD ; - public final JPAParser.identification_variable_return identification_variable() throws RecognitionException { - JPAParser.identification_variable_return retval = new JPAParser.identification_variable_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD392=null; - - Object WORD392_tree=null; - - try { - // JPA.g:441:5: ( WORD ) - // JPA.g:441:7: WORD - { - root_0 = (Object)adaptor.nil(); - - WORD392=(Token)match(input,WORD,FOLLOW_WORD_in_identification_variable3501); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD392_tree = (Object)adaptor.create(WORD392); - adaptor.addChild(root_0, WORD392_tree); - } - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "identification_variable" - - public static class parameter_name_return extends ParserRuleReturnScope { - Object tree; - public Object getTree() { return tree; } - }; - - // $ANTLR start "parameter_name" - // JPA.g:443:1: parameter_name : WORD ( '.' WORD )* ; - public final JPAParser.parameter_name_return parameter_name() throws RecognitionException { - JPAParser.parameter_name_return retval = new JPAParser.parameter_name_return(); - retval.start = input.LT(1); - - Object root_0 = null; - - Token WORD393=null; - Token char_literal394=null; - Token WORD395=null; - - Object WORD393_tree=null; - Object char_literal394_tree=null; - Object WORD395_tree=null; - - try { - // JPA.g:444:5: ( WORD ( '.' WORD )* ) - // JPA.g:444:7: WORD ( '.' WORD )* - { - root_0 = (Object)adaptor.nil(); - - WORD393=(Token)match(input,WORD,FOLLOW_WORD_in_parameter_name3513); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD393_tree = (Object)adaptor.create(WORD393); - adaptor.addChild(root_0, WORD393_tree); - } - // JPA.g:444:12: ( '.' WORD )* - loop103: - do { - int alt103=2; - int LA103_0 = input.LA(1); - - if ( (LA103_0==57) ) { - alt103=1; - } - - - switch (alt103) { - case 1 : - // JPA.g:444:13: '.' WORD - { - char_literal394=(Token)match(input,57,FOLLOW_57_in_parameter_name3516); if (state.failed) return retval; - if ( state.backtracking==0 ) { - char_literal394_tree = (Object)adaptor.create(char_literal394); - adaptor.addChild(root_0, char_literal394_tree); - } - WORD395=(Token)match(input,WORD,FOLLOW_WORD_in_parameter_name3519); if (state.failed) return retval; - if ( state.backtracking==0 ) { - WORD395_tree = (Object)adaptor.create(WORD395); - adaptor.addChild(root_0, WORD395_tree); - } - - } - break; - - default : - break loop103; - } - } while (true); - - - } - - retval.stop = input.LT(-1); - - if ( state.backtracking==0 ) { - - retval.tree = (Object)adaptor.rulePostProcessing(root_0); - adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); - } - } - catch (RecognitionException re) { - reportError(re); - recover(input,re); - retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); - - } - finally { - } - return retval; - } - // $ANTLR end "parameter_name" - - // $ANTLR start synpred20_JPA - public final void synpred20_JPA_fragment() throws RecognitionException { - // JPA.g:130:47: ( field ) - // JPA.g:130:47: field - { - pushFollow(FOLLOW_field_in_synpred20_JPA887); - field(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred20_JPA - - // $ANTLR start synpred23_JPA - public final void synpred23_JPA_fragment() throws RecognitionException { - // JPA.g:140:49: ( field ) - // JPA.g:140:49: field - { - pushFollow(FOLLOW_field_in_synpred23_JPA982); - field(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred23_JPA - - // $ANTLR start synpred57_JPA - public final void synpred57_JPA_fragment() throws RecognitionException { - // JPA.g:228:8: ( 'NOT' ) - // JPA.g:228:8: 'NOT' - { - match(input,62,FOLLOW_62_in_synpred57_JPA1823); if (state.failed) return ; - - } - } - // $ANTLR end synpred57_JPA - - // $ANTLR start synpred58_JPA - public final void synpred58_JPA_fragment() throws RecognitionException { - // JPA.g:228:7: ( ( 'NOT' )? simple_cond_expression ) - // JPA.g:228:7: ( 'NOT' )? simple_cond_expression - { - // JPA.g:228:7: ( 'NOT' )? - int alt108=2; - int LA108_0 = input.LA(1); - - if ( (LA108_0==62) ) { - int LA108_1 = input.LA(2); - - if ( (synpred57_JPA()) ) { - alt108=1; - } - } - switch (alt108) { - case 1 : - // JPA.g:228:8: 'NOT' - { - match(input,62,FOLLOW_62_in_synpred58_JPA1823); if (state.failed) return ; - - } - break; - - } - - pushFollow(FOLLOW_simple_cond_expression_in_synpred58_JPA1827); - simple_cond_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred58_JPA - - // $ANTLR start synpred59_JPA - public final void synpred59_JPA_fragment() throws RecognitionException { - // JPA.g:232:7: ( comparison_expression ) - // JPA.g:232:7: comparison_expression - { - pushFollow(FOLLOW_comparison_expression_in_synpred59_JPA1866); - comparison_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred59_JPA - - // $ANTLR start synpred60_JPA - public final void synpred60_JPA_fragment() throws RecognitionException { - // JPA.g:233:7: ( between_expression ) - // JPA.g:233:7: between_expression - { - pushFollow(FOLLOW_between_expression_in_synpred60_JPA1874); - between_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred60_JPA - - // $ANTLR start synpred61_JPA - public final void synpred61_JPA_fragment() throws RecognitionException { - // JPA.g:234:7: ( like_expression ) - // JPA.g:234:7: like_expression - { - pushFollow(FOLLOW_like_expression_in_synpred61_JPA1882); - like_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred61_JPA - - // $ANTLR start synpred62_JPA - public final void synpred62_JPA_fragment() throws RecognitionException { - // JPA.g:235:7: ( in_expression ) - // JPA.g:235:7: in_expression - { - pushFollow(FOLLOW_in_expression_in_synpred62_JPA1890); - in_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred62_JPA - - // $ANTLR start synpred63_JPA - public final void synpred63_JPA_fragment() throws RecognitionException { - // JPA.g:236:7: ( null_comparison_expression ) - // JPA.g:236:7: null_comparison_expression - { - pushFollow(FOLLOW_null_comparison_expression_in_synpred63_JPA1898); - null_comparison_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred63_JPA - - // $ANTLR start synpred64_JPA - public final void synpred64_JPA_fragment() throws RecognitionException { - // JPA.g:237:7: ( empty_collection_comparison_expression ) - // JPA.g:237:7: empty_collection_comparison_expression - { - pushFollow(FOLLOW_empty_collection_comparison_expression_in_synpred64_JPA1906); - empty_collection_comparison_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred64_JPA - - // $ANTLR start synpred65_JPA - public final void synpred65_JPA_fragment() throws RecognitionException { - // JPA.g:238:7: ( collection_member_expression ) - // JPA.g:238:7: collection_member_expression - { - pushFollow(FOLLOW_collection_member_expression_in_synpred65_JPA1914); - collection_member_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred65_JPA - - // $ANTLR start synpred84_JPA - public final void synpred84_JPA_fragment() throws RecognitionException { - // JPA.g:265:7: ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression ) - // JPA.g:265:7: arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression - { - pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2165); - arithmetic_expression(); - - state._fsp--; - if (state.failed) return ; - // JPA.g:265:29: ( 'NOT' )? - int alt109=2; - int LA109_0 = input.LA(1); - - if ( (LA109_0==62) ) { - alt109=1; - } - switch (alt109) { - case 1 : - // JPA.g:265:30: 'NOT' - { - match(input,62,FOLLOW_62_in_synpred84_JPA2168); if (state.failed) return ; - - } - break; - - } - - match(input,77,FOLLOW_77_in_synpred84_JPA2172); if (state.failed) return ; - pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2174); - arithmetic_expression(); - - state._fsp--; - if (state.failed) return ; - match(input,AND,FOLLOW_AND_in_synpred84_JPA2176); if (state.failed) return ; - pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2178); - arithmetic_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred84_JPA - - // $ANTLR start synpred86_JPA - public final void synpred86_JPA_fragment() throws RecognitionException { - // JPA.g:266:7: ( string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression ) - // JPA.g:266:7: string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression - { - pushFollow(FOLLOW_string_expression_in_synpred86_JPA2186); - string_expression(); - - state._fsp--; - if (state.failed) return ; - // JPA.g:266:25: ( 'NOT' )? - int alt110=2; - int LA110_0 = input.LA(1); - - if ( (LA110_0==62) ) { - alt110=1; - } - switch (alt110) { - case 1 : - // JPA.g:266:26: 'NOT' - { - match(input,62,FOLLOW_62_in_synpred86_JPA2189); if (state.failed) return ; - - } - break; - - } - - match(input,77,FOLLOW_77_in_synpred86_JPA2193); if (state.failed) return ; - pushFollow(FOLLOW_string_expression_in_synpred86_JPA2195); - string_expression(); - - state._fsp--; - if (state.failed) return ; - match(input,AND,FOLLOW_AND_in_synpred86_JPA2197); if (state.failed) return ; - pushFollow(FOLLOW_string_expression_in_synpred86_JPA2199); - string_expression(); - - state._fsp--; - if (state.failed) return ; - - } - } - // $ANTLR end synpred86_JPA - - // $ANTLR start synpred104_JPA - public final void synpred104_JPA_fragment() throws RecognitionException { - // JPA.g:299:7: ( string_expression comparison_operator ( string_expression | all_or_any_expression ) ) - // JPA.g:299:7: string_expression comparison_operator ( string_expression | all_or_any_expression ) - { - pushFollow(FOLLOW_string_expression_in_synpred104_JPA2455); - string_expression(); - - state._fsp--; - if (state.failed) return ; - pushFollow(FOLLOW_comparison_operator_in_synpred104_JPA2457); - comparison_operator(); - - state._fsp--; - if (state.failed) return ; - // JPA.g:299:45: ( string_expression | all_or_any_expression ) - int alt112=2; - int LA112_0 = input.LA(1); - - if ( ((LA112_0>=AVG && LA112_0<=COUNT)||LA112_0==STRINGLITERAL||(LA112_0>=WORD && LA112_0<=NAMED_PARAMETER)||LA112_0==56||(LA112_0>=106 && LA112_0<=110)||(LA112_0>=115 && LA112_0<=116)) ) { - alt112=1; - } - else if ( ((LA112_0>=86 && LA112_0<=88)) ) { - alt112=2; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - NoViableAltException nvae = - new NoViableAltException("", 112, 0, input); - - throw nvae; - } - switch (alt112) { - case 1 : - // JPA.g:299:46: string_expression - { - pushFollow(FOLLOW_string_expression_in_synpred104_JPA2460); - string_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - case 2 : - // JPA.g:299:66: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_synpred104_JPA2464); - all_or_any_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - - } - - - } - } - // $ANTLR end synpred104_JPA - - // $ANTLR start synpred107_JPA - public final void synpred107_JPA_fragment() throws RecognitionException { - // JPA.g:300:7: ( boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) ) - // JPA.g:300:7: boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) - { - pushFollow(FOLLOW_boolean_expression_in_synpred107_JPA2473); - boolean_expression(); - - state._fsp--; - if (state.failed) return ; - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:300:39: ( boolean_expression | all_or_any_expression ) - int alt113=2; - int LA113_0 = input.LA(1); - - if ( ((LA113_0>=WORD && LA113_0<=NAMED_PARAMETER)||LA113_0==56||(LA113_0>=115 && LA113_0<=116)||(LA113_0>=118 && LA113_0<=119)) ) { - alt113=1; - } - else if ( ((LA113_0>=86 && LA113_0<=88)) ) { - alt113=2; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - NoViableAltException nvae = - new NoViableAltException("", 113, 0, input); - - throw nvae; - } - switch (alt113) { - case 1 : - // JPA.g:300:40: boolean_expression - { - pushFollow(FOLLOW_boolean_expression_in_synpred107_JPA2484); - boolean_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - case 2 : - // JPA.g:300:61: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_synpred107_JPA2488); - all_or_any_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - - } - - - } - } - // $ANTLR end synpred107_JPA - - // $ANTLR start synpred110_JPA - public final void synpred110_JPA_fragment() throws RecognitionException { - // JPA.g:301:7: ( enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) ) - // JPA.g:301:7: enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) - { - pushFollow(FOLLOW_enum_expression_in_synpred110_JPA2497); - enum_expression(); - - state._fsp--; - if (state.failed) return ; - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:301:34: ( enum_expression | all_or_any_expression ) - int alt114=2; - int LA114_0 = input.LA(1); - - if ( ((LA114_0>=WORD && LA114_0<=NAMED_PARAMETER)||LA114_0==56||(LA114_0>=115 && LA114_0<=116)) ) { - alt114=1; - } - else if ( ((LA114_0>=86 && LA114_0<=88)) ) { - alt114=2; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - NoViableAltException nvae = - new NoViableAltException("", 114, 0, input); - - throw nvae; - } - switch (alt114) { - case 1 : - // JPA.g:301:35: enum_expression - { - pushFollow(FOLLOW_enum_expression_in_synpred110_JPA2506); - enum_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - case 2 : - // JPA.g:301:53: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_synpred110_JPA2510); - all_or_any_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - - } - - - } - } - // $ANTLR end synpred110_JPA - - // $ANTLR start synpred112_JPA - public final void synpred112_JPA_fragment() throws RecognitionException { - // JPA.g:302:7: ( datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) ) - // JPA.g:302:7: datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) - { - pushFollow(FOLLOW_datetime_expression_in_synpred112_JPA2519); - datetime_expression(); - - state._fsp--; - if (state.failed) return ; - pushFollow(FOLLOW_comparison_operator_in_synpred112_JPA2521); - comparison_operator(); - - state._fsp--; - if (state.failed) return ; - // JPA.g:302:47: ( datetime_expression | all_or_any_expression ) - int alt115=2; - int LA115_0 = input.LA(1); - - if ( ((LA115_0>=AVG && LA115_0<=COUNT)||(LA115_0>=WORD && LA115_0<=NAMED_PARAMETER)||LA115_0==56||(LA115_0>=103 && LA115_0<=105)||(LA115_0>=115 && LA115_0<=116)) ) { - alt115=1; - } - else if ( ((LA115_0>=86 && LA115_0<=88)) ) { - alt115=2; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - NoViableAltException nvae = - new NoViableAltException("", 115, 0, input); - - throw nvae; - } - switch (alt115) { - case 1 : - // JPA.g:302:48: datetime_expression - { - pushFollow(FOLLOW_datetime_expression_in_synpred112_JPA2524); - datetime_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - case 2 : - // JPA.g:302:70: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_synpred112_JPA2528); - all_or_any_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - - } - - - } - } - // $ANTLR end synpred112_JPA - - // $ANTLR start synpred115_JPA - public final void synpred115_JPA_fragment() throws RecognitionException { - // JPA.g:303:7: ( entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) ) - // JPA.g:303:7: entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) - { - pushFollow(FOLLOW_entity_expression_in_synpred115_JPA2537); - entity_expression(); - - state._fsp--; - if (state.failed) return ; - if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { - input.consume(); - state.errorRecovery=false;state.failed=false; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - MismatchedSetException mse = new MismatchedSetException(null,input); - throw mse; - } - - // JPA.g:303:38: ( entity_expression | all_or_any_expression ) - int alt116=2; - int LA116_0 = input.LA(1); - - if ( ((LA116_0>=WORD && LA116_0<=NAMED_PARAMETER)||(LA116_0>=115 && LA116_0<=116)) ) { - alt116=1; - } - else if ( ((LA116_0>=86 && LA116_0<=88)) ) { - alt116=2; - } - else { - if (state.backtracking>0) {state.failed=true; return ;} - NoViableAltException nvae = - new NoViableAltException("", 116, 0, input); - - throw nvae; - } - switch (alt116) { - case 1 : - // JPA.g:303:39: entity_expression - { - pushFollow(FOLLOW_entity_expression_in_synpred115_JPA2548); - entity_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - case 2 : - // JPA.g:303:59: all_or_any_expression - { - pushFollow(FOLLOW_all_or_any_expression_in_synpred115_JPA2552); - all_or_any_expression(); - - state._fsp--; - if (state.failed) return ; - - } - break; - - } - - - } - } - // $ANTLR end synpred115_JPA - - // Delegated rules - - public final boolean synpred115_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred115_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred110_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred110_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred112_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred112_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred60_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred60_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred64_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred64_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred65_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred65_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred20_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred20_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred104_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred104_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred84_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred84_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred62_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred62_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred63_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred63_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred23_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred23_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred59_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred59_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred107_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred107_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred58_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred58_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred86_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred86_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred57_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred57_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - public final boolean synpred61_JPA() { - state.backtracking++; - int start = input.mark(); - try { - synpred61_JPA_fragment(); // can never throw exception - } catch (RecognitionException re) { - System.err.println("impossible: "+re); - } - boolean success = !state.failed; - input.rewind(start); - state.backtracking--; - state.failed=false; - return success; - } - - - protected DFA31 dfa31 = new DFA31(this); - protected DFA36 dfa36 = new DFA36(this); - protected DFA48 dfa48 = new DFA48(this); - protected DFA49 dfa49 = new DFA49(this); - protected DFA59 dfa59 = new DFA59(this); - protected DFA79 dfa79 = new DFA79(this); - static final String DFA31_eotS = - "\11\uffff"; - static final String DFA31_eofS = - "\4\uffff\3\7\1\uffff\1\7"; - static final String DFA31_minS = - "\1\75\1\30\1\71\1\uffff\3\25\1\uffff\1\25"; - static final String DFA31_maxS = - "\1\75\1\167\1\132\1\uffff\3\140\1\uffff\1\140"; - static final String DFA31_acceptS = - "\3\uffff\1\1\3\uffff\1\2\1\uffff"; - static final String DFA31_specialS = - "\11\uffff}>"; - static final String[] DFA31_transitionS = { - "\1\1", - "\5\3\2\uffff\1\3\12\uffff\1\3\1\uffff\1\3\1\uffff\1\2\1\3"+ - "\10\uffff\1\3\5\uffff\2\3\1\uffff\2\3\6\uffff\4\3\10\uffff\1"+ - "\3\13\uffff\16\3\3\uffff\3\3\1\uffff\2\3", - "\1\4\4\uffff\1\3\24\uffff\1\3\5\uffff\2\3", - "", - "\1\7\12\uffff\1\7\6\uffff\1\7\1\5\5\uffff\1\6\13\uffff\1\3"+ - "\3\uffff\1\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1"+ - "\3\5\uffff\10\3", - "\1\7\12\uffff\1\7\6\uffff\3\7\17\uffff\1\10\1\3\3\uffff\1"+ - "\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1\3\5\uffff"+ - "\10\3", - "\1\7\12\uffff\1\7\6\uffff\2\7\20\uffff\1\10\1\3\3\uffff\1"+ - "\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1\3\5\uffff"+ - "\10\3", - "", - "\1\7\12\uffff\1\7\6\uffff\1\7\1\5\5\uffff\1\6\13\uffff\1\3"+ - "\3\uffff\1\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1"+ - "\3\5\uffff\10\3" - }; - - static final short[] DFA31_eot = DFA.unpackEncodedString(DFA31_eotS); - static final short[] DFA31_eof = DFA.unpackEncodedString(DFA31_eofS); - static final char[] DFA31_min = DFA.unpackEncodedStringToUnsignedChars(DFA31_minS); - static final char[] DFA31_max = DFA.unpackEncodedStringToUnsignedChars(DFA31_maxS); - static final short[] DFA31_accept = DFA.unpackEncodedString(DFA31_acceptS); - static final short[] DFA31_special = DFA.unpackEncodedString(DFA31_specialS); - static final short[][] DFA31_transition; - - static { - int numStates = DFA31_transitionS.length; - DFA31_transition = new short[numStates][]; - for (int i=0; i ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) );"; - } - } - static final String DFA36_eotS = - "\7\uffff"; - static final String DFA36_eofS = - "\2\uffff\2\5\2\uffff\1\5"; - static final String DFA36_minS = - "\1\56\1\71\2\26\2\uffff\1\26"; - static final String DFA36_maxS = - "\1\56\1\71\1\66\1\71\2\uffff\1\66"; - static final String DFA36_acceptS = - "\4\uffff\1\2\1\1\1\uffff"; - static final String DFA36_specialS = - "\7\uffff}>"; - static final String[] DFA36_transitionS = { - "\1\1", - "\1\2", - "\1\5\1\4\10\uffff\1\5\7\uffff\1\3\5\uffff\1\3\7\uffff\1\5", - "\1\5\1\4\10\uffff\1\5\25\uffff\1\5\2\uffff\1\6", - "", - "", - "\1\5\1\4\10\uffff\1\5\7\uffff\1\3\5\uffff\1\3\7\uffff\1\5" - }; - - static final short[] DFA36_eot = DFA.unpackEncodedString(DFA36_eotS); - static final short[] DFA36_eof = DFA.unpackEncodedString(DFA36_eofS); - static final char[] DFA36_min = DFA.unpackEncodedStringToUnsignedChars(DFA36_minS); - static final char[] DFA36_max = DFA.unpackEncodedStringToUnsignedChars(DFA36_maxS); - static final short[] DFA36_accept = DFA.unpackEncodedString(DFA36_acceptS); - static final short[] DFA36_special = DFA.unpackEncodedString(DFA36_specialS); - static final short[][] DFA36_transition; - - static { - int numStates = DFA36_transitionS.length; - DFA36_transition = new short[numStates][]; - for (int i=0; i ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) );"; - } - } - static final String DFA48_eotS = - "\42\uffff"; - static final String DFA48_eofS = - "\42\uffff"; - static final String DFA48_minS = - "\1\30\23\uffff\1\0\15\uffff"; - static final String DFA48_maxS = - "\1\167\23\uffff\1\0\15\uffff"; - static final String DFA48_acceptS = - "\1\uffff\1\1\37\uffff\1\2"; - static final String DFA48_specialS = - "\24\uffff\1\0\15\uffff}>"; - static final String[] DFA48_transitionS = { - "\5\1\2\uffff\1\24\12\uffff\1\1\1\uffff\1\1\1\uffff\2\1\10\uffff"+ - "\1\1\5\uffff\2\1\1\uffff\2\1\6\uffff\4\1\10\uffff\1\1\13\uffff"+ - "\16\1\3\uffff\3\1\1\uffff\2\1", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "\1\uffff", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - }; - - static final short[] DFA48_eot = DFA.unpackEncodedString(DFA48_eotS); - static final short[] DFA48_eof = DFA.unpackEncodedString(DFA48_eofS); - static final char[] DFA48_min = DFA.unpackEncodedStringToUnsignedChars(DFA48_minS); - static final char[] DFA48_max = DFA.unpackEncodedStringToUnsignedChars(DFA48_maxS); - static final short[] DFA48_accept = DFA.unpackEncodedString(DFA48_acceptS); - static final short[] DFA48_special = DFA.unpackEncodedString(DFA48_specialS); - static final short[][] DFA48_transition; - - static { - int numStates = DFA48_transitionS.length; - DFA48_transition = new short[numStates][]; - for (int i=0; i ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' );"; - } - public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { - TokenStream input = (TokenStream)_input; - int _s = s; - switch ( s ) { - case 0 : - int LA48_20 = input.LA(1); - - - int index48_20 = input.index(); - input.rewind(); - s = -1; - if ( (synpred58_JPA()) ) {s = 1;} - - else if ( (true) ) {s = 33;} - - - input.seek(index48_20); - if ( s>=0 ) return s; - break; - } - if (state.backtracking>0) {state.failed=true; return -1;} - NoViableAltException nvae = - new NoViableAltException(getDescription(), 48, _s, input); - error(nvae); - throw nvae; - } - } - static final String DFA49_eotS = - "\47\uffff"; - static final String DFA49_eofS = - "\47\uffff"; - static final String DFA49_minS = - "\1\30\15\0\1\uffff\13\0\15\uffff"; - static final String DFA49_maxS = - "\1\167\15\0\1\uffff\13\0\15\uffff"; - static final String DFA49_acceptS = - "\16\uffff\1\1\13\uffff\1\10\1\uffff\1\11\4\uffff\1\2\1\3\1\4\1"+ - "\5\1\6\1\7"; - static final String DFA49_specialS = - "\1\uffff\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\11\1\12\1\13\1"+ - "\14\1\uffff\1\15\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25\1\26\1"+ - "\27\15\uffff}>"; - static final String[] DFA49_transitionS = { - "\4\14\1\13\2\uffff\1\23\12\uffff\1\22\1\uffff\1\2\1\uffff\1"+ - "\1\1\4\10\uffff\1\15\5\uffff\1\32\1\34\1\uffff\2\20\6\uffff"+ - "\4\34\10\uffff\1\32\13\uffff\1\24\1\25\1\26\1\27\1\30\1\31\3"+ - "\17\1\6\1\7\1\10\1\11\1\12\3\uffff\1\21\1\3\1\5\1\uffff\2\16", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - }; - - static final short[] DFA49_eot = DFA.unpackEncodedString(DFA49_eotS); - static final short[] DFA49_eof = DFA.unpackEncodedString(DFA49_eofS); - static final char[] DFA49_min = DFA.unpackEncodedStringToUnsignedChars(DFA49_minS); - static final char[] DFA49_max = DFA.unpackEncodedStringToUnsignedChars(DFA49_maxS); - static final short[] DFA49_accept = DFA.unpackEncodedString(DFA49_acceptS); - static final short[] DFA49_special = DFA.unpackEncodedString(DFA49_specialS); - static final short[][] DFA49_transition; - - static { - int numStates = DFA49_transitionS.length; - DFA49_transition = new short[numStates][]; - for (int i=0; i=0 ) return s; - break; - case 1 : - int LA49_2 = input.LA(1); - - - int index49_2 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_2); - if ( s>=0 ) return s; - break; - case 2 : - int LA49_3 = input.LA(1); - - - int index49_3 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - else if ( (synpred63_JPA()) ) {s = 36;} - - else if ( (synpred65_JPA()) ) {s = 38;} - - - input.seek(index49_3); - if ( s>=0 ) return s; - break; - case 3 : - int LA49_4 = input.LA(1); - - - int index49_4 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - else if ( (synpred63_JPA()) ) {s = 36;} - - else if ( (synpred65_JPA()) ) {s = 38;} - - - input.seek(index49_4); - if ( s>=0 ) return s; - break; - case 4 : - int LA49_5 = input.LA(1); - - - int index49_5 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - else if ( (synpred63_JPA()) ) {s = 36;} - - else if ( (synpred65_JPA()) ) {s = 38;} - - - input.seek(index49_5); - if ( s>=0 ) return s; - break; - case 5 : - int LA49_6 = input.LA(1); - - - int index49_6 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_6); - if ( s>=0 ) return s; - break; - case 6 : - int LA49_7 = input.LA(1); - - - int index49_7 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_7); - if ( s>=0 ) return s; - break; - case 7 : - int LA49_8 = input.LA(1); - - - int index49_8 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_8); - if ( s>=0 ) return s; - break; - case 8 : - int LA49_9 = input.LA(1); - - - int index49_9 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_9); - if ( s>=0 ) return s; - break; - case 9 : - int LA49_10 = input.LA(1); - - - int index49_10 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_10); - if ( s>=0 ) return s; - break; - case 10 : - int LA49_11 = input.LA(1); - - - int index49_11 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_11); - if ( s>=0 ) return s; - break; - case 11 : - int LA49_12 = input.LA(1); - - - int index49_12 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_12); - if ( s>=0 ) return s; - break; - case 12 : - int LA49_13 = input.LA(1); - - - int index49_13 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - else if ( (synpred61_JPA()) ) {s = 34;} - - - input.seek(index49_13); - if ( s>=0 ) return s; - break; - case 13 : - int LA49_15 = input.LA(1); - - - int index49_15 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_15); - if ( s>=0 ) return s; - break; - case 14 : - int LA49_16 = input.LA(1); - - - int index49_16 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_16); - if ( s>=0 ) return s; - break; - case 15 : - int LA49_17 = input.LA(1); - - - int index49_17 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_17); - if ( s>=0 ) return s; - break; - case 16 : - int LA49_18 = input.LA(1); - - - int index49_18 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_18); - if ( s>=0 ) return s; - break; - case 17 : - int LA49_19 = input.LA(1); - - - int index49_19 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_19); - if ( s>=0 ) return s; - break; - case 18 : - int LA49_20 = input.LA(1); - - - int index49_20 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_20); - if ( s>=0 ) return s; - break; - case 19 : - int LA49_21 = input.LA(1); - - - int index49_21 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_21); - if ( s>=0 ) return s; - break; - case 20 : - int LA49_22 = input.LA(1); - - - int index49_22 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_22); - if ( s>=0 ) return s; - break; - case 21 : - int LA49_23 = input.LA(1); - - - int index49_23 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_23); - if ( s>=0 ) return s; - break; - case 22 : - int LA49_24 = input.LA(1); - - - int index49_24 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_24); - if ( s>=0 ) return s; - break; - case 23 : - int LA49_25 = input.LA(1); - - - int index49_25 = input.index(); - input.rewind(); - s = -1; - if ( (synpred59_JPA()) ) {s = 14;} - - else if ( (synpred60_JPA()) ) {s = 33;} - - - input.seek(index49_25); - if ( s>=0 ) return s; - break; - } - if (state.backtracking>0) {state.failed=true; return -1;} - NoViableAltException nvae = - new NoViableAltException(getDescription(), 49, _s, input); - error(nvae); - throw nvae; - } - } - static final String DFA59_eotS = - "\31\uffff"; - static final String DFA59_eofS = - "\31\uffff"; - static final String DFA59_minS = - "\1\30\1\uffff\1\0\3\uffff\3\0\6\uffff\3\0\7\uffff"; - static final String DFA59_maxS = - "\1\164\1\uffff\1\0\3\uffff\3\0\6\uffff\3\0\7\uffff"; - static final String DFA59_acceptS = - "\1\uffff\1\1\20\uffff\1\2\5\uffff\1\3"; - static final String DFA59_specialS = - "\2\uffff\1\0\3\uffff\1\1\1\2\1\3\6\uffff\1\4\1\5\1\6\7\uffff}>"; - static final String[] DFA59_transitionS = { - "\4\20\1\17\2\uffff\1\1\12\uffff\1\1\1\uffff\1\22\1\uffff\1"+ - "\2\1\7\10\uffff\1\21\10\uffff\2\1\36\uffff\6\1\3\30\5\22\3\uffff"+ - "\1\1\1\6\1\10", - "", - "\1\uffff", - "", - "", - "", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "", - "", - "", - "", - "", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "", - "", - "", - "", - "", - "" - }; - - static final short[] DFA59_eot = DFA.unpackEncodedString(DFA59_eotS); - static final short[] DFA59_eof = DFA.unpackEncodedString(DFA59_eofS); - static final char[] DFA59_min = DFA.unpackEncodedStringToUnsignedChars(DFA59_minS); - static final char[] DFA59_max = DFA.unpackEncodedStringToUnsignedChars(DFA59_maxS); - static final short[] DFA59_accept = DFA.unpackEncodedString(DFA59_acceptS); - static final short[] DFA59_special = DFA.unpackEncodedString(DFA59_specialS); - static final short[][] DFA59_transition; - - static { - int numStates = DFA59_transitionS.length; - DFA59_transition = new short[numStates][]; - for (int i=0; i=0 ) return s; - break; - case 1 : - int LA59_6 = input.LA(1); - - - int index59_6 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_6); - if ( s>=0 ) return s; - break; - case 2 : - int LA59_7 = input.LA(1); - - - int index59_7 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_7); - if ( s>=0 ) return s; - break; - case 3 : - int LA59_8 = input.LA(1); - - - int index59_8 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_8); - if ( s>=0 ) return s; - break; - case 4 : - int LA59_15 = input.LA(1); - - - int index59_15 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_15); - if ( s>=0 ) return s; - break; - case 5 : - int LA59_16 = input.LA(1); - - - int index59_16 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_16); - if ( s>=0 ) return s; - break; - case 6 : - int LA59_17 = input.LA(1); - - - int index59_17 = input.index(); - input.rewind(); - s = -1; - if ( (synpred84_JPA()) ) {s = 1;} - - else if ( (synpred86_JPA()) ) {s = 18;} - - else if ( (true) ) {s = 24;} - - - input.seek(index59_17); - if ( s>=0 ) return s; - break; - } - if (state.backtracking>0) {state.failed=true; return -1;} - NoViableAltException nvae = - new NoViableAltException(getDescription(), 59, _s, input); - error(nvae); - throw nvae; - } - } - static final String DFA79_eotS = - "\34\uffff"; - static final String DFA79_eofS = - "\34\uffff"; - static final String DFA79_minS = - "\1\30\1\0\1\uffff\3\0\5\uffff\3\0\16\uffff"; - static final String DFA79_maxS = - "\1\167\1\0\1\uffff\3\0\5\uffff\3\0\16\uffff"; - static final String DFA79_acceptS = - "\2\uffff\1\1\13\uffff\1\2\1\4\1\6\11\uffff\1\3\1\5"; - static final String DFA79_specialS = - "\1\uffff\1\0\1\uffff\1\1\1\2\1\3\5\uffff\1\4\1\5\1\6\16\uffff}>"; - static final String[] DFA79_transitionS = { - "\4\14\1\13\2\uffff\1\20\12\uffff\1\20\1\uffff\1\2\1\uffff\1"+ - "\1\1\4\10\uffff\1\15\10\uffff\2\20\36\uffff\6\20\3\17\5\2\3"+ - "\uffff\1\20\1\3\1\5\1\uffff\2\16", - "\1\uffff", - "", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "", - "", - "", - "", - "\1\uffff", - "\1\uffff", - "\1\uffff", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - }; - - static final short[] DFA79_eot = DFA.unpackEncodedString(DFA79_eotS); - static final short[] DFA79_eof = DFA.unpackEncodedString(DFA79_eofS); - static final char[] DFA79_min = DFA.unpackEncodedStringToUnsignedChars(DFA79_minS); - static final char[] DFA79_max = DFA.unpackEncodedStringToUnsignedChars(DFA79_maxS); - static final short[] DFA79_accept = DFA.unpackEncodedString(DFA79_acceptS); - static final short[] DFA79_special = DFA.unpackEncodedString(DFA79_specialS); - static final short[][] DFA79_transition; - - static { - int numStates = DFA79_transitionS.length; - DFA79_transition = new short[numStates][]; - for (int i=0; i' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) );"; - } - public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { - TokenStream input = (TokenStream)_input; - int _s = s; - switch ( s ) { - case 0 : - int LA79_1 = input.LA(1); - - - int index79_1 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred107_JPA()) ) {s = 14;} - - else if ( (synpred110_JPA()) ) {s = 26;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (synpred115_JPA()) ) {s = 27;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_1); - if ( s>=0 ) return s; - break; - case 1 : - int LA79_3 = input.LA(1); - - - int index79_3 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred107_JPA()) ) {s = 14;} - - else if ( (synpred110_JPA()) ) {s = 26;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (synpred115_JPA()) ) {s = 27;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_3); - if ( s>=0 ) return s; - break; - case 2 : - int LA79_4 = input.LA(1); - - - int index79_4 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred107_JPA()) ) {s = 14;} - - else if ( (synpred110_JPA()) ) {s = 26;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (synpred115_JPA()) ) {s = 27;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_4); - if ( s>=0 ) return s; - break; - case 3 : - int LA79_5 = input.LA(1); - - - int index79_5 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred107_JPA()) ) {s = 14;} - - else if ( (synpred110_JPA()) ) {s = 26;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (synpred115_JPA()) ) {s = 27;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_5); - if ( s>=0 ) return s; - break; - case 4 : - int LA79_11 = input.LA(1); - - - int index79_11 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_11); - if ( s>=0 ) return s; - break; - case 5 : - int LA79_12 = input.LA(1); - - - int index79_12 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_12); - if ( s>=0 ) return s; - break; - case 6 : - int LA79_13 = input.LA(1); - - - int index79_13 = input.index(); - input.rewind(); - s = -1; - if ( (synpred104_JPA()) ) {s = 2;} - - else if ( (synpred107_JPA()) ) {s = 14;} - - else if ( (synpred110_JPA()) ) {s = 26;} - - else if ( (synpred112_JPA()) ) {s = 15;} - - else if ( (true) ) {s = 16;} - - - input.seek(index79_13); - if ( s>=0 ) return s; - break; - } - if (state.backtracking>0) {state.failed=true; return -1;} - NoViableAltException nvae = - new NoViableAltException(getDescription(), 79, _s, input); - error(nvae); - throw nvae; - } - } - - - public static final BitSet FOLLOW_select_statement_in_ql_statement426 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_52_in_select_statement441 = new BitSet(new long[]{0x180040021F000000L}); - public static final BitSet FOLLOW_select_clause_in_select_statement443 = new BitSet(new long[]{0x0020000000000000L}); - public static final BitSet FOLLOW_from_clause_in_select_statement445 = new BitSet(new long[]{0x2000018000200002L}); - public static final BitSet FOLLOW_where_clause_in_select_statement448 = new BitSet(new long[]{0x0000018000200002L}); - public static final BitSet FOLLOW_groupby_clause_in_select_statement453 = new BitSet(new long[]{0x0000008000200002L}); - public static final BitSet FOLLOW_having_clause_in_select_statement458 = new BitSet(new long[]{0x0000008000000002L}); - public static final BitSet FOLLOW_orderby_clause_in_select_statement462 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_53_in_from_clause523 = new BitSet(new long[]{0x0100400000000000L}); - public static final BitSet FOLLOW_identification_variable_declaration_in_from_clause525 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_54_in_from_clause528 = new BitSet(new long[]{0x0500400000000000L}); - public static final BitSet FOLLOW_identification_variable_or_collection_declaration_in_from_clause530 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_identification_variable_declaration_in_identification_variable_or_collection_declaration563 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_collection_member_declaration_in_identification_variable_or_collection_declaration571 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_range_variable_declaration_in_identification_variable_declaration594 = new BitSet(new long[]{0x0000003400000002L}); - public static final BitSet FOLLOW_joined_clause_in_identification_variable_declaration596 = new BitSet(new long[]{0x0000003400000002L}); - public static final BitSet FOLLOW_join_in_joined_clause627 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_fetch_join_in_joined_clause631 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_range_variable_declaration_source_in_range_variable_declaration643 = new BitSet(new long[]{0x0080400000000000L}); - public static final BitSet FOLLOW_55_in_range_variable_declaration646 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_range_variable_declaration650 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_abstract_schema_name_in_range_variable_declaration_source686 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_56_in_range_variable_declaration_source696 = new BitSet(new long[]{0x180040021F000000L}); - public static final BitSet FOLLOW_select_clause_in_range_variable_declaration_source698 = new BitSet(new long[]{0x0020000000000000L}); - public static final BitSet FOLLOW_from_clause_in_range_variable_declaration_source700 = new BitSet(new long[]{0x2000018100200000L}); - public static final BitSet FOLLOW_where_clause_in_range_variable_declaration_source703 = new BitSet(new long[]{0x0000018100200000L}); - public static final BitSet FOLLOW_groupby_clause_in_range_variable_declaration_source708 = new BitSet(new long[]{0x0000008100200000L}); - public static final BitSet FOLLOW_having_clause_in_range_variable_declaration_source713 = new BitSet(new long[]{0x0000008100000000L}); - public static final BitSet FOLLOW_orderby_clause_in_range_variable_declaration_source717 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_range_variable_declaration_source723 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_join_spec_in_join786 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_join_association_path_expression_in_join788 = new BitSet(new long[]{0x0080400000000000L}); - public static final BitSet FOLLOW_55_in_join791 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_join795 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_join_spec_in_fetch_join833 = new BitSet(new long[]{0x0000004000000000L}); - public static final BitSet FOLLOW_FETCH_in_fetch_join835 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_join_association_path_expression_in_fetch_join837 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_LEFT_in_join_spec850 = new BitSet(new long[]{0x0000002800000000L}); - public static final BitSet FOLLOW_OUTER_in_join_spec854 = new BitSet(new long[]{0x0000002000000000L}); - public static final BitSet FOLLOW_INNER_in_join_spec860 = new BitSet(new long[]{0x0000002000000000L}); - public static final BitSet FOLLOW_JOIN_in_join_spec865 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_join_association_path_expression877 = new BitSet(new long[]{0x0200000000000000L}); - public static final BitSet FOLLOW_57_in_join_association_path_expression879 = new BitSet(new long[]{0x0000410000000002L}); - public static final BitSet FOLLOW_field_in_join_association_path_expression882 = new BitSet(new long[]{0x0200000000000000L}); - public static final BitSet FOLLOW_57_in_join_association_path_expression883 = new BitSet(new long[]{0x0000410000000002L}); - public static final BitSet FOLLOW_field_in_join_association_path_expression887 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_58_in_collection_member_declaration924 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_collection_member_declaration925 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_collection_member_declaration927 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_collection_member_declaration929 = new BitSet(new long[]{0x0080400000000000L}); - public static final BitSet FOLLOW_55_in_collection_member_declaration932 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_collection_member_declaration936 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_path_expression971 = new BitSet(new long[]{0x0200000000000000L}); - public static final BitSet FOLLOW_57_in_path_expression973 = new BitSet(new long[]{0x0000410000000002L}); - public static final BitSet FOLLOW_field_in_path_expression976 = new BitSet(new long[]{0x0200000000000000L}); - public static final BitSet FOLLOW_57_in_path_expression977 = new BitSet(new long[]{0x0000410000000002L}); - public static final BitSet FOLLOW_field_in_path_expression982 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_DISTINCT_in_select_clause1021 = new BitSet(new long[]{0x180040021F000000L}); - public static final BitSet FOLLOW_select_expression_in_select_clause1025 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_54_in_select_clause1028 = new BitSet(new long[]{0x180040021F000000L}); - public static final BitSet FOLLOW_select_expression_in_select_clause1030 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_path_expression_in_select_expression1075 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_select_expression1083 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_select_expression1091 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_59_in_select_expression1109 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_select_expression1111 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_select_expression1112 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_select_expression1113 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_constructor_expression_in_select_expression1121 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_60_in_constructor_expression1133 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_constructor_name_in_constructor_expression1135 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_constructor_expression1137 = new BitSet(new long[]{0x000040001F000000L}); - public static final BitSet FOLLOW_constructor_item_in_constructor_expression1139 = new BitSet(new long[]{0x0040000100000000L}); - public static final BitSet FOLLOW_54_in_constructor_expression1142 = new BitSet(new long[]{0x000040001F000000L}); - public static final BitSet FOLLOW_constructor_item_in_constructor_expression1144 = new BitSet(new long[]{0x0040000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_constructor_expression1148 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_constructor_item1160 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_constructor_item1164 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_function_name_in_aggregate_expression1176 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_aggregate_expression1178 = new BitSet(new long[]{0x0000400200000000L}); - public static final BitSet FOLLOW_DISTINCT_in_aggregate_expression1181 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_aggregate_expression1185 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_aggregate_expression1186 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_COUNT_in_aggregate_expression1220 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_aggregate_expression1222 = new BitSet(new long[]{0x0000400200000000L}); - public static final BitSet FOLLOW_DISTINCT_in_aggregate_expression1225 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_aggregate_expression1229 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_aggregate_expression1231 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_aggregate_expression_function_name0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_61_in_where_clause1299 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_conditional_expression_in_where_clause1301 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_61_in_where_clause1320 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_where_clause1322 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_GROUP_in_groupby_clause1346 = new BitSet(new long[]{0x0000020000000000L}); - public static final BitSet FOLLOW_BY_in_groupby_clause1348 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_groupby_item_in_groupby_clause1350 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_54_in_groupby_clause1353 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_groupby_item_in_groupby_clause1355 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_path_expression_in_groupby_item1395 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_groupby_item1399 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_HAVING_in_having_clause1411 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_conditional_expression_in_having_clause1413 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_ORDER_in_orderby_clause1425 = new BitSet(new long[]{0x0000020000000000L}); - public static final BitSet FOLLOW_BY_in_orderby_clause1427 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_orderby_item_in_orderby_clause1429 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_54_in_orderby_clause1432 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_orderby_item_in_orderby_clause1434 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_path_expression_in_orderby_item1469 = new BitSet(new long[]{0x0000000000400002L}); - public static final BitSet FOLLOW_ASC_in_orderby_item1474 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_orderby_item1506 = new BitSet(new long[]{0x0000000000800000L}); - public static final BitSet FOLLOW_DESC_in_orderby_item1510 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_56_in_subquery1542 = new BitSet(new long[]{0x000040021F000000L}); - public static final BitSet FOLLOW_simple_select_clause_in_subquery1544 = new BitSet(new long[]{0x0020000000000000L}); - public static final BitSet FOLLOW_subquery_from_clause_in_subquery1546 = new BitSet(new long[]{0x2000010100200000L}); - public static final BitSet FOLLOW_where_clause_in_subquery1549 = new BitSet(new long[]{0x0000010100200000L}); - public static final BitSet FOLLOW_groupby_clause_in_subquery1554 = new BitSet(new long[]{0x0000000100200000L}); - public static final BitSet FOLLOW_having_clause_in_subquery1559 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_subquery1565 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_53_in_subquery_from_clause1614 = new BitSet(new long[]{0x0500400000000000L}); - public static final BitSet FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1616 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_54_in_subquery_from_clause1619 = new BitSet(new long[]{0x0500400000000000L}); - public static final BitSet FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1621 = new BitSet(new long[]{0x0040000000000002L}); - public static final BitSet FOLLOW_identification_variable_declaration_in_subselect_identification_variable_declaration1659 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_association_path_expression_in_subselect_identification_variable_declaration1667 = new BitSet(new long[]{0x0080400000000000L}); - public static final BitSet FOLLOW_55_in_subselect_identification_variable_declaration1670 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_identification_variable_in_subselect_identification_variable_declaration1674 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_collection_member_declaration_in_subselect_identification_variable_declaration1682 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_association_path_expression1694 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_DISTINCT_in_simple_select_clause1707 = new BitSet(new long[]{0x000040021F000000L}); - public static final BitSet FOLLOW_simple_select_expression_in_simple_select_clause1711 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_simple_select_expression1748 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_simple_select_expression1756 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_simple_select_expression1764 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_conditional_term_in_conditional_expression1777 = new BitSet(new long[]{0x0000000020000002L}); - public static final BitSet FOLLOW_OR_in_conditional_expression1781 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_conditional_term_in_conditional_expression1783 = new BitSet(new long[]{0x0000000020000002L}); - public static final BitSet FOLLOW_conditional_factor_in_conditional_term1798 = new BitSet(new long[]{0x0000000040000002L}); - public static final BitSet FOLLOW_AND_in_conditional_term1802 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_conditional_factor_in_conditional_term1804 = new BitSet(new long[]{0x0000000040000002L}); - public static final BitSet FOLLOW_62_in_conditional_factor1823 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_simple_cond_expression_in_conditional_factor1827 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_LPAREN_in_conditional_factor1852 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_conditional_expression_in_conditional_factor1853 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_conditional_factor1854 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_comparison_expression_in_simple_cond_expression1866 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_between_expression_in_simple_cond_expression1874 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_like_expression_in_simple_cond_expression1882 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_in_expression_in_simple_cond_expression1890 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_null_comparison_expression_in_simple_cond_expression1898 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_empty_collection_comparison_expression_in_simple_cond_expression1906 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_collection_member_expression_in_simple_cond_expression1914 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_exists_expression_in_simple_cond_expression1922 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_macro_expression_in_simple_cond_expression1930 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_between_macro_expression_in_date_macro_expression1942 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_before_macro_expression_in_date_macro_expression1950 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_after_macro_expression_in_date_macro_expression1958 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_equals_macro_expression_in_date_macro_expression1966 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_date_today_macro_expression_in_date_macro_expression1974 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_63_in_date_between_macro_expression1986 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_date_between_macro_expression1988 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_between_macro_expression1990 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_between_macro_expression1992 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000001L}); - public static final BitSet FOLLOW_64_in_date_between_macro_expression1994 = new BitSet(new long[]{0x0040000000000000L,0x0000000000000006L}); - public static final BitSet FOLLOW_set_in_date_between_macro_expression1997 = new BitSet(new long[]{0x0000040000000000L}); - public static final BitSet FOLLOW_INT_NUMERAL_in_date_between_macro_expression2005 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_between_macro_expression2009 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000001L}); - public static final BitSet FOLLOW_64_in_date_between_macro_expression2011 = new BitSet(new long[]{0x0040000000000000L,0x0000000000000006L}); - public static final BitSet FOLLOW_set_in_date_between_macro_expression2014 = new BitSet(new long[]{0x0000040000000000L}); - public static final BitSet FOLLOW_INT_NUMERAL_in_date_between_macro_expression2022 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_between_macro_expression2026 = new BitSet(new long[]{0x0000000000000000L,0x00000000000001F8L}); - public static final BitSet FOLLOW_set_in_date_between_macro_expression2028 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_date_between_macro_expression2051 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_73_in_date_before_macro_expression2063 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_date_before_macro_expression2065 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_before_macro_expression2067 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_before_macro_expression2069 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_before_macro_expression2072 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_input_parameter_in_date_before_macro_expression2076 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_date_before_macro_expression2079 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_74_in_date_after_macro_expression2091 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_date_after_macro_expression2093 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_after_macro_expression2095 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_after_macro_expression2097 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_after_macro_expression2100 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_input_parameter_in_date_after_macro_expression2104 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_date_after_macro_expression2107 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_75_in_date_equals_macro_expression2119 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_date_equals_macro_expression2121 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_equals_macro_expression2123 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_date_equals_macro_expression2125 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_equals_macro_expression2128 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_input_parameter_in_date_equals_macro_expression2132 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_date_equals_macro_expression2135 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_76_in_date_today_macro_expression2147 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_date_today_macro_expression2149 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_date_today_macro_expression2151 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_date_today_macro_expression2153 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2165 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_62_in_between_expression2168 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_77_in_between_expression2172 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); - public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2174 = new BitSet(new long[]{0x0000000040000000L}); - public static final BitSet FOLLOW_AND_in_between_expression2176 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); - public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2178 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_expression_in_between_expression2186 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_62_in_between_expression2189 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_77_in_between_expression2193 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_expression_in_between_expression2195 = new BitSet(new long[]{0x0000000040000000L}); - public static final BitSet FOLLOW_AND_in_between_expression2197 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_expression_in_between_expression2199 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_datetime_expression_in_between_expression2207 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_62_in_between_expression2210 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_77_in_between_expression2214 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8000000000L}); - public static final BitSet FOLLOW_datetime_expression_in_between_expression2216 = new BitSet(new long[]{0x0000000040000000L}); - public static final BitSet FOLLOW_AND_in_between_expression2218 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8000000000L}); - public static final BitSet FOLLOW_datetime_expression_in_between_expression2220 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_in_expression2232 = new BitSet(new long[]{0x4400000000000000L}); - public static final BitSet FOLLOW_62_in_in_expression2235 = new BitSet(new long[]{0x0400000000000000L}); - public static final BitSet FOLLOW_58_in_in_expression2239 = new BitSet(new long[]{0x0100D0009F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_in_expression_right_part_in_in_expression2241 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_LPAREN_in_in_expression_right_part2253 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_in_item_in_in_expression_right_part2255 = new BitSet(new long[]{0x0040000100000000L}); - public static final BitSet FOLLOW_54_in_in_expression_right_part2258 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_in_item_in_in_expression_right_part2260 = new BitSet(new long[]{0x0040000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_in_expression_right_part2264 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_in_expression_right_part2272 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_literal_in_in_item2284 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_in_item2292 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_expression_in_like_expression2304 = new BitSet(new long[]{0x4000000000000000L,0x0000000000004000L}); - public static final BitSet FOLLOW_62_in_like_expression2307 = new BitSet(new long[]{0x0000000000000000L,0x0000000000004000L}); - public static final BitSet FOLLOW_78_in_like_expression2311 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); - public static final BitSet FOLLOW_pattern_value_in_like_expression2314 = new BitSet(new long[]{0x0000000000000002L,0x0000000000008000L}); - public static final BitSet FOLLOW_input_parameter_in_like_expression2318 = new BitSet(new long[]{0x0000000000000002L,0x0000000000008000L}); - public static final BitSet FOLLOW_79_in_like_expression2321 = new BitSet(new long[]{0x0000080000000000L}); - public static final BitSet FOLLOW_ESCAPE_CHARACTER_in_like_expression2323 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_null_comparison_expression2338 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); - public static final BitSet FOLLOW_input_parameter_in_null_comparison_expression2342 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); - public static final BitSet FOLLOW_80_in_null_comparison_expression2345 = new BitSet(new long[]{0x4000000000000000L,0x0000000000020000L}); - public static final BitSet FOLLOW_62_in_null_comparison_expression2348 = new BitSet(new long[]{0x0000000000000000L,0x0000000000020000L}); - public static final BitSet FOLLOW_81_in_null_comparison_expression2352 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_empty_collection_comparison_expression2364 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); - public static final BitSet FOLLOW_80_in_empty_collection_comparison_expression2366 = new BitSet(new long[]{0x4000000000000000L,0x0000000000040000L}); - public static final BitSet FOLLOW_62_in_empty_collection_comparison_expression2369 = new BitSet(new long[]{0x0000000000000000L,0x0000000000040000L}); - public static final BitSet FOLLOW_82_in_empty_collection_comparison_expression2373 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_entity_expression_in_collection_member_expression2385 = new BitSet(new long[]{0x4000000000000000L,0x0000000000080000L}); - public static final BitSet FOLLOW_62_in_collection_member_expression2388 = new BitSet(new long[]{0x0000000000000000L,0x0000000000080000L}); - public static final BitSet FOLLOW_83_in_collection_member_expression2392 = new BitSet(new long[]{0x0000400000000000L,0x0000000000100000L}); - public static final BitSet FOLLOW_84_in_collection_member_expression2395 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_collection_member_expression2399 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_62_in_exists_expression2412 = new BitSet(new long[]{0x0000000000000000L,0x0000000000200000L}); - public static final BitSet FOLLOW_85_in_exists_expression2416 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_subquery_in_exists_expression2418 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_all_or_any_expression2430 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_subquery_in_all_or_any_expression2443 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_expression_in_comparison_expression2455 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); - public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2457 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_string_expression_in_comparison_expression2460 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2464 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_boolean_expression_in_comparison_expression2473 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_comparison_expression2475 = new BitSet(new long[]{0x0100D0001F000000L,0x00D87C0001C00000L}); - public static final BitSet FOLLOW_boolean_expression_in_comparison_expression2484 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2488 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_enum_expression_in_comparison_expression2497 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_comparison_expression2499 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_enum_expression_in_comparison_expression2506 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2510 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_datetime_expression_in_comparison_expression2519 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); - public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2521 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8001C00000L}); - public static final BitSet FOLLOW_datetime_expression_in_comparison_expression2524 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2528 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_entity_expression_in_comparison_expression2537 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_comparison_expression2539 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_entity_expression_in_comparison_expression2548 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2552 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_arithmetic_expression_in_comparison_expression2561 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); - public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2563 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE01C00006L}); - public static final BitSet FOLLOW_arithmetic_expression_in_comparison_expression2566 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2570 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_comparison_operator0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_arithmetic_expression2635 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_arithmetic_expression2643 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_arithmetic_term_in_simple_arithmetic_expression2656 = new BitSet(new long[]{0x0000000000000002L,0x0000000000000006L}); - public static final BitSet FOLLOW_set_in_simple_arithmetic_expression2660 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_arithmetic_term_in_simple_arithmetic_expression2670 = new BitSet(new long[]{0x0000000000000002L,0x0000000000000006L}); - public static final BitSet FOLLOW_arithmetic_factor_in_arithmetic_term2685 = new BitSet(new long[]{0x0000000000000002L,0x0000000180000000L}); - public static final BitSet FOLLOW_set_in_arithmetic_term2689 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_arithmetic_factor_in_arithmetic_term2699 = new BitSet(new long[]{0x0000000000000002L,0x0000000180000000L}); - public static final BitSet FOLLOW_set_in_arithmetic_factor2713 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_arithmetic_primary_in_arithmetic_factor2724 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_arithmetic_primary2736 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_numeric_literal_in_arithmetic_primary2744 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_LPAREN_in_arithmetic_primary2752 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_arithmetic_primary2753 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_arithmetic_primary2754 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_arithmetic_primary2762 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_functions_returning_numerics_in_arithmetic_primary2770 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_arithmetic_primary2778 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_primary_in_string_expression2790 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_string_expression2794 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_string_primary2806 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_STRINGLITERAL_in_string_primary2814 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_string_primary2822 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_functions_returning_strings_in_string_primary2830 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_string_primary2838 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_datetime_primary_in_datetime_expression2850 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_datetime_expression2858 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_datetime_primary2870 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_datetime_primary2878 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_functions_returning_datetime_in_datetime_primary2886 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_aggregate_expression_in_datetime_primary2894 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_boolean_primary_in_boolean_expression2906 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_boolean_expression2914 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_boolean_primary2926 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_boolean_literal_in_boolean_primary2934 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_boolean_primary2942 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_enum_primary_in_enum_expression2954 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_subquery_in_enum_expression2962 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_enum_primary2974 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_enum_literal_in_enum_primary2982 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_enum_primary2990 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_path_expression_in_entity_expression3002 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_simple_entity_expression_in_entity_expression3010 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_identification_variable_in_simple_entity_expression3022 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_input_parameter_in_simple_entity_expression3030 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_97_in_functions_returning_numerics3042 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3044 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3045 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3046 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_98_in_functions_returning_numerics3054 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3056 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3057 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_numerics3058 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3060 = new BitSet(new long[]{0x0040000100000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_numerics3062 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3064 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3067 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_99_in_functions_returning_numerics3075 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3077 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3078 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3079 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_100_in_functions_returning_numerics3087 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3089 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3090 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3091 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_101_in_functions_returning_numerics3099 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3101 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3102 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_numerics3103 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3105 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3106 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_102_in_functions_returning_numerics3114 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3116 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_path_expression_in_functions_returning_numerics3117 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3118 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_functions_returning_datetime0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_106_in_functions_returning_strings3158 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3160 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3161 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_strings3162 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3164 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3165 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_107_in_functions_returning_strings3173 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3175 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3176 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_strings3177 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3178 = new BitSet(new long[]{0x0040000000000000L}); - public static final BitSet FOLLOW_54_in_functions_returning_strings3179 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); - public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3181 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3182 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_108_in_functions_returning_strings3190 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3192 = new BitSet(new long[]{0x0020F0001F000000L,0x001BFC0000000000L}); - public static final BitSet FOLLOW_trim_specification_in_functions_returning_strings3195 = new BitSet(new long[]{0x0020200000000000L}); - public static final BitSet FOLLOW_TRIM_CHARACTER_in_functions_returning_strings3200 = new BitSet(new long[]{0x0020000000000000L}); - public static final BitSet FOLLOW_53_in_functions_returning_strings3204 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3208 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3209 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_109_in_functions_returning_strings3217 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3219 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3220 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3221 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_110_in_functions_returning_strings3229 = new BitSet(new long[]{0x0000000080000000L}); - public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3231 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3232 = new BitSet(new long[]{0x0000000100000000L}); - public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3233 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_trim_specification0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_abstract_schema_name3274 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_pattern_value3287 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_114_in_numeric_literal3301 = new BitSet(new long[]{0x0000040000000000L}); - public static final BitSet FOLLOW_INT_NUMERAL_in_numeric_literal3305 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_115_in_input_parameter3318 = new BitSet(new long[]{0x0000040000000000L}); - public static final BitSet FOLLOW_INT_NUMERAL_in_input_parameter3320 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_NAMED_PARAMETER_in_input_parameter3343 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_116_in_input_parameter3364 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_WORD_in_input_parameter3366 = new BitSet(new long[]{0x0000000000000000L,0x0020000000000000L}); - public static final BitSet FOLLOW_117_in_input_parameter3368 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_literal3396 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_constructor_name3408 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_enum_literal3452 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_boolean_literal0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_set_in_field0 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_identification_variable3501 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_WORD_in_parameter_name3513 = new BitSet(new long[]{0x0200000000000002L}); - public static final BitSet FOLLOW_57_in_parameter_name3516 = new BitSet(new long[]{0x0000400000000000L}); - public static final BitSet FOLLOW_WORD_in_parameter_name3519 = new BitSet(new long[]{0x0200000000000002L}); - public static final BitSet FOLLOW_field_in_synpred20_JPA887 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_field_in_synpred23_JPA982 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_62_in_synpred57_JPA1823 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_62_in_synpred58_JPA1823 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); - public static final BitSet FOLLOW_simple_cond_expression_in_synpred58_JPA1827 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_comparison_expression_in_synpred59_JPA1866 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_between_expression_in_synpred60_JPA1874 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_like_expression_in_synpred61_JPA1882 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_in_expression_in_synpred62_JPA1890 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_null_comparison_expression_in_synpred63_JPA1898 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_empty_collection_comparison_expression_in_synpred64_JPA1906 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_collection_member_expression_in_synpred65_JPA1914 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2165 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_62_in_synpred84_JPA2168 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_77_in_synpred84_JPA2172 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); - public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2174 = new BitSet(new long[]{0x0000000040000000L}); - public static final BitSet FOLLOW_AND_in_synpred84_JPA2176 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); - public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2178 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2186 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_62_in_synpred86_JPA2189 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); - public static final BitSet FOLLOW_77_in_synpred86_JPA2193 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2195 = new BitSet(new long[]{0x0000000040000000L}); - public static final BitSet FOLLOW_AND_in_synpred86_JPA2197 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); - public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2199 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_string_expression_in_synpred104_JPA2455 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); - public static final BitSet FOLLOW_comparison_operator_in_synpred104_JPA2457 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_string_expression_in_synpred104_JPA2460 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_synpred104_JPA2464 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_boolean_expression_in_synpred107_JPA2473 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_synpred107_JPA2475 = new BitSet(new long[]{0x0100D0001F000000L,0x00D87C0001C00000L}); - public static final BitSet FOLLOW_boolean_expression_in_synpred107_JPA2484 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_synpred107_JPA2488 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_enum_expression_in_synpred110_JPA2497 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_synpred110_JPA2499 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_enum_expression_in_synpred110_JPA2506 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_synpred110_JPA2510 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_datetime_expression_in_synpred112_JPA2519 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); - public static final BitSet FOLLOW_comparison_operator_in_synpred112_JPA2521 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8001C00000L}); - public static final BitSet FOLLOW_datetime_expression_in_synpred112_JPA2524 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_synpred112_JPA2528 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_entity_expression_in_synpred115_JPA2537 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); - public static final BitSet FOLLOW_set_in_synpred115_JPA2539 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); - public static final BitSet FOLLOW_entity_expression_in_synpred115_JPA2548 = new BitSet(new long[]{0x0000000000000002L}); - public static final BitSet FOLLOW_all_or_any_expression_in_synpred115_JPA2552 = new BitSet(new long[]{0x0000000000000002L}); - - @Override - public void emitErrorMessage(String msg) { - //do nothing - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * 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. + * + */ + +// $ANTLR 3.2 Sep 23, 2009 12:02:23 JPA.g 2012-08-06 14:42:50 + +package com.haulmont.cuba.core.sys.jpql.antlr; + +import com.haulmont.cuba.core.sys.jpql.tree.*; +import org.antlr.runtime.*; +import org.antlr.runtime.tree.CommonTreeAdaptor; +import org.antlr.runtime.tree.RewriteRuleSubtreeStream; +import org.antlr.runtime.tree.RewriteRuleTokenStream; +import org.antlr.runtime.tree.TreeAdaptor; + +public class JPAParser extends Parser { + public static final String[] tokenNames = new String[] { + "", "", "", "", "T_SELECTED_ITEMS", "T_SELECTED_ITEM", "T_SOURCES", "T_SOURCE", "T_SELECTED_FIELD", "T_SELECTED_ENTITY", "T_ID_VAR", "T_JOIN_VAR", "T_COLLECTION_MEMBER", "T_QUERY", "T_CONDITION", "T_SIMPLE_CONDITION", "T_PARAMETER", "T_GROUP_BY", "T_ORDER_BY", "T_ORDER_BY_FIELD", "T_AGGREGATE_EXPR", "HAVING", "ASC", "DESC", "AVG", "MAX", "MIN", "SUM", "COUNT", "OR", "AND", "LPAREN", "RPAREN", "DISTINCT", "LEFT", "OUTER", "INNER", "JOIN", "FETCH", "ORDER", "GROUP", "BY", "INT_NUMERAL", "ESCAPE_CHARACTER", "STRINGLITERAL", "TRIM_CHARACTER", "WORD", "NAMED_PARAMETER", "RUSSIAN_SYMBOLS", "WS", "COMMENT", "LINE_COMMENT", "'SELECT'", "'FROM'", "','", "'AS'", "'(SELECT'", "'.'", "'IN'", "'OBJECT'", "'NEW'", "'WHERE'", "'NOT'", "'@BETWEEN'", "'NOW'", "'+'", "'-'", "'YEAR'", "'MONTH'", "'DAY'", "'HOUR'", "'MINUTE'", "'SECOND'", "'@DATEBEFORE'", "'@DATEAFTER'", "'@DATEEQUALS'", "'@TODAY'", "'BETWEEN'", "'LIKE'", "'ESCAPE'", "'IS'", "'NULL'", "'EMPTY'", "'MEMBER'", "'OF'", "'EXISTS'", "'ALL'", "'ANY'", "'SOME'", "'='", "'<>'", "'>'", "'>='", "'<'", "'<='", "'*'", "'/'", "'LENGTH'", "'LOCATE'", "'ABS'", "'SQRT'", "'MOD'", "'SIZE'", "'CURRENT_DATE'", "'CURRENT_TIME'", "'CURRENT_TIMESTAMP'", "'CONCAT'", "'SUBSTRING'", "'TRIM'", "'LOWER'", "'UPPER'", "'LEADING'", "'TRAILING'", "'BOTH'", "'0x'", "'?'", "'${'", "'}'", "'true'", "'false'" + }; + public static final int T_JOIN_VAR=11; + public static final int T_AGGREGATE_EXPR=20; + public static final int COUNT=28; + public static final int T_ORDER_BY=18; + public static final int EOF=-1; + public static final int WORD=46; + public static final int T__93=93; + public static final int T__94=94; + public static final int RPAREN=32; + public static final int T__91=91; + public static final int T__92=92; + public static final int T__90=90; + public static final int TRIM_CHARACTER=45; + public static final int T_SELECTED_ITEM=5; + public static final int COMMENT=50; + public static final int T__99=99; + public static final int T__98=98; + public static final int T__97=97; + public static final int T__96=96; + public static final int T_QUERY=13; + public static final int T__95=95; + public static final int T__80=80; + public static final int T__81=81; + public static final int T__82=82; + public static final int T__83=83; + public static final int ASC=22; + public static final int LINE_COMMENT=51; + public static final int T__85=85; + public static final int T__84=84; + public static final int T__87=87; + public static final int T__86=86; + public static final int T__89=89; + public static final int T__88=88; + public static final int GROUP=40; + public static final int WS=49; + public static final int T__71=71; + public static final int T__72=72; + public static final int FETCH=38; + public static final int T__70=70; + public static final int T_SELECTED_FIELD=8; + public static final int OR=29; + public static final int T__76=76; + public static final int T__75=75; + public static final int DISTINCT=33; + public static final int T__74=74; + public static final int T__73=73; + public static final int T__79=79; + public static final int T__78=78; + public static final int T__77=77; + public static final int T__68=68; + public static final int T__69=69; + public static final int T__66=66; + public static final int T__67=67; + public static final int T_SELECTED_ITEMS=4; + public static final int T__64=64; + public static final int T__65=65; + public static final int INNER=36; + public static final int T__62=62; + public static final int T__63=63; + public static final int ORDER=39; + public static final int T__118=118; + public static final int T_SOURCE=7; + public static final int T__119=119; + public static final int T__116=116; + public static final int T_ID_VAR=10; + public static final int T__117=117; + public static final int T_SIMPLE_CONDITION=15; + public static final int T__114=114; + public static final int T__115=115; + public static final int MAX=25; + public static final int AND=30; + public static final int SUM=27; + public static final int T__61=61; + public static final int T__60=60; + public static final int RUSSIAN_SYMBOLS=48; + public static final int LPAREN=31; + public static final int T__55=55; + public static final int T__56=56; + public static final int T__57=57; + public static final int T__58=58; + public static final int T__52=52; + public static final int T__53=53; + public static final int T__54=54; + public static final int T__107=107; + public static final int T__108=108; + public static final int T__109=109; + public static final int LEFT=34; + public static final int AVG=24; + public static final int T_ORDER_BY_FIELD=19; + public static final int T__59=59; + public static final int T__103=103; + public static final int T__104=104; + public static final int T__105=105; + public static final int T__106=106; + public static final int T__111=111; + public static final int T__110=110; + public static final int T__113=113; + public static final int T__112=112; + public static final int T_GROUP_BY=17; + public static final int OUTER=35; + public static final int BY=41; + public static final int T_CONDITION=14; + public static final int T_SELECTED_ENTITY=9; + public static final int T__102=102; + public static final int HAVING=21; + public static final int T__101=101; + public static final int MIN=26; + public static final int T__100=100; + public static final int T_PARAMETER=16; + public static final int JOIN=37; + public static final int NAMED_PARAMETER=47; + public static final int ESCAPE_CHARACTER=43; + public static final int INT_NUMERAL=42; + public static final int STRINGLITERAL=44; + public static final int T_COLLECTION_MEMBER=12; + public static final int DESC=23; + public static final int T_SOURCES=6; + + // delegates + // delegators + + + public JPAParser(TokenStream input) { + this(input, new RecognizerSharedState()); + } + public JPAParser(TokenStream input, RecognizerSharedState state) { + super(input, state); + + } + + protected TreeAdaptor adaptor = new CommonTreeAdaptor(); + + public void setTreeAdaptor(TreeAdaptor adaptor) { + this.adaptor = adaptor; + } + public TreeAdaptor getTreeAdaptor() { + return adaptor; + } + + public String[] getTokenNames() { return JPAParser.tokenNames; } + public String getGrammarFileName() { return "JPA.g"; } + + + public static class ql_statement_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "ql_statement" + // JPA.g:85:1: ql_statement : select_statement ; + public final JPAParser.ql_statement_return ql_statement() throws RecognitionException { + JPAParser.ql_statement_return retval = new JPAParser.ql_statement_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.select_statement_return select_statement1 = null; + + + + try { + // JPA.g:86:5: ( select_statement ) + // JPA.g:86:7: select_statement + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_select_statement_in_ql_statement426); + select_statement1=select_statement(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, select_statement1.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "ql_statement" + + public static class select_statement_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "select_statement" + // JPA.g:88:1: select_statement : sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ; + public final JPAParser.select_statement_return select_statement() throws RecognitionException { + JPAParser.select_statement_return retval = new JPAParser.select_statement_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token sl=null; + JPAParser.select_clause_return select_clause2 = null; + + JPAParser.from_clause_return from_clause3 = null; + + JPAParser.where_clause_return where_clause4 = null; + + JPAParser.groupby_clause_return groupby_clause5 = null; + + JPAParser.having_clause_return having_clause6 = null; + + JPAParser.orderby_clause_return orderby_clause7 = null; + + + Object sl_tree=null; + RewriteRuleTokenStream stream_52=new RewriteRuleTokenStream(adaptor,"token 52"); + RewriteRuleSubtreeStream stream_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule select_clause"); + RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); + RewriteRuleSubtreeStream stream_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule from_clause"); + RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); + RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); + RewriteRuleSubtreeStream stream_orderby_clause=new RewriteRuleSubtreeStream(adaptor,"rule orderby_clause"); + try { + // JPA.g:89:5: (sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ) + // JPA.g:89:8: sl= 'SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? + { + sl=(Token)match(input,52,FOLLOW_52_in_select_statement441); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_52.add(sl); + + pushFollow(FOLLOW_select_clause_in_select_statement443); + select_clause2=select_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_select_clause.add(select_clause2.getTree()); + pushFollow(FOLLOW_from_clause_in_select_statement445); + from_clause3=from_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_from_clause.add(from_clause3.getTree()); + // JPA.g:89:46: ( where_clause )? + int alt1=2; + int LA1_0 = input.LA(1); + + if ( (LA1_0==61) ) { + alt1=1; + } + switch (alt1) { + case 1 : + // JPA.g:89:47: where_clause + { + pushFollow(FOLLOW_where_clause_in_select_statement448); + where_clause4=where_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_where_clause.add(where_clause4.getTree()); + + } + break; + + } + + // JPA.g:89:62: ( groupby_clause )? + int alt2=2; + int LA2_0 = input.LA(1); + + if ( (LA2_0==GROUP) ) { + alt2=1; + } + switch (alt2) { + case 1 : + // JPA.g:89:63: groupby_clause + { + pushFollow(FOLLOW_groupby_clause_in_select_statement453); + groupby_clause5=groupby_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause5.getTree()); + + } + break; + + } + + // JPA.g:89:80: ( having_clause )? + int alt3=2; + int LA3_0 = input.LA(1); + + if ( (LA3_0==HAVING) ) { + alt3=1; + } + switch (alt3) { + case 1 : + // JPA.g:89:81: having_clause + { + pushFollow(FOLLOW_having_clause_in_select_statement458); + having_clause6=having_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_having_clause.add(having_clause6.getTree()); + + } + break; + + } + + // JPA.g:89:96: ( orderby_clause )? + int alt4=2; + int LA4_0 = input.LA(1); + + if ( (LA4_0==ORDER) ) { + alt4=1; + } + switch (alt4) { + case 1 : + // JPA.g:89:97: orderby_clause + { + pushFollow(FOLLOW_orderby_clause_in_select_statement462); + orderby_clause7=orderby_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_orderby_clause.add(orderby_clause7.getTree()); + + } + break; + + } + + + + // AST REWRITE + // elements: orderby_clause, having_clause, groupby_clause, select_clause, from_clause, where_clause + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 90:6: -> ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) + { + // JPA.g:90:9: ^( T_QUERY[$sl] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, sl), root_1); + + // JPA.g:90:35: ( select_clause )? + if ( stream_select_clause.hasNext() ) { + adaptor.addChild(root_1, stream_select_clause.nextTree()); + + } + stream_select_clause.reset(); + adaptor.addChild(root_1, stream_from_clause.nextTree()); + // JPA.g:90:64: ( where_clause )? + if ( stream_where_clause.hasNext() ) { + adaptor.addChild(root_1, stream_where_clause.nextTree()); + + } + stream_where_clause.reset(); + // JPA.g:90:80: ( groupby_clause )? + if ( stream_groupby_clause.hasNext() ) { + adaptor.addChild(root_1, stream_groupby_clause.nextTree()); + + } + stream_groupby_clause.reset(); + // JPA.g:90:98: ( having_clause )? + if ( stream_having_clause.hasNext() ) { + adaptor.addChild(root_1, stream_having_clause.nextTree()); + + } + stream_having_clause.reset(); + // JPA.g:90:115: ( orderby_clause )? + if ( stream_orderby_clause.hasNext() ) { + adaptor.addChild(root_1, stream_orderby_clause.nextTree()); + + } + stream_orderby_clause.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "select_statement" + + public static class from_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "from_clause" + // JPA.g:92:1: from_clause : fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) ; + public final JPAParser.from_clause_return from_clause() throws RecognitionException { + JPAParser.from_clause_return retval = new JPAParser.from_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token fr=null; + Token char_literal9=null; + JPAParser.identification_variable_declaration_return identification_variable_declaration8 = null; + + JPAParser.identification_variable_or_collection_declaration_return identification_variable_or_collection_declaration10 = null; + + + Object fr_tree=null; + Object char_literal9_tree=null; + RewriteRuleTokenStream stream_53=new RewriteRuleTokenStream(adaptor,"token 53"); + RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); + RewriteRuleSubtreeStream stream_identification_variable_or_collection_declaration=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable_or_collection_declaration"); + RewriteRuleSubtreeStream stream_identification_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable_declaration"); + try { + // JPA.g:93:5: (fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) ) + // JPA.g:93:7: fr= 'FROM' identification_variable_declaration ( ',' identification_variable_or_collection_declaration )* + { + fr=(Token)match(input,53,FOLLOW_53_in_from_clause523); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_53.add(fr); + + pushFollow(FOLLOW_identification_variable_declaration_in_from_clause525); + identification_variable_declaration8=identification_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable_declaration.add(identification_variable_declaration8.getTree()); + // JPA.g:93:53: ( ',' identification_variable_or_collection_declaration )* + loop5: + do { + int alt5=2; + int LA5_0 = input.LA(1); + + if ( (LA5_0==54) ) { + alt5=1; + } + + + switch (alt5) { + case 1 : + // JPA.g:93:54: ',' identification_variable_or_collection_declaration + { + char_literal9=(Token)match(input,54,FOLLOW_54_in_from_clause528); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_54.add(char_literal9); + + pushFollow(FOLLOW_identification_variable_or_collection_declaration_in_from_clause530); + identification_variable_or_collection_declaration10=identification_variable_or_collection_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable_or_collection_declaration.add(identification_variable_or_collection_declaration10.getTree()); + + } + break; + + default : + break loop5; + } + } while (true); + + + + // AST REWRITE + // elements: identification_variable_or_collection_declaration, identification_variable_declaration + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 94:5: -> ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) + { + // JPA.g:94:8: ^( T_SOURCES[$fr] identification_variable_declaration ( identification_variable_or_collection_declaration )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new FromNode(T_SOURCES, fr), root_1); + + adaptor.addChild(root_1, stream_identification_variable_declaration.nextTree()); + // JPA.g:94:71: ( identification_variable_or_collection_declaration )* + while ( stream_identification_variable_or_collection_declaration.hasNext() ) { + adaptor.addChild(root_1, stream_identification_variable_or_collection_declaration.nextTree()); + + } + stream_identification_variable_or_collection_declaration.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "from_clause" + + public static class identification_variable_or_collection_declaration_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "identification_variable_or_collection_declaration" + // JPA.g:96:1: identification_variable_or_collection_declaration : ( identification_variable_declaration | collection_member_declaration -> ^( T_SOURCE collection_member_declaration ) ); + public final JPAParser.identification_variable_or_collection_declaration_return identification_variable_or_collection_declaration() throws RecognitionException { + JPAParser.identification_variable_or_collection_declaration_return retval = new JPAParser.identification_variable_or_collection_declaration_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.identification_variable_declaration_return identification_variable_declaration11 = null; + + JPAParser.collection_member_declaration_return collection_member_declaration12 = null; + + + RewriteRuleSubtreeStream stream_collection_member_declaration=new RewriteRuleSubtreeStream(adaptor,"rule collection_member_declaration"); + try { + // JPA.g:97:5: ( identification_variable_declaration | collection_member_declaration -> ^( T_SOURCE collection_member_declaration ) ) + int alt6=2; + int LA6_0 = input.LA(1); + + if ( (LA6_0==WORD||LA6_0==56) ) { + alt6=1; + } + else if ( (LA6_0==58) ) { + alt6=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 6, 0, input); + + throw nvae; + } + switch (alt6) { + case 1 : + // JPA.g:97:7: identification_variable_declaration + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_identification_variable_declaration_in_identification_variable_or_collection_declaration563); + identification_variable_declaration11=identification_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable_declaration11.getTree()); + + } + break; + case 2 : + // JPA.g:98:7: collection_member_declaration + { + pushFollow(FOLLOW_collection_member_declaration_in_identification_variable_or_collection_declaration571); + collection_member_declaration12=collection_member_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_collection_member_declaration.add(collection_member_declaration12.getTree()); + + + // AST REWRITE + // elements: collection_member_declaration + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 98:37: -> ^( T_SOURCE collection_member_declaration ) + { + // JPA.g:98:40: ^( T_SOURCE collection_member_declaration ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_1); + + adaptor.addChild(root_1, stream_collection_member_declaration.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "identification_variable_or_collection_declaration" + + public static class identification_variable_declaration_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "identification_variable_declaration" + // JPA.g:100:1: identification_variable_declaration : range_variable_declaration ( joined_clause )* -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) ; + public final JPAParser.identification_variable_declaration_return identification_variable_declaration() throws RecognitionException { + JPAParser.identification_variable_declaration_return retval = new JPAParser.identification_variable_declaration_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.range_variable_declaration_return range_variable_declaration13 = null; + + JPAParser.joined_clause_return joined_clause14 = null; + + + RewriteRuleSubtreeStream stream_joined_clause=new RewriteRuleSubtreeStream(adaptor,"rule joined_clause"); + RewriteRuleSubtreeStream stream_range_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule range_variable_declaration"); + try { + // JPA.g:101:5: ( range_variable_declaration ( joined_clause )* -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) ) + // JPA.g:101:7: range_variable_declaration ( joined_clause )* + { + pushFollow(FOLLOW_range_variable_declaration_in_identification_variable_declaration594); + range_variable_declaration13=range_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_range_variable_declaration.add(range_variable_declaration13.getTree()); + // JPA.g:101:34: ( joined_clause )* + loop7: + do { + int alt7=2; + int LA7_0 = input.LA(1); + + if ( (LA7_0==LEFT||(LA7_0>=INNER && LA7_0<=JOIN)) ) { + alt7=1; + } + + + switch (alt7) { + case 1 : + // JPA.g:0:0: joined_clause + { + pushFollow(FOLLOW_joined_clause_in_identification_variable_declaration596); + joined_clause14=joined_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_joined_clause.add(joined_clause14.getTree()); + + } + break; + + default : + break loop7; + } + } while (true); + + + + // AST REWRITE + // elements: joined_clause, range_variable_declaration + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 102:5: -> ^( T_SOURCE range_variable_declaration ( joined_clause )* ) + { + // JPA.g:102:8: ^( T_SOURCE range_variable_declaration ( joined_clause )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_1); + + adaptor.addChild(root_1, stream_range_variable_declaration.nextTree()); + // JPA.g:102:67: ( joined_clause )* + while ( stream_joined_clause.hasNext() ) { + adaptor.addChild(root_1, stream_joined_clause.nextTree()); + + } + stream_joined_clause.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "identification_variable_declaration" + + public static class joined_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "joined_clause" + // JPA.g:104:1: joined_clause : ( join | fetch_join ); + public final JPAParser.joined_clause_return joined_clause() throws RecognitionException { + JPAParser.joined_clause_return retval = new JPAParser.joined_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.join_return join15 = null; + + JPAParser.fetch_join_return fetch_join16 = null; + + + + try { + // JPA.g:105:5: ( join | fetch_join ) + int alt8=2; + switch ( input.LA(1) ) { + case LEFT: + { + int LA8_1 = input.LA(2); + + if ( (LA8_1==OUTER) ) { + int LA8_4 = input.LA(3); + + if ( (LA8_4==JOIN) ) { + int LA8_3 = input.LA(4); + + if ( (LA8_3==FETCH) ) { + alt8=2; + } + else if ( (LA8_3==WORD) ) { + alt8=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 3, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 4, input); + + throw nvae; + } + } + else if ( (LA8_1==JOIN) ) { + int LA8_3 = input.LA(3); + + if ( (LA8_3==FETCH) ) { + alt8=2; + } + else if ( (LA8_3==WORD) ) { + alt8=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 3, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 1, input); + + throw nvae; + } + } + break; + case INNER: + { + int LA8_2 = input.LA(2); + + if ( (LA8_2==JOIN) ) { + int LA8_3 = input.LA(3); + + if ( (LA8_3==FETCH) ) { + alt8=2; + } + else if ( (LA8_3==WORD) ) { + alt8=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 3, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 2, input); + + throw nvae; + } + } + break; + case JOIN: + { + int LA8_3 = input.LA(2); + + if ( (LA8_3==FETCH) ) { + alt8=2; + } + else if ( (LA8_3==WORD) ) { + alt8=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 3, input); + + throw nvae; + } + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 8, 0, input); + + throw nvae; + } + + switch (alt8) { + case 1 : + // JPA.g:105:7: join + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_join_in_joined_clause627); + join15=join(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, join15.getTree()); + + } + break; + case 2 : + // JPA.g:105:14: fetch_join + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_fetch_join_in_joined_clause631); + fetch_join16=fetch_join(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, fetch_join16.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "joined_clause" + + public static class range_variable_declaration_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "range_variable_declaration" + // JPA.g:107:1: range_variable_declaration : range_variable_declaration_source ( 'AS' )? identification_variable -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) ; + public final JPAParser.range_variable_declaration_return range_variable_declaration() throws RecognitionException { + JPAParser.range_variable_declaration_return retval = new JPAParser.range_variable_declaration_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal18=null; + JPAParser.range_variable_declaration_source_return range_variable_declaration_source17 = null; + + JPAParser.identification_variable_return identification_variable19 = null; + + + Object string_literal18_tree=null; + RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_range_variable_declaration_source=new RewriteRuleSubtreeStream(adaptor,"rule range_variable_declaration_source"); + try { + // JPA.g:108:5: ( range_variable_declaration_source ( 'AS' )? identification_variable -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) ) + // JPA.g:108:7: range_variable_declaration_source ( 'AS' )? identification_variable + { + pushFollow(FOLLOW_range_variable_declaration_source_in_range_variable_declaration643); + range_variable_declaration_source17=range_variable_declaration_source(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_range_variable_declaration_source.add(range_variable_declaration_source17.getTree()); + // JPA.g:108:41: ( 'AS' )? + int alt9=2; + int LA9_0 = input.LA(1); + + if ( (LA9_0==55) ) { + alt9=1; + } + switch (alt9) { + case 1 : + // JPA.g:108:42: 'AS' + { + string_literal18=(Token)match(input,55,FOLLOW_55_in_range_variable_declaration646); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_55.add(string_literal18); + + + } + break; + + } + + pushFollow(FOLLOW_identification_variable_in_range_variable_declaration650); + identification_variable19=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable19.getTree()); + + + // AST REWRITE + // elements: range_variable_declaration_source + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 109:7: -> ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) + { + // JPA.g:109:10: ^( T_ID_VAR[$identification_variable.text] range_variable_declaration_source ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new IdentificationVariableNode(T_ID_VAR, (identification_variable19!=null?input.toString(identification_variable19.start,identification_variable19.stop):null)), root_1); + + adaptor.addChild(root_1, stream_range_variable_declaration_source.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "range_variable_declaration" + + public static class range_variable_declaration_source_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "range_variable_declaration_source" + // JPA.g:112:1: range_variable_declaration_source : ( abstract_schema_name | lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ); + public final JPAParser.range_variable_declaration_source_return range_variable_declaration_source() throws RecognitionException { + JPAParser.range_variable_declaration_source_return retval = new JPAParser.range_variable_declaration_source_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token lp=null; + Token rp=null; + JPAParser.abstract_schema_name_return abstract_schema_name20 = null; + + JPAParser.select_clause_return select_clause21 = null; + + JPAParser.from_clause_return from_clause22 = null; + + JPAParser.where_clause_return where_clause23 = null; + + JPAParser.groupby_clause_return groupby_clause24 = null; + + JPAParser.having_clause_return having_clause25 = null; + + JPAParser.orderby_clause_return orderby_clause26 = null; + + + Object lp_tree=null; + Object rp_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_56=new RewriteRuleTokenStream(adaptor,"token 56"); + RewriteRuleSubtreeStream stream_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule select_clause"); + RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); + RewriteRuleSubtreeStream stream_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule from_clause"); + RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); + RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); + RewriteRuleSubtreeStream stream_orderby_clause=new RewriteRuleSubtreeStream(adaptor,"rule orderby_clause"); + try { + // JPA.g:113:5: ( abstract_schema_name | lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) ) + int alt14=2; + int LA14_0 = input.LA(1); + + if ( (LA14_0==WORD) ) { + alt14=1; + } + else if ( (LA14_0==56) ) { + alt14=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 14, 0, input); + + throw nvae; + } + switch (alt14) { + case 1 : + // JPA.g:113:7: abstract_schema_name + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_abstract_schema_name_in_range_variable_declaration_source686); + abstract_schema_name20=abstract_schema_name(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, abstract_schema_name20.getTree()); + + } + break; + case 2 : + // JPA.g:114:7: lp= '(SELECT' select_clause from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? rp= ')' + { + lp=(Token)match(input,56,FOLLOW_56_in_range_variable_declaration_source696); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_56.add(lp); + + pushFollow(FOLLOW_select_clause_in_range_variable_declaration_source698); + select_clause21=select_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_select_clause.add(select_clause21.getTree()); + pushFollow(FOLLOW_from_clause_in_range_variable_declaration_source700); + from_clause22=from_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_from_clause.add(from_clause22.getTree()); + // JPA.g:114:46: ( where_clause )? + int alt10=2; + int LA10_0 = input.LA(1); + + if ( (LA10_0==61) ) { + alt10=1; + } + switch (alt10) { + case 1 : + // JPA.g:114:47: where_clause + { + pushFollow(FOLLOW_where_clause_in_range_variable_declaration_source703); + where_clause23=where_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_where_clause.add(where_clause23.getTree()); + + } + break; + + } + + // JPA.g:114:62: ( groupby_clause )? + int alt11=2; + int LA11_0 = input.LA(1); + + if ( (LA11_0==GROUP) ) { + alt11=1; + } + switch (alt11) { + case 1 : + // JPA.g:114:63: groupby_clause + { + pushFollow(FOLLOW_groupby_clause_in_range_variable_declaration_source708); + groupby_clause24=groupby_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause24.getTree()); + + } + break; + + } + + // JPA.g:114:80: ( having_clause )? + int alt12=2; + int LA12_0 = input.LA(1); + + if ( (LA12_0==HAVING) ) { + alt12=1; + } + switch (alt12) { + case 1 : + // JPA.g:114:81: having_clause + { + pushFollow(FOLLOW_having_clause_in_range_variable_declaration_source713); + having_clause25=having_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_having_clause.add(having_clause25.getTree()); + + } + break; + + } + + // JPA.g:114:96: ( orderby_clause )? + int alt13=2; + int LA13_0 = input.LA(1); + + if ( (LA13_0==ORDER) ) { + alt13=1; + } + switch (alt13) { + case 1 : + // JPA.g:114:97: orderby_clause + { + pushFollow(FOLLOW_orderby_clause_in_range_variable_declaration_source717); + orderby_clause26=orderby_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_orderby_clause.add(orderby_clause26.getTree()); + + } + break; + + } + + rp=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_range_variable_declaration_source723); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(rp); + + + + // AST REWRITE + // elements: select_clause, having_clause, groupby_clause, from_clause, where_clause, orderby_clause + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 115:6: -> ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) + { + // JPA.g:115:9: ^( T_QUERY[$lp, $rp] ( select_clause )? from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ( orderby_clause )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, lp, rp), root_1); + + // JPA.g:115:40: ( select_clause )? + if ( stream_select_clause.hasNext() ) { + adaptor.addChild(root_1, stream_select_clause.nextTree()); + + } + stream_select_clause.reset(); + adaptor.addChild(root_1, stream_from_clause.nextTree()); + // JPA.g:115:69: ( where_clause )? + if ( stream_where_clause.hasNext() ) { + adaptor.addChild(root_1, stream_where_clause.nextTree()); + + } + stream_where_clause.reset(); + // JPA.g:115:85: ( groupby_clause )? + if ( stream_groupby_clause.hasNext() ) { + adaptor.addChild(root_1, stream_groupby_clause.nextTree()); + + } + stream_groupby_clause.reset(); + // JPA.g:115:103: ( having_clause )? + if ( stream_having_clause.hasNext() ) { + adaptor.addChild(root_1, stream_having_clause.nextTree()); + + } + stream_having_clause.reset(); + // JPA.g:115:120: ( orderby_clause )? + if ( stream_orderby_clause.hasNext() ) { + adaptor.addChild(root_1, stream_orderby_clause.nextTree()); + + } + stream_orderby_clause.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "range_variable_declaration_source" + + public static class join_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "join" + // JPA.g:118:1: join : join_spec join_association_path_expression ( 'AS' )? identification_variable -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) ; + public final JPAParser.join_return join() throws RecognitionException { + JPAParser.join_return retval = new JPAParser.join_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal29=null; + JPAParser.join_spec_return join_spec27 = null; + + JPAParser.join_association_path_expression_return join_association_path_expression28 = null; + + JPAParser.identification_variable_return identification_variable30 = null; + + + Object string_literal29_tree=null; + RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_join_association_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule join_association_path_expression"); + RewriteRuleSubtreeStream stream_join_spec=new RewriteRuleSubtreeStream(adaptor,"rule join_spec"); + try { + // JPA.g:119:5: ( join_spec join_association_path_expression ( 'AS' )? identification_variable -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) ) + // JPA.g:119:7: join_spec join_association_path_expression ( 'AS' )? identification_variable + { + pushFollow(FOLLOW_join_spec_in_join786); + join_spec27=join_spec(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_join_spec.add(join_spec27.getTree()); + pushFollow(FOLLOW_join_association_path_expression_in_join788); + join_association_path_expression28=join_association_path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_join_association_path_expression.add(join_association_path_expression28.getTree()); + // JPA.g:119:50: ( 'AS' )? + int alt15=2; + int LA15_0 = input.LA(1); + + if ( (LA15_0==55) ) { + alt15=1; + } + switch (alt15) { + case 1 : + // JPA.g:119:51: 'AS' + { + string_literal29=(Token)match(input,55,FOLLOW_55_in_join791); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_55.add(string_literal29); + + + } + break; + + } + + pushFollow(FOLLOW_identification_variable_in_join795); + identification_variable30=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable30.getTree()); + + + // AST REWRITE + // elements: join_association_path_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 120:7: -> ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) + { + // JPA.g:120:10: ^( T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new JoinVariableNode(T_JOIN_VAR, (join_spec27!=null?input.toString(join_spec27.start,join_spec27.stop):null), (identification_variable30!=null?input.toString(identification_variable30.start,identification_variable30.stop):null)), root_1); + + adaptor.addChild(root_1, stream_join_association_path_expression.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "join" + + public static class fetch_join_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "fetch_join" + // JPA.g:123:1: fetch_join : join_spec 'FETCH' join_association_path_expression ; + public final JPAParser.fetch_join_return fetch_join() throws RecognitionException { + JPAParser.fetch_join_return retval = new JPAParser.fetch_join_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal32=null; + JPAParser.join_spec_return join_spec31 = null; + + JPAParser.join_association_path_expression_return join_association_path_expression33 = null; + + + Object string_literal32_tree=null; + + try { + // JPA.g:124:5: ( join_spec 'FETCH' join_association_path_expression ) + // JPA.g:124:7: join_spec 'FETCH' join_association_path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_join_spec_in_fetch_join833); + join_spec31=join_spec(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, join_spec31.getTree()); + string_literal32=(Token)match(input,FETCH,FOLLOW_FETCH_in_fetch_join835); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal32_tree = (Object)adaptor.create(string_literal32); + adaptor.addChild(root_0, string_literal32_tree); + } + pushFollow(FOLLOW_join_association_path_expression_in_fetch_join837); + join_association_path_expression33=join_association_path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, join_association_path_expression33.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "fetch_join" + + public static class join_spec_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "join_spec" + // JPA.g:126:1: join_spec : ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' ; + public final JPAParser.join_spec_return join_spec() throws RecognitionException { + JPAParser.join_spec_return retval = new JPAParser.join_spec_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal34=null; + Token string_literal35=null; + Token string_literal36=null; + Token string_literal37=null; + + Object string_literal34_tree=null; + Object string_literal35_tree=null; + Object string_literal36_tree=null; + Object string_literal37_tree=null; + + try { + // JPA.g:127:5: ( ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' ) + // JPA.g:127:6: ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? 'JOIN' + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:127:6: ( ( 'LEFT' ) ( 'OUTER' )? | 'INNER' )? + int alt17=3; + int LA17_0 = input.LA(1); + + if ( (LA17_0==LEFT) ) { + alt17=1; + } + else if ( (LA17_0==INNER) ) { + alt17=2; + } + switch (alt17) { + case 1 : + // JPA.g:127:7: ( 'LEFT' ) ( 'OUTER' )? + { + // JPA.g:127:7: ( 'LEFT' ) + // JPA.g:127:8: 'LEFT' + { + string_literal34=(Token)match(input,LEFT,FOLLOW_LEFT_in_join_spec850); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal34_tree = (Object)adaptor.create(string_literal34); + adaptor.addChild(root_0, string_literal34_tree); + } + + } + + // JPA.g:127:16: ( 'OUTER' )? + int alt16=2; + int LA16_0 = input.LA(1); + + if ( (LA16_0==OUTER) ) { + alt16=1; + } + switch (alt16) { + case 1 : + // JPA.g:127:17: 'OUTER' + { + string_literal35=(Token)match(input,OUTER,FOLLOW_OUTER_in_join_spec854); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal35_tree = (Object)adaptor.create(string_literal35); + adaptor.addChild(root_0, string_literal35_tree); + } + + } + break; + + } + + + } + break; + case 2 : + // JPA.g:127:29: 'INNER' + { + string_literal36=(Token)match(input,INNER,FOLLOW_INNER_in_join_spec860); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal36_tree = (Object)adaptor.create(string_literal36); + adaptor.addChild(root_0, string_literal36_tree); + } + + } + break; + + } + + string_literal37=(Token)match(input,JOIN,FOLLOW_JOIN_in_join_spec865); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal37_tree = (Object)adaptor.create(string_literal37); + adaptor.addChild(root_0, string_literal37_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "join_spec" + + public static class join_association_path_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "join_association_path_expression" + // JPA.g:129:1: join_association_path_expression : identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ; + public final JPAParser.join_association_path_expression_return join_association_path_expression() throws RecognitionException { + JPAParser.join_association_path_expression_return retval = new JPAParser.join_association_path_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal39=null; + Token char_literal41=null; + JPAParser.identification_variable_return identification_variable38 = null; + + JPAParser.field_return field40 = null; + + JPAParser.field_return field42 = null; + + + Object char_literal39_tree=null; + Object char_literal41_tree=null; + RewriteRuleTokenStream stream_57=new RewriteRuleTokenStream(adaptor,"token 57"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_field=new RewriteRuleSubtreeStream(adaptor,"rule field"); + try { + // JPA.g:130:5: ( identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ) + // JPA.g:130:7: identification_variable '.' ( field '.' )* ( field )? + { + pushFollow(FOLLOW_identification_variable_in_join_association_path_expression877); + identification_variable38=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable38.getTree()); + char_literal39=(Token)match(input,57,FOLLOW_57_in_join_association_path_expression879); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_57.add(char_literal39); + + // JPA.g:130:35: ( field '.' )* + loop18: + do { + int alt18=2; + int LA18_0 = input.LA(1); + + if ( (LA18_0==WORD) ) { + int LA18_1 = input.LA(2); + + if ( (LA18_1==57) ) { + alt18=1; + } + + + } + else if ( (LA18_0==GROUP) ) { + int LA18_3 = input.LA(2); + + if ( (LA18_3==57) ) { + alt18=1; + } + + + } + + + switch (alt18) { + case 1 : + // JPA.g:130:36: field '.' + { + pushFollow(FOLLOW_field_in_join_association_path_expression882); + field40=field(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_field.add(field40.getTree()); + char_literal41=(Token)match(input,57,FOLLOW_57_in_join_association_path_expression883); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_57.add(char_literal41); + + + } + break; + + default : + break loop18; + } + } while (true); + + // JPA.g:130:47: ( field )? + int alt19=2; + int LA19_0 = input.LA(1); + + if ( (LA19_0==WORD) ) { + int LA19_1 = input.LA(2); + + if ( (synpred20_JPA()) ) { + alt19=1; + } + } + else if ( (LA19_0==GROUP) ) { + int LA19_3 = input.LA(2); + + if ( (LA19_3==EOF||LA19_3==HAVING||LA19_3==RPAREN||LA19_3==LEFT||(LA19_3>=INNER && LA19_3<=JOIN)||(LA19_3>=ORDER && LA19_3<=GROUP)||LA19_3==WORD||(LA19_3>=54 && LA19_3<=55)||LA19_3==61) ) { + alt19=1; + } + } + switch (alt19) { + case 1 : + // JPA.g:0:0: field + { + pushFollow(FOLLOW_field_in_join_association_path_expression887); + field42=field(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_field.add(field42.getTree()); + + } + break; + + } + + + + // AST REWRITE + // elements: field + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 131:5: -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) + { + // JPA.g:131:8: ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_FIELD, (identification_variable38!=null?input.toString(identification_variable38.start,identification_variable38.stop):null)), root_1); + + // JPA.g:131:68: ( field )* + while ( stream_field.hasNext() ) { + adaptor.addChild(root_1, stream_field.nextTree()); + + } + stream_field.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "join_association_path_expression" + + public static class collection_member_declaration_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "collection_member_declaration" + // JPA.g:134:1: collection_member_declaration : 'IN' '(' path_expression ')' ( 'AS' )? identification_variable -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) ; + public final JPAParser.collection_member_declaration_return collection_member_declaration() throws RecognitionException { + JPAParser.collection_member_declaration_return retval = new JPAParser.collection_member_declaration_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal43=null; + Token char_literal44=null; + Token char_literal46=null; + Token string_literal47=null; + JPAParser.path_expression_return path_expression45 = null; + + JPAParser.identification_variable_return identification_variable48 = null; + + + Object string_literal43_tree=null; + Object char_literal44_tree=null; + Object char_literal46_tree=null; + Object string_literal47_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_58=new RewriteRuleTokenStream(adaptor,"token 58"); + RewriteRuleTokenStream stream_55=new RewriteRuleTokenStream(adaptor,"token 55"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); + try { + // JPA.g:135:5: ( 'IN' '(' path_expression ')' ( 'AS' )? identification_variable -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) ) + // JPA.g:135:7: 'IN' '(' path_expression ')' ( 'AS' )? identification_variable + { + string_literal43=(Token)match(input,58,FOLLOW_58_in_collection_member_declaration924); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_58.add(string_literal43); + + char_literal44=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_collection_member_declaration925); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(char_literal44); + + pushFollow(FOLLOW_path_expression_in_collection_member_declaration927); + path_expression45=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_path_expression.add(path_expression45.getTree()); + char_literal46=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_collection_member_declaration929); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(char_literal46); + + // JPA.g:135:35: ( 'AS' )? + int alt20=2; + int LA20_0 = input.LA(1); + + if ( (LA20_0==55) ) { + alt20=1; + } + switch (alt20) { + case 1 : + // JPA.g:135:36: 'AS' + { + string_literal47=(Token)match(input,55,FOLLOW_55_in_collection_member_declaration932); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_55.add(string_literal47); + + + } + break; + + } + + pushFollow(FOLLOW_identification_variable_in_collection_member_declaration936); + identification_variable48=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable48.getTree()); + + + // AST REWRITE + // elements: path_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 136:5: -> ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) + { + // JPA.g:136:8: ^( T_COLLECTION_MEMBER[$identification_variable.text] path_expression ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new CollectionMemberNode(T_COLLECTION_MEMBER, (identification_variable48!=null?input.toString(identification_variable48.start,identification_variable48.stop):null)), root_1); + + adaptor.addChild(root_1, stream_path_expression.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "collection_member_declaration" + + public static class path_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "path_expression" + // JPA.g:139:1: path_expression : identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ; + public final JPAParser.path_expression_return path_expression() throws RecognitionException { + JPAParser.path_expression_return retval = new JPAParser.path_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal50=null; + Token char_literal52=null; + JPAParser.identification_variable_return identification_variable49 = null; + + JPAParser.field_return field51 = null; + + JPAParser.field_return field53 = null; + + + Object char_literal50_tree=null; + Object char_literal52_tree=null; + RewriteRuleTokenStream stream_57=new RewriteRuleTokenStream(adaptor,"token 57"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_field=new RewriteRuleSubtreeStream(adaptor,"rule field"); + try { + // JPA.g:140:5: ( identification_variable '.' ( field '.' )* ( field )? -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) ) + // JPA.g:140:8: identification_variable '.' ( field '.' )* ( field )? + { + pushFollow(FOLLOW_identification_variable_in_path_expression971); + identification_variable49=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable49.getTree()); + char_literal50=(Token)match(input,57,FOLLOW_57_in_path_expression973); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_57.add(char_literal50); + + // JPA.g:140:36: ( field '.' )* + loop21: + do { + int alt21=2; + int LA21_0 = input.LA(1); + + if ( (LA21_0==GROUP) ) { + int LA21_1 = input.LA(2); + + if ( (LA21_1==57) ) { + alt21=1; + } + + + } + else if ( (LA21_0==WORD) ) { + int LA21_3 = input.LA(2); + + if ( (LA21_3==57) ) { + alt21=1; + } + + + } + + + switch (alt21) { + case 1 : + // JPA.g:140:37: field '.' + { + pushFollow(FOLLOW_field_in_path_expression976); + field51=field(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_field.add(field51.getTree()); + char_literal52=(Token)match(input,57,FOLLOW_57_in_path_expression977); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_57.add(char_literal52); + + + } + break; + + default : + break loop21; + } + } while (true); + + // JPA.g:140:48: ( field )? + int alt22=2; + int LA22_0 = input.LA(1); + + if ( (LA22_0==GROUP) ) { + int LA22_1 = input.LA(2); + + if ( (LA22_1==EOF||(LA22_1>=HAVING && LA22_1<=DESC)||(LA22_1>=OR && LA22_1<=AND)||LA22_1==RPAREN||(LA22_1>=ORDER && LA22_1<=GROUP)||LA22_1==WORD||(LA22_1>=53 && LA22_1<=55)||LA22_1==58||LA22_1==62||(LA22_1>=65 && LA22_1<=66)||(LA22_1>=77 && LA22_1<=78)||LA22_1==80||LA22_1==83||(LA22_1>=89 && LA22_1<=96)) ) { + alt22=1; + } + } + else if ( (LA22_0==WORD) ) { + int LA22_3 = input.LA(2); + + if ( (synpred23_JPA()) ) { + alt22=1; + } + } + switch (alt22) { + case 1 : + // JPA.g:140:49: field + { + pushFollow(FOLLOW_field_in_path_expression982); + field53=field(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_field.add(field53.getTree()); + + } + break; + + } + + + + // AST REWRITE + // elements: field + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 141:5: -> ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) + { + // JPA.g:141:8: ^( T_SELECTED_FIELD[$identification_variable.text] ( field )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_FIELD, (identification_variable49!=null?input.toString(identification_variable49.start,identification_variable49.stop):null)), root_1); + + // JPA.g:141:68: ( field )* + while ( stream_field.hasNext() ) { + adaptor.addChild(root_1, stream_field.nextTree()); + + } + stream_field.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "path_expression" + + public static class select_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "select_clause" + // JPA.g:144:1: select_clause : ( 'DISTINCT' )? select_expression ( ',' select_expression )* -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) ; + public final JPAParser.select_clause_return select_clause() throws RecognitionException { + JPAParser.select_clause_return retval = new JPAParser.select_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal54=null; + Token char_literal56=null; + JPAParser.select_expression_return select_expression55 = null; + + JPAParser.select_expression_return select_expression57 = null; + + + Object string_literal54_tree=null; + Object char_literal56_tree=null; + RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); + RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); + RewriteRuleSubtreeStream stream_select_expression=new RewriteRuleSubtreeStream(adaptor,"rule select_expression"); + try { + // JPA.g:145:5: ( ( 'DISTINCT' )? select_expression ( ',' select_expression )* -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) ) + // JPA.g:145:7: ( 'DISTINCT' )? select_expression ( ',' select_expression )* + { + // JPA.g:145:7: ( 'DISTINCT' )? + int alt23=2; + int LA23_0 = input.LA(1); + + if ( (LA23_0==DISTINCT) ) { + alt23=1; + } + switch (alt23) { + case 1 : + // JPA.g:145:8: 'DISTINCT' + { + string_literal54=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_select_clause1021); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal54); + + + } + break; + + } + + pushFollow(FOLLOW_select_expression_in_select_clause1025); + select_expression55=select_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_select_expression.add(select_expression55.getTree()); + // JPA.g:145:39: ( ',' select_expression )* + loop24: + do { + int alt24=2; + int LA24_0 = input.LA(1); + + if ( (LA24_0==54) ) { + alt24=1; + } + + + switch (alt24) { + case 1 : + // JPA.g:145:40: ',' select_expression + { + char_literal56=(Token)match(input,54,FOLLOW_54_in_select_clause1028); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_54.add(char_literal56); + + pushFollow(FOLLOW_select_expression_in_select_clause1030); + select_expression57=select_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_select_expression.add(select_expression57.getTree()); + + } + break; + + default : + break loop24; + } + } while (true); + + + + // AST REWRITE + // elements: DISTINCT, select_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 146:5: -> ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) + { + // JPA.g:146:8: ^( T_SELECTED_ITEMS ( 'DISTINCT' )? ( ^( T_SELECTED_ITEM[] select_expression ) )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(T_SELECTED_ITEMS, "T_SELECTED_ITEMS"), root_1); + + // JPA.g:146:27: ( 'DISTINCT' )? + if ( stream_DISTINCT.hasNext() ) { + adaptor.addChild(root_1, stream_DISTINCT.nextNode()); + + } + stream_DISTINCT.reset(); + // JPA.g:146:41: ( ^( T_SELECTED_ITEM[] select_expression ) )* + while ( stream_select_expression.hasNext() ) { + // JPA.g:146:41: ^( T_SELECTED_ITEM[] select_expression ) + { + Object root_2 = (Object)adaptor.nil(); + root_2 = (Object)adaptor.becomeRoot(new SelectedItemNode(T_SELECTED_ITEM), root_2); + + adaptor.addChild(root_2, stream_select_expression.nextTree()); + + adaptor.addChild(root_1, root_2); + } + + } + stream_select_expression.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "select_clause" + + public static class select_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "select_expression" + // JPA.g:149:1: select_expression : ( path_expression | aggregate_expression | identification_variable -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) | 'OBJECT' '(' identification_variable ')' | constructor_expression ); + public final JPAParser.select_expression_return select_expression() throws RecognitionException { + JPAParser.select_expression_return retval = new JPAParser.select_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal61=null; + Token char_literal62=null; + Token char_literal64=null; + JPAParser.path_expression_return path_expression58 = null; + + JPAParser.aggregate_expression_return aggregate_expression59 = null; + + JPAParser.identification_variable_return identification_variable60 = null; + + JPAParser.identification_variable_return identification_variable63 = null; + + JPAParser.constructor_expression_return constructor_expression65 = null; + + + Object string_literal61_tree=null; + Object char_literal62_tree=null; + Object char_literal64_tree=null; + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + try { + // JPA.g:150:5: ( path_expression | aggregate_expression | identification_variable -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) | 'OBJECT' '(' identification_variable ')' | constructor_expression ) + int alt25=5; + switch ( input.LA(1) ) { + case WORD: + { + int LA25_1 = input.LA(2); + + if ( (LA25_1==EOF||(LA25_1>=53 && LA25_1<=54)) ) { + alt25=3; + } + else if ( (LA25_1==57) ) { + alt25=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 25, 1, input); + + throw nvae; + } + } + break; + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + { + alt25=2; + } + break; + case 59: + { + alt25=4; + } + break; + case 60: + { + alt25=5; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 25, 0, input); + + throw nvae; + } + + switch (alt25) { + case 1 : + // JPA.g:150:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_select_expression1075); + path_expression58=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression58.getTree()); + + } + break; + case 2 : + // JPA.g:151:7: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_select_expression1083); + aggregate_expression59=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression59.getTree()); + + } + break; + case 3 : + // JPA.g:152:7: identification_variable + { + pushFollow(FOLLOW_identification_variable_in_select_expression1091); + identification_variable60=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable60.getTree()); + + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 152:31: -> ^( T_SELECTED_ENTITY[$identification_variable.text] ) + { + // JPA.g:152:34: ^( T_SELECTED_ENTITY[$identification_variable.text] ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new PathNode(T_SELECTED_ENTITY, (identification_variable60!=null?input.toString(identification_variable60.start,identification_variable60.stop):null)), root_1); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 4 : + // JPA.g:153:7: 'OBJECT' '(' identification_variable ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal61=(Token)match(input,59,FOLLOW_59_in_select_expression1109); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal61_tree = (Object)adaptor.create(string_literal61); + adaptor.addChild(root_0, string_literal61_tree); + } + char_literal62=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_select_expression1111); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal62_tree = (Object)adaptor.create(char_literal62); + adaptor.addChild(root_0, char_literal62_tree); + } + pushFollow(FOLLOW_identification_variable_in_select_expression1112); + identification_variable63=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable63.getTree()); + char_literal64=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_select_expression1113); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal64_tree = (Object)adaptor.create(char_literal64); + adaptor.addChild(root_0, char_literal64_tree); + } + + } + break; + case 5 : + // JPA.g:154:7: constructor_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_constructor_expression_in_select_expression1121); + constructor_expression65=constructor_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_expression65.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "select_expression" + + public static class constructor_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "constructor_expression" + // JPA.g:156:1: constructor_expression : 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' ; + public final JPAParser.constructor_expression_return constructor_expression() throws RecognitionException { + JPAParser.constructor_expression_return retval = new JPAParser.constructor_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal66=null; + Token char_literal68=null; + Token char_literal70=null; + Token char_literal72=null; + JPAParser.constructor_name_return constructor_name67 = null; + + JPAParser.constructor_item_return constructor_item69 = null; + + JPAParser.constructor_item_return constructor_item71 = null; + + + Object string_literal66_tree=null; + Object char_literal68_tree=null; + Object char_literal70_tree=null; + Object char_literal72_tree=null; + + try { + // JPA.g:157:5: ( 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' ) + // JPA.g:157:7: 'NEW' constructor_name '(' constructor_item ( ',' constructor_item )* ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal66=(Token)match(input,60,FOLLOW_60_in_constructor_expression1133); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal66_tree = (Object)adaptor.create(string_literal66); + adaptor.addChild(root_0, string_literal66_tree); + } + pushFollow(FOLLOW_constructor_name_in_constructor_expression1135); + constructor_name67=constructor_name(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_name67.getTree()); + char_literal68=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_constructor_expression1137); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal68_tree = (Object)adaptor.create(char_literal68); + adaptor.addChild(root_0, char_literal68_tree); + } + pushFollow(FOLLOW_constructor_item_in_constructor_expression1139); + constructor_item69=constructor_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_item69.getTree()); + // JPA.g:157:51: ( ',' constructor_item )* + loop26: + do { + int alt26=2; + int LA26_0 = input.LA(1); + + if ( (LA26_0==54) ) { + alt26=1; + } + + + switch (alt26) { + case 1 : + // JPA.g:157:52: ',' constructor_item + { + char_literal70=(Token)match(input,54,FOLLOW_54_in_constructor_expression1142); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal70_tree = (Object)adaptor.create(char_literal70); + adaptor.addChild(root_0, char_literal70_tree); + } + pushFollow(FOLLOW_constructor_item_in_constructor_expression1144); + constructor_item71=constructor_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, constructor_item71.getTree()); + + } + break; + + default : + break loop26; + } + } while (true); + + char_literal72=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_constructor_expression1148); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal72_tree = (Object)adaptor.create(char_literal72); + adaptor.addChild(root_0, char_literal72_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "constructor_expression" + + public static class constructor_item_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "constructor_item" + // JPA.g:159:1: constructor_item : ( path_expression | aggregate_expression ); + public final JPAParser.constructor_item_return constructor_item() throws RecognitionException { + JPAParser.constructor_item_return retval = new JPAParser.constructor_item_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression73 = null; + + JPAParser.aggregate_expression_return aggregate_expression74 = null; + + + + try { + // JPA.g:160:5: ( path_expression | aggregate_expression ) + int alt27=2; + int LA27_0 = input.LA(1); + + if ( (LA27_0==WORD) ) { + alt27=1; + } + else if ( ((LA27_0>=AVG && LA27_0<=COUNT)) ) { + alt27=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 27, 0, input); + + throw nvae; + } + switch (alt27) { + case 1 : + // JPA.g:160:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_constructor_item1160); + path_expression73=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression73.getTree()); + + } + break; + case 2 : + // JPA.g:160:25: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_constructor_item1164); + aggregate_expression74=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression74.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "constructor_item" + + public static class aggregate_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "aggregate_expression" + // JPA.g:162:1: aggregate_expression : ( aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) | 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) ); + public final JPAParser.aggregate_expression_return aggregate_expression() throws RecognitionException { + JPAParser.aggregate_expression_return retval = new JPAParser.aggregate_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal76=null; + Token string_literal77=null; + Token char_literal79=null; + Token string_literal80=null; + Token char_literal81=null; + Token string_literal82=null; + Token char_literal84=null; + JPAParser.aggregate_expression_function_name_return aggregate_expression_function_name75 = null; + + JPAParser.path_expression_return path_expression78 = null; + + JPAParser.identification_variable_return identification_variable83 = null; + + + Object char_literal76_tree=null; + Object string_literal77_tree=null; + Object char_literal79_tree=null; + Object string_literal80_tree=null; + Object char_literal81_tree=null; + Object string_literal82_tree=null; + Object char_literal84_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_COUNT=new RewriteRuleTokenStream(adaptor,"token COUNT"); + RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_identification_variable=new RewriteRuleSubtreeStream(adaptor,"rule identification_variable"); + RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); + RewriteRuleSubtreeStream stream_aggregate_expression_function_name=new RewriteRuleSubtreeStream(adaptor,"rule aggregate_expression_function_name"); + try { + // JPA.g:163:5: ( aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) | 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) ) + int alt30=2; + int LA30_0 = input.LA(1); + + if ( (LA30_0==COUNT) ) { + int LA30_1 = input.LA(2); + + if ( (LA30_1==LPAREN) ) { + int LA30_3 = input.LA(3); + + if ( (LA30_3==DISTINCT) ) { + int LA30_4 = input.LA(4); + + if ( (LA30_4==WORD) ) { + int LA30_5 = input.LA(5); + + if ( (LA30_5==57) ) { + alt30=1; + } + else if ( (LA30_5==RPAREN) ) { + alt30=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 5, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 4, input); + + throw nvae; + } + } + else if ( (LA30_3==WORD) ) { + int LA30_5 = input.LA(4); + + if ( (LA30_5==57) ) { + alt30=1; + } + else if ( (LA30_5==RPAREN) ) { + alt30=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 5, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 3, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 1, input); + + throw nvae; + } + } + else if ( ((LA30_0>=AVG && LA30_0<=SUM)) ) { + alt30=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 0, input); + + throw nvae; + } + switch (alt30) { + case 1 : + // JPA.g:163:7: aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' + { + pushFollow(FOLLOW_aggregate_expression_function_name_in_aggregate_expression1176); + aggregate_expression_function_name75=aggregate_expression_function_name(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_aggregate_expression_function_name.add(aggregate_expression_function_name75.getTree()); + char_literal76=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_aggregate_expression1178); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(char_literal76); + + // JPA.g:163:46: ( 'DISTINCT' )? + int alt28=2; + int LA28_0 = input.LA(1); + + if ( (LA28_0==DISTINCT) ) { + alt28=1; + } + switch (alt28) { + case 1 : + // JPA.g:163:47: 'DISTINCT' + { + string_literal77=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_aggregate_expression1181); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal77); + + + } + break; + + } + + pushFollow(FOLLOW_path_expression_in_aggregate_expression1185); + path_expression78=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_path_expression.add(path_expression78.getTree()); + char_literal79=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_aggregate_expression1186); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(char_literal79); + + + + // AST REWRITE + // elements: aggregate_expression_function_name, path_expression, LPAREN, RPAREN, DISTINCT + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 164:5: -> ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) + { + // JPA.g:164:8: ^( T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ( 'DISTINCT' )? path_expression ')' ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new AggregateExpressionNode(T_AGGREGATE_EXPR), root_1); + + adaptor.addChild(root_1, stream_aggregate_expression_function_name.nextTree()); + adaptor.addChild(root_1, stream_LPAREN.nextNode()); + // JPA.g:164:93: ( 'DISTINCT' )? + if ( stream_DISTINCT.hasNext() ) { + adaptor.addChild(root_1, stream_DISTINCT.nextNode()); + + } + stream_DISTINCT.reset(); + adaptor.addChild(root_1, stream_path_expression.nextTree()); + adaptor.addChild(root_1, stream_RPAREN.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 2 : + // JPA.g:165:7: 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' + { + string_literal80=(Token)match(input,COUNT,FOLLOW_COUNT_in_aggregate_expression1220); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COUNT.add(string_literal80); + + char_literal81=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_aggregate_expression1222); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(char_literal81); + + // JPA.g:165:19: ( 'DISTINCT' )? + int alt29=2; + int LA29_0 = input.LA(1); + + if ( (LA29_0==DISTINCT) ) { + alt29=1; + } + switch (alt29) { + case 1 : + // JPA.g:165:20: 'DISTINCT' + { + string_literal82=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_aggregate_expression1225); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal82); + + + } + break; + + } + + pushFollow(FOLLOW_identification_variable_in_aggregate_expression1229); + identification_variable83=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identification_variable.add(identification_variable83.getTree()); + char_literal84=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_aggregate_expression1231); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(char_literal84); + + + + // AST REWRITE + // elements: DISTINCT, identification_variable, COUNT, LPAREN, RPAREN + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 166:5: -> ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) + { + // JPA.g:166:8: ^( T_AGGREGATE_EXPR[] 'COUNT' '(' ( 'DISTINCT' )? identification_variable ')' ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new AggregateExpressionNode(T_AGGREGATE_EXPR), root_1); + + adaptor.addChild(root_1, stream_COUNT.nextNode()); + adaptor.addChild(root_1, stream_LPAREN.nextNode()); + // JPA.g:166:66: ( 'DISTINCT' )? + if ( stream_DISTINCT.hasNext() ) { + adaptor.addChild(root_1, stream_DISTINCT.nextNode()); + + } + stream_DISTINCT.reset(); + adaptor.addChild(root_1, stream_identification_variable.nextTree()); + adaptor.addChild(root_1, stream_RPAREN.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "aggregate_expression" + + public static class aggregate_expression_function_name_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "aggregate_expression_function_name" + // JPA.g:168:1: aggregate_expression_function_name : ( 'AVG' | 'MAX' | 'MIN' | 'SUM' | 'COUNT' ); + public final JPAParser.aggregate_expression_function_name_return aggregate_expression_function_name() throws RecognitionException { + JPAParser.aggregate_expression_function_name_return retval = new JPAParser.aggregate_expression_function_name_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set85=null; + + Object set85_tree=null; + + try { + // JPA.g:169:5: ( 'AVG' | 'MAX' | 'MIN' | 'SUM' | 'COUNT' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set85=(Token)input.LT(1); + if ( (input.LA(1)>=AVG && input.LA(1)<=COUNT) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set85)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "aggregate_expression_function_name" + + public static class where_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "where_clause" + // JPA.g:171:1: where_clause : (wh= 'WHERE' conditional_expression -> ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) ); + public final JPAParser.where_clause_return where_clause() throws RecognitionException { + JPAParser.where_clause_return retval = new JPAParser.where_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token wh=null; + Token string_literal87=null; + JPAParser.conditional_expression_return conditional_expression86 = null; + + JPAParser.path_expression_return path_expression88 = null; + + + Object wh_tree=null; + Object string_literal87_tree=null; + RewriteRuleTokenStream stream_61=new RewriteRuleTokenStream(adaptor,"token 61"); + RewriteRuleSubtreeStream stream_conditional_expression=new RewriteRuleSubtreeStream(adaptor,"rule conditional_expression"); + RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); + try { + // JPA.g:172:5: (wh= 'WHERE' conditional_expression -> ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) ) + int alt31=2; + alt31 = dfa31.predict(input); + switch (alt31) { + case 1 : + // JPA.g:172:7: wh= 'WHERE' conditional_expression + { + wh=(Token)match(input,61,FOLLOW_61_in_where_clause1299); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_61.add(wh); + + pushFollow(FOLLOW_conditional_expression_in_where_clause1301); + conditional_expression86=conditional_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_conditional_expression.add(conditional_expression86.getTree()); + + + // AST REWRITE + // elements: conditional_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 172:40: -> ^( T_CONDITION[$wh] conditional_expression ) + { + // JPA.g:172:43: ^( T_CONDITION[$wh] conditional_expression ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new WhereNode(T_CONDITION, wh), root_1); + + adaptor.addChild(root_1, stream_conditional_expression.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 2 : + // JPA.g:173:7: 'WHERE' path_expression + { + string_literal87=(Token)match(input,61,FOLLOW_61_in_where_clause1320); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_61.add(string_literal87); + + pushFollow(FOLLOW_path_expression_in_where_clause1322); + path_expression88=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_path_expression.add(path_expression88.getTree()); + + + // AST REWRITE + // elements: path_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 173:31: -> ^( T_CONDITION[$wh] path_expression ) + { + // JPA.g:173:34: ^( T_CONDITION[$wh] path_expression ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new WhereNode(T_CONDITION, wh), root_1); + + adaptor.addChild(root_1, stream_path_expression.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "where_clause" + + public static class groupby_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "groupby_clause" + // JPA.g:175:1: groupby_clause : 'GROUP' 'BY' groupby_item ( ',' groupby_item )* -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) ; + public final JPAParser.groupby_clause_return groupby_clause() throws RecognitionException { + JPAParser.groupby_clause_return retval = new JPAParser.groupby_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal89=null; + Token string_literal90=null; + Token char_literal92=null; + JPAParser.groupby_item_return groupby_item91 = null; + + JPAParser.groupby_item_return groupby_item93 = null; + + + Object string_literal89_tree=null; + Object string_literal90_tree=null; + Object char_literal92_tree=null; + RewriteRuleTokenStream stream_GROUP=new RewriteRuleTokenStream(adaptor,"token GROUP"); + RewriteRuleTokenStream stream_BY=new RewriteRuleTokenStream(adaptor,"token BY"); + RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); + RewriteRuleSubtreeStream stream_groupby_item=new RewriteRuleSubtreeStream(adaptor,"rule groupby_item"); + try { + // JPA.g:176:5: ( 'GROUP' 'BY' groupby_item ( ',' groupby_item )* -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) ) + // JPA.g:176:7: 'GROUP' 'BY' groupby_item ( ',' groupby_item )* + { + string_literal89=(Token)match(input,GROUP,FOLLOW_GROUP_in_groupby_clause1346); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_GROUP.add(string_literal89); + + string_literal90=(Token)match(input,BY,FOLLOW_BY_in_groupby_clause1348); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_BY.add(string_literal90); + + pushFollow(FOLLOW_groupby_item_in_groupby_clause1350); + groupby_item91=groupby_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_groupby_item.add(groupby_item91.getTree()); + // JPA.g:176:33: ( ',' groupby_item )* + loop32: + do { + int alt32=2; + int LA32_0 = input.LA(1); + + if ( (LA32_0==54) ) { + alt32=1; + } + + + switch (alt32) { + case 1 : + // JPA.g:176:34: ',' groupby_item + { + char_literal92=(Token)match(input,54,FOLLOW_54_in_groupby_clause1353); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_54.add(char_literal92); + + pushFollow(FOLLOW_groupby_item_in_groupby_clause1355); + groupby_item93=groupby_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_groupby_item.add(groupby_item93.getTree()); + + } + break; + + default : + break loop32; + } + } while (true); + + + + // AST REWRITE + // elements: BY, groupby_item, GROUP + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 177:5: -> ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) + { + // JPA.g:177:8: ^( T_GROUP_BY[] 'GROUP' 'BY' ( groupby_item )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new GroupByNode(T_GROUP_BY), root_1); + + adaptor.addChild(root_1, stream_GROUP.nextNode()); + adaptor.addChild(root_1, stream_BY.nextNode()); + // JPA.g:177:49: ( groupby_item )* + while ( stream_groupby_item.hasNext() ) { + adaptor.addChild(root_1, stream_groupby_item.nextTree()); + + } + stream_groupby_item.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "groupby_clause" + + public static class groupby_item_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "groupby_item" + // JPA.g:180:1: groupby_item : ( path_expression | identification_variable ); + public final JPAParser.groupby_item_return groupby_item() throws RecognitionException { + JPAParser.groupby_item_return retval = new JPAParser.groupby_item_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression94 = null; + + JPAParser.identification_variable_return identification_variable95 = null; + + + + try { + // JPA.g:181:5: ( path_expression | identification_variable ) + int alt33=2; + int LA33_0 = input.LA(1); + + if ( (LA33_0==WORD) ) { + int LA33_1 = input.LA(2); + + if ( (LA33_1==EOF||LA33_1==HAVING||LA33_1==RPAREN||LA33_1==ORDER||LA33_1==54) ) { + alt33=2; + } + else if ( (LA33_1==57) ) { + alt33=1; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 33, 1, input); + + throw nvae; + } + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 33, 0, input); + + throw nvae; + } + switch (alt33) { + case 1 : + // JPA.g:181:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_groupby_item1395); + path_expression94=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression94.getTree()); + + } + break; + case 2 : + // JPA.g:181:25: identification_variable + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_identification_variable_in_groupby_item1399); + identification_variable95=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable95.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "groupby_item" + + public static class having_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "having_clause" + // JPA.g:183:1: having_clause : 'HAVING' conditional_expression ; + public final JPAParser.having_clause_return having_clause() throws RecognitionException { + JPAParser.having_clause_return retval = new JPAParser.having_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal96=null; + JPAParser.conditional_expression_return conditional_expression97 = null; + + + Object string_literal96_tree=null; + + try { + // JPA.g:184:5: ( 'HAVING' conditional_expression ) + // JPA.g:184:7: 'HAVING' conditional_expression + { + root_0 = (Object)adaptor.nil(); + + string_literal96=(Token)match(input,HAVING,FOLLOW_HAVING_in_having_clause1411); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal96_tree = (Object)adaptor.create(string_literal96); + adaptor.addChild(root_0, string_literal96_tree); + } + pushFollow(FOLLOW_conditional_expression_in_having_clause1413); + conditional_expression97=conditional_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_expression97.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "having_clause" + + public static class orderby_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "orderby_clause" + // JPA.g:186:1: orderby_clause : 'ORDER' 'BY' orderby_item ( ',' orderby_item )* -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) ; + public final JPAParser.orderby_clause_return orderby_clause() throws RecognitionException { + JPAParser.orderby_clause_return retval = new JPAParser.orderby_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal98=null; + Token string_literal99=null; + Token char_literal101=null; + JPAParser.orderby_item_return orderby_item100 = null; + + JPAParser.orderby_item_return orderby_item102 = null; + + + Object string_literal98_tree=null; + Object string_literal99_tree=null; + Object char_literal101_tree=null; + RewriteRuleTokenStream stream_BY=new RewriteRuleTokenStream(adaptor,"token BY"); + RewriteRuleTokenStream stream_ORDER=new RewriteRuleTokenStream(adaptor,"token ORDER"); + RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); + RewriteRuleSubtreeStream stream_orderby_item=new RewriteRuleSubtreeStream(adaptor,"rule orderby_item"); + try { + // JPA.g:187:5: ( 'ORDER' 'BY' orderby_item ( ',' orderby_item )* -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) ) + // JPA.g:187:7: 'ORDER' 'BY' orderby_item ( ',' orderby_item )* + { + string_literal98=(Token)match(input,ORDER,FOLLOW_ORDER_in_orderby_clause1425); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ORDER.add(string_literal98); + + string_literal99=(Token)match(input,BY,FOLLOW_BY_in_orderby_clause1427); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_BY.add(string_literal99); + + pushFollow(FOLLOW_orderby_item_in_orderby_clause1429); + orderby_item100=orderby_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_orderby_item.add(orderby_item100.getTree()); + // JPA.g:187:33: ( ',' orderby_item )* + loop34: + do { + int alt34=2; + int LA34_0 = input.LA(1); + + if ( (LA34_0==54) ) { + alt34=1; + } + + + switch (alt34) { + case 1 : + // JPA.g:187:34: ',' orderby_item + { + char_literal101=(Token)match(input,54,FOLLOW_54_in_orderby_clause1432); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_54.add(char_literal101); + + pushFollow(FOLLOW_orderby_item_in_orderby_clause1434); + orderby_item102=orderby_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_orderby_item.add(orderby_item102.getTree()); + + } + break; + + default : + break loop34; + } + } while (true); + + + + // AST REWRITE + // elements: BY, orderby_item, ORDER + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 188:5: -> ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) + { + // JPA.g:188:8: ^( T_ORDER_BY[] 'ORDER' 'BY' ( orderby_item )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new OrderByNode(T_ORDER_BY), root_1); + + adaptor.addChild(root_1, stream_ORDER.nextNode()); + adaptor.addChild(root_1, stream_BY.nextNode()); + // JPA.g:188:49: ( orderby_item )* + while ( stream_orderby_item.hasNext() ) { + adaptor.addChild(root_1, stream_orderby_item.nextTree()); + + } + stream_orderby_item.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "orderby_clause" + + public static class orderby_item_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "orderby_item" + // JPA.g:190:1: orderby_item : ( path_expression ( 'ASC' )? -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) ); + public final JPAParser.orderby_item_return orderby_item() throws RecognitionException { + JPAParser.orderby_item_return retval = new JPAParser.orderby_item_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal104=null; + Token string_literal106=null; + JPAParser.path_expression_return path_expression103 = null; + + JPAParser.path_expression_return path_expression105 = null; + + + Object string_literal104_tree=null; + Object string_literal106_tree=null; + RewriteRuleTokenStream stream_DESC=new RewriteRuleTokenStream(adaptor,"token DESC"); + RewriteRuleTokenStream stream_ASC=new RewriteRuleTokenStream(adaptor,"token ASC"); + RewriteRuleSubtreeStream stream_path_expression=new RewriteRuleSubtreeStream(adaptor,"rule path_expression"); + try { + // JPA.g:191:5: ( path_expression ( 'ASC' )? -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) ) + int alt36=2; + alt36 = dfa36.predict(input); + switch (alt36) { + case 1 : + // JPA.g:191:7: path_expression ( 'ASC' )? + { + pushFollow(FOLLOW_path_expression_in_orderby_item1469); + path_expression103=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_path_expression.add(path_expression103.getTree()); + // JPA.g:191:25: ( 'ASC' )? + int alt35=2; + int LA35_0 = input.LA(1); + + if ( (LA35_0==ASC) ) { + alt35=1; + } + switch (alt35) { + case 1 : + // JPA.g:191:26: 'ASC' + { + string_literal104=(Token)match(input,ASC,FOLLOW_ASC_in_orderby_item1474); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ASC.add(string_literal104); + + + } + break; + + } + + + + // AST REWRITE + // elements: ASC, path_expression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 192:6: -> ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) + { + // JPA.g:192:9: ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new OrderByFieldNode(T_ORDER_BY_FIELD), root_1); + + adaptor.addChild(root_1, stream_path_expression.nextTree()); + // JPA.g:192:64: ( 'ASC' )? + if ( stream_ASC.hasNext() ) { + adaptor.addChild(root_1, stream_ASC.nextNode()); + + } + stream_ASC.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 2 : + // JPA.g:193:7: path_expression 'DESC' + { + pushFollow(FOLLOW_path_expression_in_orderby_item1506); + path_expression105=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_path_expression.add(path_expression105.getTree()); + string_literal106=(Token)match(input,DESC,FOLLOW_DESC_in_orderby_item1510); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DESC.add(string_literal106); + + + + // AST REWRITE + // elements: path_expression, DESC + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 194:5: -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) + { + // JPA.g:194:8: ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new OrderByFieldNode(T_ORDER_BY_FIELD), root_1); + + adaptor.addChild(root_1, stream_path_expression.nextTree()); + adaptor.addChild(root_1, stream_DESC.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "orderby_item" + + public static class subquery_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "subquery" + // JPA.g:196:1: subquery : lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) ; + public final JPAParser.subquery_return subquery() throws RecognitionException { + JPAParser.subquery_return retval = new JPAParser.subquery_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token lp=null; + Token rp=null; + JPAParser.simple_select_clause_return simple_select_clause107 = null; + + JPAParser.subquery_from_clause_return subquery_from_clause108 = null; + + JPAParser.where_clause_return where_clause109 = null; + + JPAParser.groupby_clause_return groupby_clause110 = null; + + JPAParser.having_clause_return having_clause111 = null; + + + Object lp_tree=null; + Object rp_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_56=new RewriteRuleTokenStream(adaptor,"token 56"); + RewriteRuleSubtreeStream stream_groupby_clause=new RewriteRuleSubtreeStream(adaptor,"rule groupby_clause"); + RewriteRuleSubtreeStream stream_having_clause=new RewriteRuleSubtreeStream(adaptor,"rule having_clause"); + RewriteRuleSubtreeStream stream_where_clause=new RewriteRuleSubtreeStream(adaptor,"rule where_clause"); + RewriteRuleSubtreeStream stream_subquery_from_clause=new RewriteRuleSubtreeStream(adaptor,"rule subquery_from_clause"); + RewriteRuleSubtreeStream stream_simple_select_clause=new RewriteRuleSubtreeStream(adaptor,"rule simple_select_clause"); + try { + // JPA.g:197:5: (lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) ) + // JPA.g:197:7: lp= '(SELECT' simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? rp= ')' + { + lp=(Token)match(input,56,FOLLOW_56_in_subquery1542); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_56.add(lp); + + pushFollow(FOLLOW_simple_select_clause_in_subquery1544); + simple_select_clause107=simple_select_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_simple_select_clause.add(simple_select_clause107.getTree()); + pushFollow(FOLLOW_subquery_from_clause_in_subquery1546); + subquery_from_clause108=subquery_from_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_subquery_from_clause.add(subquery_from_clause108.getTree()); + // JPA.g:197:62: ( where_clause )? + int alt37=2; + int LA37_0 = input.LA(1); + + if ( (LA37_0==61) ) { + alt37=1; + } + switch (alt37) { + case 1 : + // JPA.g:197:63: where_clause + { + pushFollow(FOLLOW_where_clause_in_subquery1549); + where_clause109=where_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_where_clause.add(where_clause109.getTree()); + + } + break; + + } + + // JPA.g:197:78: ( groupby_clause )? + int alt38=2; + int LA38_0 = input.LA(1); + + if ( (LA38_0==GROUP) ) { + alt38=1; + } + switch (alt38) { + case 1 : + // JPA.g:197:79: groupby_clause + { + pushFollow(FOLLOW_groupby_clause_in_subquery1554); + groupby_clause110=groupby_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_groupby_clause.add(groupby_clause110.getTree()); + + } + break; + + } + + // JPA.g:197:96: ( having_clause )? + int alt39=2; + int LA39_0 = input.LA(1); + + if ( (LA39_0==HAVING) ) { + alt39=1; + } + switch (alt39) { + case 1 : + // JPA.g:197:97: having_clause + { + pushFollow(FOLLOW_having_clause_in_subquery1559); + having_clause111=having_clause(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_having_clause.add(having_clause111.getTree()); + + } + break; + + } + + rp=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_subquery1565); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(rp); + + + + // AST REWRITE + // elements: where_clause, simple_select_clause, groupby_clause, subquery_from_clause, having_clause + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 198:6: -> ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) + { + // JPA.g:198:9: ^( T_QUERY[$lp,$rp] simple_select_clause subquery_from_clause ( where_clause )? ( groupby_clause )? ( having_clause )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new QueryNode(T_QUERY, lp, rp), root_1); + + adaptor.addChild(root_1, stream_simple_select_clause.nextTree()); + adaptor.addChild(root_1, stream_subquery_from_clause.nextTree()); + // JPA.g:198:81: ( where_clause )? + if ( stream_where_clause.hasNext() ) { + adaptor.addChild(root_1, stream_where_clause.nextTree()); + + } + stream_where_clause.reset(); + // JPA.g:198:97: ( groupby_clause )? + if ( stream_groupby_clause.hasNext() ) { + adaptor.addChild(root_1, stream_groupby_clause.nextTree()); + + } + stream_groupby_clause.reset(); + // JPA.g:198:115: ( having_clause )? + if ( stream_having_clause.hasNext() ) { + adaptor.addChild(root_1, stream_having_clause.nextTree()); + + } + stream_having_clause.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "subquery" + + public static class subquery_from_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "subquery_from_clause" + // JPA.g:200:1: subquery_from_clause : fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) ; + public final JPAParser.subquery_from_clause_return subquery_from_clause() throws RecognitionException { + JPAParser.subquery_from_clause_return retval = new JPAParser.subquery_from_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token fr=null; + Token char_literal113=null; + JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration112 = null; + + JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration114 = null; + + + Object fr_tree=null; + Object char_literal113_tree=null; + RewriteRuleTokenStream stream_53=new RewriteRuleTokenStream(adaptor,"token 53"); + RewriteRuleTokenStream stream_54=new RewriteRuleTokenStream(adaptor,"token 54"); + RewriteRuleSubtreeStream stream_subselect_identification_variable_declaration=new RewriteRuleSubtreeStream(adaptor,"rule subselect_identification_variable_declaration"); + try { + // JPA.g:201:5: (fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) ) + // JPA.g:201:7: fr= 'FROM' subselect_identification_variable_declaration ( ',' subselect_identification_variable_declaration )* + { + fr=(Token)match(input,53,FOLLOW_53_in_subquery_from_clause1614); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_53.add(fr); + + pushFollow(FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1616); + subselect_identification_variable_declaration112=subselect_identification_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_subselect_identification_variable_declaration.add(subselect_identification_variable_declaration112.getTree()); + // JPA.g:201:63: ( ',' subselect_identification_variable_declaration )* + loop40: + do { + int alt40=2; + int LA40_0 = input.LA(1); + + if ( (LA40_0==54) ) { + alt40=1; + } + + + switch (alt40) { + case 1 : + // JPA.g:201:64: ',' subselect_identification_variable_declaration + { + char_literal113=(Token)match(input,54,FOLLOW_54_in_subquery_from_clause1619); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_54.add(char_literal113); + + pushFollow(FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1621); + subselect_identification_variable_declaration114=subselect_identification_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_subselect_identification_variable_declaration.add(subselect_identification_variable_declaration114.getTree()); + + } + break; + + default : + break loop40; + } + } while (true); + + + + // AST REWRITE + // elements: subselect_identification_variable_declaration + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 202:5: -> ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) + { + // JPA.g:202:8: ^( T_SOURCES[$fr] ( ^( T_SOURCE subselect_identification_variable_declaration ) )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new FromNode(T_SOURCES, fr), root_1); + + // JPA.g:202:35: ( ^( T_SOURCE subselect_identification_variable_declaration ) )* + while ( stream_subselect_identification_variable_declaration.hasNext() ) { + // JPA.g:202:35: ^( T_SOURCE subselect_identification_variable_declaration ) + { + Object root_2 = (Object)adaptor.nil(); + root_2 = (Object)adaptor.becomeRoot(new SelectionSourceNode(T_SOURCE), root_2); + + adaptor.addChild(root_2, stream_subselect_identification_variable_declaration.nextTree()); + + adaptor.addChild(root_1, root_2); + } + + } + stream_subselect_identification_variable_declaration.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "subquery_from_clause" + + public static class subselect_identification_variable_declaration_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "subselect_identification_variable_declaration" + // JPA.g:204:1: subselect_identification_variable_declaration : ( identification_variable_declaration | association_path_expression ( 'AS' )? identification_variable | collection_member_declaration ); + public final JPAParser.subselect_identification_variable_declaration_return subselect_identification_variable_declaration() throws RecognitionException { + JPAParser.subselect_identification_variable_declaration_return retval = new JPAParser.subselect_identification_variable_declaration_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal117=null; + JPAParser.identification_variable_declaration_return identification_variable_declaration115 = null; + + JPAParser.association_path_expression_return association_path_expression116 = null; + + JPAParser.identification_variable_return identification_variable118 = null; + + JPAParser.collection_member_declaration_return collection_member_declaration119 = null; + + + Object string_literal117_tree=null; + + try { + // JPA.g:205:5: ( identification_variable_declaration | association_path_expression ( 'AS' )? identification_variable | collection_member_declaration ) + int alt42=3; + switch ( input.LA(1) ) { + case WORD: + { + int LA42_1 = input.LA(2); + + if ( (LA42_1==WORD||LA42_1==55) ) { + alt42=1; + } + else if ( (LA42_1==57) ) { + alt42=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 42, 1, input); + + throw nvae; + } + } + break; + case 56: + { + alt42=1; + } + break; + case 58: + { + alt42=3; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 42, 0, input); + + throw nvae; + } + + switch (alt42) { + case 1 : + // JPA.g:205:7: identification_variable_declaration + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_identification_variable_declaration_in_subselect_identification_variable_declaration1659); + identification_variable_declaration115=identification_variable_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable_declaration115.getTree()); + + } + break; + case 2 : + // JPA.g:206:7: association_path_expression ( 'AS' )? identification_variable + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_association_path_expression_in_subselect_identification_variable_declaration1667); + association_path_expression116=association_path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, association_path_expression116.getTree()); + // JPA.g:206:35: ( 'AS' )? + int alt41=2; + int LA41_0 = input.LA(1); + + if ( (LA41_0==55) ) { + alt41=1; + } + switch (alt41) { + case 1 : + // JPA.g:206:36: 'AS' + { + string_literal117=(Token)match(input,55,FOLLOW_55_in_subselect_identification_variable_declaration1670); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal117_tree = (Object)adaptor.create(string_literal117); + adaptor.addChild(root_0, string_literal117_tree); + } + + } + break; + + } + + pushFollow(FOLLOW_identification_variable_in_subselect_identification_variable_declaration1674); + identification_variable118=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable118.getTree()); + + } + break; + case 3 : + // JPA.g:207:7: collection_member_declaration + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_collection_member_declaration_in_subselect_identification_variable_declaration1682); + collection_member_declaration119=collection_member_declaration(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, collection_member_declaration119.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "subselect_identification_variable_declaration" + + public static class association_path_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "association_path_expression" + // JPA.g:209:1: association_path_expression : path_expression ; + public final JPAParser.association_path_expression_return association_path_expression() throws RecognitionException { + JPAParser.association_path_expression_return retval = new JPAParser.association_path_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression120 = null; + + + + try { + // JPA.g:210:5: ( path_expression ) + // JPA.g:210:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_association_path_expression1694); + path_expression120=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression120.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "association_path_expression" + + public static class simple_select_clause_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "simple_select_clause" + // JPA.g:212:1: simple_select_clause : ( 'DISTINCT' )? simple_select_expression -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) ; + public final JPAParser.simple_select_clause_return simple_select_clause() throws RecognitionException { + JPAParser.simple_select_clause_return retval = new JPAParser.simple_select_clause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal121=null; + JPAParser.simple_select_expression_return simple_select_expression122 = null; + + + Object string_literal121_tree=null; + RewriteRuleTokenStream stream_DISTINCT=new RewriteRuleTokenStream(adaptor,"token DISTINCT"); + RewriteRuleSubtreeStream stream_simple_select_expression=new RewriteRuleSubtreeStream(adaptor,"rule simple_select_expression"); + try { + // JPA.g:213:5: ( ( 'DISTINCT' )? simple_select_expression -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) ) + // JPA.g:213:7: ( 'DISTINCT' )? simple_select_expression + { + // JPA.g:213:7: ( 'DISTINCT' )? + int alt43=2; + int LA43_0 = input.LA(1); + + if ( (LA43_0==DISTINCT) ) { + alt43=1; + } + switch (alt43) { + case 1 : + // JPA.g:213:8: 'DISTINCT' + { + string_literal121=(Token)match(input,DISTINCT,FOLLOW_DISTINCT_in_simple_select_clause1707); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DISTINCT.add(string_literal121); + + + } + break; + + } + + pushFollow(FOLLOW_simple_select_expression_in_simple_select_clause1711); + simple_select_expression122=simple_select_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_simple_select_expression.add(simple_select_expression122.getTree()); + + + // AST REWRITE + // elements: simple_select_expression, DISTINCT + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 214:5: -> ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) + { + // JPA.g:214:8: ^( T_SELECTED_ITEMS ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(T_SELECTED_ITEMS, "T_SELECTED_ITEMS"), root_1); + + // JPA.g:214:27: ^( T_SELECTED_ITEM[] ( 'DISTINCT' )? simple_select_expression ) + { + Object root_2 = (Object)adaptor.nil(); + root_2 = (Object)adaptor.becomeRoot(new SelectedItemNode(T_SELECTED_ITEM), root_2); + + // JPA.g:214:65: ( 'DISTINCT' )? + if ( stream_DISTINCT.hasNext() ) { + adaptor.addChild(root_2, stream_DISTINCT.nextNode()); + + } + stream_DISTINCT.reset(); + adaptor.addChild(root_2, stream_simple_select_expression.nextTree()); + + adaptor.addChild(root_1, root_2); + } + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "simple_select_clause" + + public static class simple_select_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "simple_select_expression" + // JPA.g:216:1: simple_select_expression : ( path_expression | aggregate_expression | identification_variable ); + public final JPAParser.simple_select_expression_return simple_select_expression() throws RecognitionException { + JPAParser.simple_select_expression_return retval = new JPAParser.simple_select_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression123 = null; + + JPAParser.aggregate_expression_return aggregate_expression124 = null; + + JPAParser.identification_variable_return identification_variable125 = null; + + + + try { + // JPA.g:217:5: ( path_expression | aggregate_expression | identification_variable ) + int alt44=3; + int LA44_0 = input.LA(1); + + if ( (LA44_0==WORD) ) { + int LA44_1 = input.LA(2); + + if ( (LA44_1==57) ) { + alt44=1; + } + else if ( (LA44_1==53) ) { + alt44=3; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 44, 1, input); + + throw nvae; + } + } + else if ( ((LA44_0>=AVG && LA44_0<=COUNT)) ) { + alt44=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 44, 0, input); + + throw nvae; + } + switch (alt44) { + case 1 : + // JPA.g:217:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_simple_select_expression1748); + path_expression123=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression123.getTree()); + + } + break; + case 2 : + // JPA.g:218:7: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_simple_select_expression1756); + aggregate_expression124=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression124.getTree()); + + } + break; + case 3 : + // JPA.g:219:7: identification_variable + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_identification_variable_in_simple_select_expression1764); + identification_variable125=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable125.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "simple_select_expression" + + public static class conditional_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "conditional_expression" + // JPA.g:221:1: conditional_expression : ( conditional_term ) ( 'OR' conditional_term )* ; + public final JPAParser.conditional_expression_return conditional_expression() throws RecognitionException { + JPAParser.conditional_expression_return retval = new JPAParser.conditional_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal127=null; + JPAParser.conditional_term_return conditional_term126 = null; + + JPAParser.conditional_term_return conditional_term128 = null; + + + Object string_literal127_tree=null; + + try { + // JPA.g:222:5: ( ( conditional_term ) ( 'OR' conditional_term )* ) + // JPA.g:222:7: ( conditional_term ) ( 'OR' conditional_term )* + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:222:7: ( conditional_term ) + // JPA.g:222:8: conditional_term + { + pushFollow(FOLLOW_conditional_term_in_conditional_expression1777); + conditional_term126=conditional_term(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_term126.getTree()); + + } + + // JPA.g:222:26: ( 'OR' conditional_term )* + loop45: + do { + int alt45=2; + int LA45_0 = input.LA(1); + + if ( (LA45_0==OR) ) { + alt45=1; + } + + + switch (alt45) { + case 1 : + // JPA.g:222:27: 'OR' conditional_term + { + string_literal127=(Token)match(input,OR,FOLLOW_OR_in_conditional_expression1781); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal127_tree = (Object)adaptor.create(string_literal127); + adaptor.addChild(root_0, string_literal127_tree); + } + pushFollow(FOLLOW_conditional_term_in_conditional_expression1783); + conditional_term128=conditional_term(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_term128.getTree()); + + } + break; + + default : + break loop45; + } + } while (true); + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "conditional_expression" + + public static class conditional_term_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "conditional_term" + // JPA.g:224:1: conditional_term : ( conditional_factor ) ( 'AND' conditional_factor )* ; + public final JPAParser.conditional_term_return conditional_term() throws RecognitionException { + JPAParser.conditional_term_return retval = new JPAParser.conditional_term_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal130=null; + JPAParser.conditional_factor_return conditional_factor129 = null; + + JPAParser.conditional_factor_return conditional_factor131 = null; + + + Object string_literal130_tree=null; + + try { + // JPA.g:225:5: ( ( conditional_factor ) ( 'AND' conditional_factor )* ) + // JPA.g:225:7: ( conditional_factor ) ( 'AND' conditional_factor )* + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:225:7: ( conditional_factor ) + // JPA.g:225:8: conditional_factor + { + pushFollow(FOLLOW_conditional_factor_in_conditional_term1798); + conditional_factor129=conditional_factor(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_factor129.getTree()); + + } + + // JPA.g:225:28: ( 'AND' conditional_factor )* + loop46: + do { + int alt46=2; + int LA46_0 = input.LA(1); + + if ( (LA46_0==AND) ) { + alt46=1; + } + + + switch (alt46) { + case 1 : + // JPA.g:225:29: 'AND' conditional_factor + { + string_literal130=(Token)match(input,AND,FOLLOW_AND_in_conditional_term1802); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal130_tree = (Object)adaptor.create(string_literal130); + adaptor.addChild(root_0, string_literal130_tree); + } + pushFollow(FOLLOW_conditional_factor_in_conditional_term1804); + conditional_factor131=conditional_factor(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_factor131.getTree()); + + } + break; + + default : + break loop46; + } + } while (true); + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "conditional_term" + + public static class conditional_factor_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "conditional_factor" + // JPA.g:227:1: conditional_factor : ( ( 'NOT' )? simple_cond_expression -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' ); + public final JPAParser.conditional_factor_return conditional_factor() throws RecognitionException { + JPAParser.conditional_factor_return retval = new JPAParser.conditional_factor_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal132=null; + Token char_literal134=null; + Token char_literal136=null; + JPAParser.simple_cond_expression_return simple_cond_expression133 = null; + + JPAParser.conditional_expression_return conditional_expression135 = null; + + + Object string_literal132_tree=null; + Object char_literal134_tree=null; + Object char_literal136_tree=null; + RewriteRuleTokenStream stream_62=new RewriteRuleTokenStream(adaptor,"token 62"); + RewriteRuleSubtreeStream stream_simple_cond_expression=new RewriteRuleSubtreeStream(adaptor,"rule simple_cond_expression"); + try { + // JPA.g:228:5: ( ( 'NOT' )? simple_cond_expression -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' ) + int alt48=2; + alt48 = dfa48.predict(input); + switch (alt48) { + case 1 : + // JPA.g:228:7: ( 'NOT' )? simple_cond_expression + { + // JPA.g:228:7: ( 'NOT' )? + int alt47=2; + int LA47_0 = input.LA(1); + + if ( (LA47_0==62) ) { + int LA47_1 = input.LA(2); + + if ( (synpred57_JPA()) ) { + alt47=1; + } + } + switch (alt47) { + case 1 : + // JPA.g:228:8: 'NOT' + { + string_literal132=(Token)match(input,62,FOLLOW_62_in_conditional_factor1823); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_62.add(string_literal132); + + + } + break; + + } + + pushFollow(FOLLOW_simple_cond_expression_in_conditional_factor1827); + simple_cond_expression133=simple_cond_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_simple_cond_expression.add(simple_cond_expression133.getTree()); + + + // AST REWRITE + // elements: simple_cond_expression, 62 + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 228:39: -> ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) + { + // JPA.g:228:42: ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new SimpleConditionNode(T_SIMPLE_CONDITION), root_1); + + // JPA.g:228:86: ( 'NOT' )? + if ( stream_62.hasNext() ) { + adaptor.addChild(root_1, stream_62.nextNode()); + + } + stream_62.reset(); + adaptor.addChild(root_1, stream_simple_cond_expression.nextTree()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 2 : + // JPA.g:229:7: '(' conditional_expression ')' + { + root_0 = (Object)adaptor.nil(); + + char_literal134=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_conditional_factor1852); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal134_tree = (Object)adaptor.create(char_literal134); + adaptor.addChild(root_0, char_literal134_tree); + } + pushFollow(FOLLOW_conditional_expression_in_conditional_factor1853); + conditional_expression135=conditional_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, conditional_expression135.getTree()); + char_literal136=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_conditional_factor1854); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal136_tree = (Object)adaptor.create(char_literal136); + adaptor.addChild(root_0, char_literal136_tree); + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "conditional_factor" + + public static class simple_cond_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "simple_cond_expression" + // JPA.g:231:1: simple_cond_expression : ( comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression | date_macro_expression ); + public final JPAParser.simple_cond_expression_return simple_cond_expression() throws RecognitionException { + JPAParser.simple_cond_expression_return retval = new JPAParser.simple_cond_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.comparison_expression_return comparison_expression137 = null; + + JPAParser.between_expression_return between_expression138 = null; + + JPAParser.like_expression_return like_expression139 = null; + + JPAParser.in_expression_return in_expression140 = null; + + JPAParser.null_comparison_expression_return null_comparison_expression141 = null; + + JPAParser.empty_collection_comparison_expression_return empty_collection_comparison_expression142 = null; + + JPAParser.collection_member_expression_return collection_member_expression143 = null; + + JPAParser.exists_expression_return exists_expression144 = null; + + JPAParser.date_macro_expression_return date_macro_expression145 = null; + + + + try { + // JPA.g:232:5: ( comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression | date_macro_expression ) + int alt49=9; + alt49 = dfa49.predict(input); + switch (alt49) { + case 1 : + // JPA.g:232:7: comparison_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_comparison_expression_in_simple_cond_expression1866); + comparison_expression137=comparison_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_expression137.getTree()); + + } + break; + case 2 : + // JPA.g:233:7: between_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_between_expression_in_simple_cond_expression1874); + between_expression138=between_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, between_expression138.getTree()); + + } + break; + case 3 : + // JPA.g:234:7: like_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_like_expression_in_simple_cond_expression1882); + like_expression139=like_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, like_expression139.getTree()); + + } + break; + case 4 : + // JPA.g:235:7: in_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_in_expression_in_simple_cond_expression1890); + in_expression140=in_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, in_expression140.getTree()); + + } + break; + case 5 : + // JPA.g:236:7: null_comparison_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_null_comparison_expression_in_simple_cond_expression1898); + null_comparison_expression141=null_comparison_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, null_comparison_expression141.getTree()); + + } + break; + case 6 : + // JPA.g:237:7: empty_collection_comparison_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_empty_collection_comparison_expression_in_simple_cond_expression1906); + empty_collection_comparison_expression142=empty_collection_comparison_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, empty_collection_comparison_expression142.getTree()); + + } + break; + case 7 : + // JPA.g:238:7: collection_member_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_collection_member_expression_in_simple_cond_expression1914); + collection_member_expression143=collection_member_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, collection_member_expression143.getTree()); + + } + break; + case 8 : + // JPA.g:239:7: exists_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_exists_expression_in_simple_cond_expression1922); + exists_expression144=exists_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, exists_expression144.getTree()); + + } + break; + case 9 : + // JPA.g:240:7: date_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_macro_expression_in_simple_cond_expression1930); + date_macro_expression145=date_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_macro_expression145.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "simple_cond_expression" + + public static class date_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_macro_expression" + // JPA.g:242:1: date_macro_expression : ( date_between_macro_expression | date_before_macro_expression | date_after_macro_expression | date_equals_macro_expression | date_today_macro_expression ); + public final JPAParser.date_macro_expression_return date_macro_expression() throws RecognitionException { + JPAParser.date_macro_expression_return retval = new JPAParser.date_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.date_between_macro_expression_return date_between_macro_expression146 = null; + + JPAParser.date_before_macro_expression_return date_before_macro_expression147 = null; + + JPAParser.date_after_macro_expression_return date_after_macro_expression148 = null; + + JPAParser.date_equals_macro_expression_return date_equals_macro_expression149 = null; + + JPAParser.date_today_macro_expression_return date_today_macro_expression150 = null; + + + + try { + // JPA.g:243:5: ( date_between_macro_expression | date_before_macro_expression | date_after_macro_expression | date_equals_macro_expression | date_today_macro_expression ) + int alt50=5; + switch ( input.LA(1) ) { + case 63: + { + alt50=1; + } + break; + case 73: + { + alt50=2; + } + break; + case 74: + { + alt50=3; + } + break; + case 75: + { + alt50=4; + } + break; + case 76: + { + alt50=5; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 50, 0, input); + + throw nvae; + } + + switch (alt50) { + case 1 : + // JPA.g:243:7: date_between_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_between_macro_expression_in_date_macro_expression1942); + date_between_macro_expression146=date_between_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_between_macro_expression146.getTree()); + + } + break; + case 2 : + // JPA.g:244:7: date_before_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_before_macro_expression_in_date_macro_expression1950); + date_before_macro_expression147=date_before_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_before_macro_expression147.getTree()); + + } + break; + case 3 : + // JPA.g:245:7: date_after_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_after_macro_expression_in_date_macro_expression1958); + date_after_macro_expression148=date_after_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_after_macro_expression148.getTree()); + + } + break; + case 4 : + // JPA.g:246:7: date_equals_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_equals_macro_expression_in_date_macro_expression1966); + date_equals_macro_expression149=date_equals_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_equals_macro_expression149.getTree()); + + } + break; + case 5 : + // JPA.g:247:7: date_today_macro_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_date_today_macro_expression_in_date_macro_expression1974); + date_today_macro_expression150=date_today_macro_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, date_today_macro_expression150.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_macro_expression" + + public static class date_between_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_between_macro_expression" + // JPA.g:249:1: date_between_macro_expression : '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' ; + public final JPAParser.date_between_macro_expression_return date_between_macro_expression() throws RecognitionException { + JPAParser.date_between_macro_expression_return retval = new JPAParser.date_between_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal151=null; + Token char_literal152=null; + Token char_literal154=null; + Token string_literal155=null; + Token set156=null; + Token INT_NUMERAL157=null; + Token char_literal158=null; + Token string_literal159=null; + Token set160=null; + Token INT_NUMERAL161=null; + Token char_literal162=null; + Token set163=null; + Token char_literal164=null; + JPAParser.path_expression_return path_expression153 = null; + + + Object string_literal151_tree=null; + Object char_literal152_tree=null; + Object char_literal154_tree=null; + Object string_literal155_tree=null; + Object set156_tree=null; + Object INT_NUMERAL157_tree=null; + Object char_literal158_tree=null; + Object string_literal159_tree=null; + Object set160_tree=null; + Object INT_NUMERAL161_tree=null; + Object char_literal162_tree=null; + Object set163_tree=null; + Object char_literal164_tree=null; + + try { + // JPA.g:250:5: ( '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' ) + // JPA.g:250:7: '@BETWEEN' '(' path_expression ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' 'NOW' ( ( '+' | '-' ) INT_NUMERAL )? ',' ( 'YEAR' | 'MONTH' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ) ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal151=(Token)match(input,63,FOLLOW_63_in_date_between_macro_expression1986); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal151_tree = (Object)adaptor.create(string_literal151); + adaptor.addChild(root_0, string_literal151_tree); + } + char_literal152=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_between_macro_expression1988); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal152_tree = (Object)adaptor.create(char_literal152); + adaptor.addChild(root_0, char_literal152_tree); + } + pushFollow(FOLLOW_path_expression_in_date_between_macro_expression1990); + path_expression153=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression153.getTree()); + char_literal154=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression1992); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal154_tree = (Object)adaptor.create(char_literal154); + adaptor.addChild(root_0, char_literal154_tree); + } + string_literal155=(Token)match(input,64,FOLLOW_64_in_date_between_macro_expression1994); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal155_tree = (Object)adaptor.create(string_literal155); + adaptor.addChild(root_0, string_literal155_tree); + } + // JPA.g:250:48: ( ( '+' | '-' ) INT_NUMERAL )? + int alt51=2; + int LA51_0 = input.LA(1); + + if ( ((LA51_0>=65 && LA51_0<=66)) ) { + alt51=1; + } + switch (alt51) { + case 1 : + // JPA.g:250:49: ( '+' | '-' ) INT_NUMERAL + { + set156=(Token)input.LT(1); + if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set156)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + INT_NUMERAL157=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_date_between_macro_expression2005); if (state.failed) return retval; + if ( state.backtracking==0 ) { + INT_NUMERAL157_tree = (Object)adaptor.create(INT_NUMERAL157); + adaptor.addChild(root_0, INT_NUMERAL157_tree); + } + + } + break; + + } + + char_literal158=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression2009); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal158_tree = (Object)adaptor.create(char_literal158); + adaptor.addChild(root_0, char_literal158_tree); + } + string_literal159=(Token)match(input,64,FOLLOW_64_in_date_between_macro_expression2011); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal159_tree = (Object)adaptor.create(string_literal159); + adaptor.addChild(root_0, string_literal159_tree); + } + // JPA.g:250:85: ( ( '+' | '-' ) INT_NUMERAL )? + int alt52=2; + int LA52_0 = input.LA(1); + + if ( ((LA52_0>=65 && LA52_0<=66)) ) { + alt52=1; + } + switch (alt52) { + case 1 : + // JPA.g:250:86: ( '+' | '-' ) INT_NUMERAL + { + set160=(Token)input.LT(1); + if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set160)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + INT_NUMERAL161=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_date_between_macro_expression2022); if (state.failed) return retval; + if ( state.backtracking==0 ) { + INT_NUMERAL161_tree = (Object)adaptor.create(INT_NUMERAL161); + adaptor.addChild(root_0, INT_NUMERAL161_tree); + } + + } + break; + + } + + char_literal162=(Token)match(input,54,FOLLOW_54_in_date_between_macro_expression2026); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal162_tree = (Object)adaptor.create(char_literal162); + adaptor.addChild(root_0, char_literal162_tree); + } + set163=(Token)input.LT(1); + if ( (input.LA(1)>=67 && input.LA(1)<=72) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set163)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + char_literal164=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_between_macro_expression2051); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal164_tree = (Object)adaptor.create(char_literal164); + adaptor.addChild(root_0, char_literal164_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_between_macro_expression" + + public static class date_before_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_before_macro_expression" + // JPA.g:252:1: date_before_macro_expression : '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; + public final JPAParser.date_before_macro_expression_return date_before_macro_expression() throws RecognitionException { + JPAParser.date_before_macro_expression_return retval = new JPAParser.date_before_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal165=null; + Token char_literal166=null; + Token char_literal168=null; + Token char_literal171=null; + JPAParser.path_expression_return path_expression167 = null; + + JPAParser.path_expression_return path_expression169 = null; + + JPAParser.input_parameter_return input_parameter170 = null; + + + Object string_literal165_tree=null; + Object char_literal166_tree=null; + Object char_literal168_tree=null; + Object char_literal171_tree=null; + + try { + // JPA.g:253:5: ( '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) + // JPA.g:253:7: '@DATEBEFORE' '(' path_expression ',' ( path_expression | input_parameter ) ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal165=(Token)match(input,73,FOLLOW_73_in_date_before_macro_expression2063); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal165_tree = (Object)adaptor.create(string_literal165); + adaptor.addChild(root_0, string_literal165_tree); + } + char_literal166=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_before_macro_expression2065); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal166_tree = (Object)adaptor.create(char_literal166); + adaptor.addChild(root_0, char_literal166_tree); + } + pushFollow(FOLLOW_path_expression_in_date_before_macro_expression2067); + path_expression167=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression167.getTree()); + char_literal168=(Token)match(input,54,FOLLOW_54_in_date_before_macro_expression2069); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal168_tree = (Object)adaptor.create(char_literal168); + adaptor.addChild(root_0, char_literal168_tree); + } + // JPA.g:253:45: ( path_expression | input_parameter ) + int alt53=2; + int LA53_0 = input.LA(1); + + if ( (LA53_0==WORD) ) { + alt53=1; + } + else if ( (LA53_0==NAMED_PARAMETER||(LA53_0>=115 && LA53_0<=116)) ) { + alt53=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 53, 0, input); + + throw nvae; + } + switch (alt53) { + case 1 : + // JPA.g:253:46: path_expression + { + pushFollow(FOLLOW_path_expression_in_date_before_macro_expression2072); + path_expression169=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression169.getTree()); + + } + break; + case 2 : + // JPA.g:253:64: input_parameter + { + pushFollow(FOLLOW_input_parameter_in_date_before_macro_expression2076); + input_parameter170=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter170.getTree()); + + } + break; + + } + + char_literal171=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_before_macro_expression2079); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal171_tree = (Object)adaptor.create(char_literal171); + adaptor.addChild(root_0, char_literal171_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_before_macro_expression" + + public static class date_after_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_after_macro_expression" + // JPA.g:255:1: date_after_macro_expression : '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; + public final JPAParser.date_after_macro_expression_return date_after_macro_expression() throws RecognitionException { + JPAParser.date_after_macro_expression_return retval = new JPAParser.date_after_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal172=null; + Token char_literal173=null; + Token char_literal175=null; + Token char_literal178=null; + JPAParser.path_expression_return path_expression174 = null; + + JPAParser.path_expression_return path_expression176 = null; + + JPAParser.input_parameter_return input_parameter177 = null; + + + Object string_literal172_tree=null; + Object char_literal173_tree=null; + Object char_literal175_tree=null; + Object char_literal178_tree=null; + + try { + // JPA.g:256:5: ( '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) + // JPA.g:256:7: '@DATEAFTER' '(' path_expression ',' ( path_expression | input_parameter ) ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal172=(Token)match(input,74,FOLLOW_74_in_date_after_macro_expression2091); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal172_tree = (Object)adaptor.create(string_literal172); + adaptor.addChild(root_0, string_literal172_tree); + } + char_literal173=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_after_macro_expression2093); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal173_tree = (Object)adaptor.create(char_literal173); + adaptor.addChild(root_0, char_literal173_tree); + } + pushFollow(FOLLOW_path_expression_in_date_after_macro_expression2095); + path_expression174=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression174.getTree()); + char_literal175=(Token)match(input,54,FOLLOW_54_in_date_after_macro_expression2097); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal175_tree = (Object)adaptor.create(char_literal175); + adaptor.addChild(root_0, char_literal175_tree); + } + // JPA.g:256:44: ( path_expression | input_parameter ) + int alt54=2; + int LA54_0 = input.LA(1); + + if ( (LA54_0==WORD) ) { + alt54=1; + } + else if ( (LA54_0==NAMED_PARAMETER||(LA54_0>=115 && LA54_0<=116)) ) { + alt54=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 54, 0, input); + + throw nvae; + } + switch (alt54) { + case 1 : + // JPA.g:256:45: path_expression + { + pushFollow(FOLLOW_path_expression_in_date_after_macro_expression2100); + path_expression176=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression176.getTree()); + + } + break; + case 2 : + // JPA.g:256:63: input_parameter + { + pushFollow(FOLLOW_input_parameter_in_date_after_macro_expression2104); + input_parameter177=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter177.getTree()); + + } + break; + + } + + char_literal178=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_after_macro_expression2107); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal178_tree = (Object)adaptor.create(char_literal178); + adaptor.addChild(root_0, char_literal178_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_after_macro_expression" + + public static class date_equals_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_equals_macro_expression" + // JPA.g:258:1: date_equals_macro_expression : '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' ; + public final JPAParser.date_equals_macro_expression_return date_equals_macro_expression() throws RecognitionException { + JPAParser.date_equals_macro_expression_return retval = new JPAParser.date_equals_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal179=null; + Token char_literal180=null; + Token char_literal182=null; + Token char_literal185=null; + JPAParser.path_expression_return path_expression181 = null; + + JPAParser.path_expression_return path_expression183 = null; + + JPAParser.input_parameter_return input_parameter184 = null; + + + Object string_literal179_tree=null; + Object char_literal180_tree=null; + Object char_literal182_tree=null; + Object char_literal185_tree=null; + + try { + // JPA.g:259:5: ( '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' ) + // JPA.g:259:7: '@DATEEQUALS' '(' path_expression ',' ( path_expression | input_parameter ) ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal179=(Token)match(input,75,FOLLOW_75_in_date_equals_macro_expression2119); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal179_tree = (Object)adaptor.create(string_literal179); + adaptor.addChild(root_0, string_literal179_tree); + } + char_literal180=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_equals_macro_expression2121); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal180_tree = (Object)adaptor.create(char_literal180); + adaptor.addChild(root_0, char_literal180_tree); + } + pushFollow(FOLLOW_path_expression_in_date_equals_macro_expression2123); + path_expression181=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression181.getTree()); + char_literal182=(Token)match(input,54,FOLLOW_54_in_date_equals_macro_expression2125); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal182_tree = (Object)adaptor.create(char_literal182); + adaptor.addChild(root_0, char_literal182_tree); + } + // JPA.g:259:45: ( path_expression | input_parameter ) + int alt55=2; + int LA55_0 = input.LA(1); + + if ( (LA55_0==WORD) ) { + alt55=1; + } + else if ( (LA55_0==NAMED_PARAMETER||(LA55_0>=115 && LA55_0<=116)) ) { + alt55=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 55, 0, input); + + throw nvae; + } + switch (alt55) { + case 1 : + // JPA.g:259:46: path_expression + { + pushFollow(FOLLOW_path_expression_in_date_equals_macro_expression2128); + path_expression183=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression183.getTree()); + + } + break; + case 2 : + // JPA.g:259:64: input_parameter + { + pushFollow(FOLLOW_input_parameter_in_date_equals_macro_expression2132); + input_parameter184=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter184.getTree()); + + } + break; + + } + + char_literal185=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_equals_macro_expression2135); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal185_tree = (Object)adaptor.create(char_literal185); + adaptor.addChild(root_0, char_literal185_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_equals_macro_expression" + + public static class date_today_macro_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "date_today_macro_expression" + // JPA.g:261:1: date_today_macro_expression : '@TODAY' '(' path_expression ')' ; + public final JPAParser.date_today_macro_expression_return date_today_macro_expression() throws RecognitionException { + JPAParser.date_today_macro_expression_return retval = new JPAParser.date_today_macro_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal186=null; + Token char_literal187=null; + Token char_literal189=null; + JPAParser.path_expression_return path_expression188 = null; + + + Object string_literal186_tree=null; + Object char_literal187_tree=null; + Object char_literal189_tree=null; + + try { + // JPA.g:262:5: ( '@TODAY' '(' path_expression ')' ) + // JPA.g:262:7: '@TODAY' '(' path_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal186=(Token)match(input,76,FOLLOW_76_in_date_today_macro_expression2147); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal186_tree = (Object)adaptor.create(string_literal186); + adaptor.addChild(root_0, string_literal186_tree); + } + char_literal187=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_date_today_macro_expression2149); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal187_tree = (Object)adaptor.create(char_literal187); + adaptor.addChild(root_0, char_literal187_tree); + } + pushFollow(FOLLOW_path_expression_in_date_today_macro_expression2151); + path_expression188=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression188.getTree()); + char_literal189=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_date_today_macro_expression2153); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal189_tree = (Object)adaptor.create(char_literal189); + adaptor.addChild(root_0, char_literal189_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "date_today_macro_expression" + + public static class between_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "between_expression" + // JPA.g:264:1: between_expression : ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression | string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression | datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression ); + public final JPAParser.between_expression_return between_expression() throws RecognitionException { + JPAParser.between_expression_return retval = new JPAParser.between_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal191=null; + Token string_literal192=null; + Token string_literal194=null; + Token string_literal197=null; + Token string_literal198=null; + Token string_literal200=null; + Token string_literal203=null; + Token string_literal204=null; + Token string_literal206=null; + JPAParser.arithmetic_expression_return arithmetic_expression190 = null; + + JPAParser.arithmetic_expression_return arithmetic_expression193 = null; + + JPAParser.arithmetic_expression_return arithmetic_expression195 = null; + + JPAParser.string_expression_return string_expression196 = null; + + JPAParser.string_expression_return string_expression199 = null; + + JPAParser.string_expression_return string_expression201 = null; + + JPAParser.datetime_expression_return datetime_expression202 = null; + + JPAParser.datetime_expression_return datetime_expression205 = null; + + JPAParser.datetime_expression_return datetime_expression207 = null; + + + Object string_literal191_tree=null; + Object string_literal192_tree=null; + Object string_literal194_tree=null; + Object string_literal197_tree=null; + Object string_literal198_tree=null; + Object string_literal200_tree=null; + Object string_literal203_tree=null; + Object string_literal204_tree=null; + Object string_literal206_tree=null; + + try { + // JPA.g:265:5: ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression | string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression | datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression ) + int alt59=3; + alt59 = dfa59.predict(input); + switch (alt59) { + case 1 : + // JPA.g:265:7: arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_arithmetic_expression_in_between_expression2165); + arithmetic_expression190=arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression190.getTree()); + // JPA.g:265:29: ( 'NOT' )? + int alt56=2; + int LA56_0 = input.LA(1); + + if ( (LA56_0==62) ) { + alt56=1; + } + switch (alt56) { + case 1 : + // JPA.g:265:30: 'NOT' + { + string_literal191=(Token)match(input,62,FOLLOW_62_in_between_expression2168); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal191_tree = (Object)adaptor.create(string_literal191); + adaptor.addChild(root_0, string_literal191_tree); + } + + } + break; + + } + + string_literal192=(Token)match(input,77,FOLLOW_77_in_between_expression2172); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal192_tree = (Object)adaptor.create(string_literal192); + adaptor.addChild(root_0, string_literal192_tree); + } + pushFollow(FOLLOW_arithmetic_expression_in_between_expression2174); + arithmetic_expression193=arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression193.getTree()); + string_literal194=(Token)match(input,AND,FOLLOW_AND_in_between_expression2176); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal194_tree = (Object)adaptor.create(string_literal194); + adaptor.addChild(root_0, string_literal194_tree); + } + pushFollow(FOLLOW_arithmetic_expression_in_between_expression2178); + arithmetic_expression195=arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression195.getTree()); + + } + break; + case 2 : + // JPA.g:266:7: string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_string_expression_in_between_expression2186); + string_expression196=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression196.getTree()); + // JPA.g:266:25: ( 'NOT' )? + int alt57=2; + int LA57_0 = input.LA(1); + + if ( (LA57_0==62) ) { + alt57=1; + } + switch (alt57) { + case 1 : + // JPA.g:266:26: 'NOT' + { + string_literal197=(Token)match(input,62,FOLLOW_62_in_between_expression2189); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal197_tree = (Object)adaptor.create(string_literal197); + adaptor.addChild(root_0, string_literal197_tree); + } + + } + break; + + } + + string_literal198=(Token)match(input,77,FOLLOW_77_in_between_expression2193); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal198_tree = (Object)adaptor.create(string_literal198); + adaptor.addChild(root_0, string_literal198_tree); + } + pushFollow(FOLLOW_string_expression_in_between_expression2195); + string_expression199=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression199.getTree()); + string_literal200=(Token)match(input,AND,FOLLOW_AND_in_between_expression2197); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal200_tree = (Object)adaptor.create(string_literal200); + adaptor.addChild(root_0, string_literal200_tree); + } + pushFollow(FOLLOW_string_expression_in_between_expression2199); + string_expression201=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression201.getTree()); + + } + break; + case 3 : + // JPA.g:267:7: datetime_expression ( 'NOT' )? 'BETWEEN' datetime_expression 'AND' datetime_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_datetime_expression_in_between_expression2207); + datetime_expression202=datetime_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression202.getTree()); + // JPA.g:267:27: ( 'NOT' )? + int alt58=2; + int LA58_0 = input.LA(1); + + if ( (LA58_0==62) ) { + alt58=1; + } + switch (alt58) { + case 1 : + // JPA.g:267:28: 'NOT' + { + string_literal203=(Token)match(input,62,FOLLOW_62_in_between_expression2210); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal203_tree = (Object)adaptor.create(string_literal203); + adaptor.addChild(root_0, string_literal203_tree); + } + + } + break; + + } + + string_literal204=(Token)match(input,77,FOLLOW_77_in_between_expression2214); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal204_tree = (Object)adaptor.create(string_literal204); + adaptor.addChild(root_0, string_literal204_tree); + } + pushFollow(FOLLOW_datetime_expression_in_between_expression2216); + datetime_expression205=datetime_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression205.getTree()); + string_literal206=(Token)match(input,AND,FOLLOW_AND_in_between_expression2218); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal206_tree = (Object)adaptor.create(string_literal206); + adaptor.addChild(root_0, string_literal206_tree); + } + pushFollow(FOLLOW_datetime_expression_in_between_expression2220); + datetime_expression207=datetime_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression207.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "between_expression" + + public static class in_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "in_expression" + // JPA.g:269:1: in_expression : path_expression ( 'NOT' )? 'IN' in_expression_right_part ; + public final JPAParser.in_expression_return in_expression() throws RecognitionException { + JPAParser.in_expression_return retval = new JPAParser.in_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal209=null; + Token string_literal210=null; + JPAParser.path_expression_return path_expression208 = null; + + JPAParser.in_expression_right_part_return in_expression_right_part211 = null; + + + Object string_literal209_tree=null; + Object string_literal210_tree=null; + + try { + // JPA.g:270:5: ( path_expression ( 'NOT' )? 'IN' in_expression_right_part ) + // JPA.g:270:7: path_expression ( 'NOT' )? 'IN' in_expression_right_part + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_in_expression2232); + path_expression208=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression208.getTree()); + // JPA.g:270:23: ( 'NOT' )? + int alt60=2; + int LA60_0 = input.LA(1); + + if ( (LA60_0==62) ) { + alt60=1; + } + switch (alt60) { + case 1 : + // JPA.g:270:24: 'NOT' + { + string_literal209=(Token)match(input,62,FOLLOW_62_in_in_expression2235); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal209_tree = (Object)adaptor.create(string_literal209); + adaptor.addChild(root_0, string_literal209_tree); + } + + } + break; + + } + + string_literal210=(Token)match(input,58,FOLLOW_58_in_in_expression2239); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal210_tree = (Object)adaptor.create(string_literal210); + adaptor.addChild(root_0, string_literal210_tree); + } + pushFollow(FOLLOW_in_expression_right_part_in_in_expression2241); + in_expression_right_part211=in_expression_right_part(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, in_expression_right_part211.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "in_expression" + + public static class in_expression_right_part_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "in_expression_right_part" + // JPA.g:272:1: in_expression_right_part : ( '(' in_item ( ',' in_item )* ')' | subquery ); + public final JPAParser.in_expression_right_part_return in_expression_right_part() throws RecognitionException { + JPAParser.in_expression_right_part_return retval = new JPAParser.in_expression_right_part_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal212=null; + Token char_literal214=null; + Token char_literal216=null; + JPAParser.in_item_return in_item213 = null; + + JPAParser.in_item_return in_item215 = null; + + JPAParser.subquery_return subquery217 = null; + + + Object char_literal212_tree=null; + Object char_literal214_tree=null; + Object char_literal216_tree=null; + + try { + // JPA.g:273:5: ( '(' in_item ( ',' in_item )* ')' | subquery ) + int alt62=2; + int LA62_0 = input.LA(1); + + if ( (LA62_0==LPAREN) ) { + alt62=1; + } + else if ( (LA62_0==56) ) { + alt62=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 62, 0, input); + + throw nvae; + } + switch (alt62) { + case 1 : + // JPA.g:273:7: '(' in_item ( ',' in_item )* ')' + { + root_0 = (Object)adaptor.nil(); + + char_literal212=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_in_expression_right_part2253); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal212_tree = (Object)adaptor.create(char_literal212); + adaptor.addChild(root_0, char_literal212_tree); + } + pushFollow(FOLLOW_in_item_in_in_expression_right_part2255); + in_item213=in_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, in_item213.getTree()); + // JPA.g:273:19: ( ',' in_item )* + loop61: + do { + int alt61=2; + int LA61_0 = input.LA(1); + + if ( (LA61_0==54) ) { + alt61=1; + } + + + switch (alt61) { + case 1 : + // JPA.g:273:20: ',' in_item + { + char_literal214=(Token)match(input,54,FOLLOW_54_in_in_expression_right_part2258); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal214_tree = (Object)adaptor.create(char_literal214); + adaptor.addChild(root_0, char_literal214_tree); + } + pushFollow(FOLLOW_in_item_in_in_expression_right_part2260); + in_item215=in_item(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, in_item215.getTree()); + + } + break; + + default : + break loop61; + } + } while (true); + + char_literal216=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_in_expression_right_part2264); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal216_tree = (Object)adaptor.create(char_literal216); + adaptor.addChild(root_0, char_literal216_tree); + } + + } + break; + case 2 : + // JPA.g:274:7: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_in_expression_right_part2272); + subquery217=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery217.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "in_expression_right_part" + + public static class in_item_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "in_item" + // JPA.g:276:1: in_item : ( literal | input_parameter ); + public final JPAParser.in_item_return in_item() throws RecognitionException { + JPAParser.in_item_return retval = new JPAParser.in_item_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.literal_return literal218 = null; + + JPAParser.input_parameter_return input_parameter219 = null; + + + + try { + // JPA.g:277:5: ( literal | input_parameter ) + int alt63=2; + int LA63_0 = input.LA(1); + + if ( (LA63_0==WORD) ) { + alt63=1; + } + else if ( (LA63_0==NAMED_PARAMETER||(LA63_0>=115 && LA63_0<=116)) ) { + alt63=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 63, 0, input); + + throw nvae; + } + switch (alt63) { + case 1 : + // JPA.g:277:7: literal + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_literal_in_in_item2284); + literal218=literal(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, literal218.getTree()); + + } + break; + case 2 : + // JPA.g:278:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_in_item2292); + input_parameter219=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter219.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "in_item" + + public static class like_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "like_expression" + // JPA.g:280:1: like_expression : string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? ; + public final JPAParser.like_expression_return like_expression() throws RecognitionException { + JPAParser.like_expression_return retval = new JPAParser.like_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal221=null; + Token string_literal222=null; + Token string_literal225=null; + Token ESCAPE_CHARACTER226=null; + JPAParser.string_expression_return string_expression220 = null; + + JPAParser.pattern_value_return pattern_value223 = null; + + JPAParser.input_parameter_return input_parameter224 = null; + + + Object string_literal221_tree=null; + Object string_literal222_tree=null; + Object string_literal225_tree=null; + Object ESCAPE_CHARACTER226_tree=null; + + try { + // JPA.g:281:5: ( string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? ) + // JPA.g:281:7: string_expression ( 'NOT' )? 'LIKE' ( pattern_value | input_parameter ) ( 'ESCAPE' ESCAPE_CHARACTER )? + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_string_expression_in_like_expression2304); + string_expression220=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression220.getTree()); + // JPA.g:281:25: ( 'NOT' )? + int alt64=2; + int LA64_0 = input.LA(1); + + if ( (LA64_0==62) ) { + alt64=1; + } + switch (alt64) { + case 1 : + // JPA.g:281:26: 'NOT' + { + string_literal221=(Token)match(input,62,FOLLOW_62_in_like_expression2307); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal221_tree = (Object)adaptor.create(string_literal221); + adaptor.addChild(root_0, string_literal221_tree); + } + + } + break; + + } + + string_literal222=(Token)match(input,78,FOLLOW_78_in_like_expression2311); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal222_tree = (Object)adaptor.create(string_literal222); + adaptor.addChild(root_0, string_literal222_tree); + } + // JPA.g:281:41: ( pattern_value | input_parameter ) + int alt65=2; + int LA65_0 = input.LA(1); + + if ( (LA65_0==WORD) ) { + alt65=1; + } + else if ( (LA65_0==NAMED_PARAMETER||(LA65_0>=115 && LA65_0<=116)) ) { + alt65=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 65, 0, input); + + throw nvae; + } + switch (alt65) { + case 1 : + // JPA.g:281:42: pattern_value + { + pushFollow(FOLLOW_pattern_value_in_like_expression2314); + pattern_value223=pattern_value(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, pattern_value223.getTree()); + + } + break; + case 2 : + // JPA.g:281:58: input_parameter + { + pushFollow(FOLLOW_input_parameter_in_like_expression2318); + input_parameter224=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter224.getTree()); + + } + break; + + } + + // JPA.g:281:74: ( 'ESCAPE' ESCAPE_CHARACTER )? + int alt66=2; + int LA66_0 = input.LA(1); + + if ( (LA66_0==79) ) { + alt66=1; + } + switch (alt66) { + case 1 : + // JPA.g:281:75: 'ESCAPE' ESCAPE_CHARACTER + { + string_literal225=(Token)match(input,79,FOLLOW_79_in_like_expression2321); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal225_tree = (Object)adaptor.create(string_literal225); + adaptor.addChild(root_0, string_literal225_tree); + } + ESCAPE_CHARACTER226=(Token)match(input,ESCAPE_CHARACTER,FOLLOW_ESCAPE_CHARACTER_in_like_expression2323); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ESCAPE_CHARACTER226_tree = (Object)adaptor.create(ESCAPE_CHARACTER226); + adaptor.addChild(root_0, ESCAPE_CHARACTER226_tree); + } + + } + break; + + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "like_expression" + + public static class null_comparison_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "null_comparison_expression" + // JPA.g:283:1: null_comparison_expression : ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' ; + public final JPAParser.null_comparison_expression_return null_comparison_expression() throws RecognitionException { + JPAParser.null_comparison_expression_return retval = new JPAParser.null_comparison_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal229=null; + Token string_literal230=null; + Token string_literal231=null; + JPAParser.path_expression_return path_expression227 = null; + + JPAParser.input_parameter_return input_parameter228 = null; + + + Object string_literal229_tree=null; + Object string_literal230_tree=null; + Object string_literal231_tree=null; + + try { + // JPA.g:284:5: ( ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' ) + // JPA.g:284:7: ( path_expression | input_parameter ) 'IS' ( 'NOT' )? 'NULL' + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:284:7: ( path_expression | input_parameter ) + int alt67=2; + int LA67_0 = input.LA(1); + + if ( (LA67_0==WORD) ) { + alt67=1; + } + else if ( (LA67_0==NAMED_PARAMETER||(LA67_0>=115 && LA67_0<=116)) ) { + alt67=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 67, 0, input); + + throw nvae; + } + switch (alt67) { + case 1 : + // JPA.g:284:8: path_expression + { + pushFollow(FOLLOW_path_expression_in_null_comparison_expression2338); + path_expression227=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression227.getTree()); + + } + break; + case 2 : + // JPA.g:284:26: input_parameter + { + pushFollow(FOLLOW_input_parameter_in_null_comparison_expression2342); + input_parameter228=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter228.getTree()); + + } + break; + + } + + string_literal229=(Token)match(input,80,FOLLOW_80_in_null_comparison_expression2345); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal229_tree = (Object)adaptor.create(string_literal229); + adaptor.addChild(root_0, string_literal229_tree); + } + // JPA.g:284:48: ( 'NOT' )? + int alt68=2; + int LA68_0 = input.LA(1); + + if ( (LA68_0==62) ) { + alt68=1; + } + switch (alt68) { + case 1 : + // JPA.g:284:49: 'NOT' + { + string_literal230=(Token)match(input,62,FOLLOW_62_in_null_comparison_expression2348); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal230_tree = (Object)adaptor.create(string_literal230); + adaptor.addChild(root_0, string_literal230_tree); + } + + } + break; + + } + + string_literal231=(Token)match(input,81,FOLLOW_81_in_null_comparison_expression2352); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal231_tree = (Object)adaptor.create(string_literal231); + adaptor.addChild(root_0, string_literal231_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "null_comparison_expression" + + public static class empty_collection_comparison_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "empty_collection_comparison_expression" + // JPA.g:286:1: empty_collection_comparison_expression : path_expression 'IS' ( 'NOT' )? 'EMPTY' ; + public final JPAParser.empty_collection_comparison_expression_return empty_collection_comparison_expression() throws RecognitionException { + JPAParser.empty_collection_comparison_expression_return retval = new JPAParser.empty_collection_comparison_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal233=null; + Token string_literal234=null; + Token string_literal235=null; + JPAParser.path_expression_return path_expression232 = null; + + + Object string_literal233_tree=null; + Object string_literal234_tree=null; + Object string_literal235_tree=null; + + try { + // JPA.g:287:5: ( path_expression 'IS' ( 'NOT' )? 'EMPTY' ) + // JPA.g:287:7: path_expression 'IS' ( 'NOT' )? 'EMPTY' + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_empty_collection_comparison_expression2364); + path_expression232=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression232.getTree()); + string_literal233=(Token)match(input,80,FOLLOW_80_in_empty_collection_comparison_expression2366); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal233_tree = (Object)adaptor.create(string_literal233); + adaptor.addChild(root_0, string_literal233_tree); + } + // JPA.g:287:28: ( 'NOT' )? + int alt69=2; + int LA69_0 = input.LA(1); + + if ( (LA69_0==62) ) { + alt69=1; + } + switch (alt69) { + case 1 : + // JPA.g:287:29: 'NOT' + { + string_literal234=(Token)match(input,62,FOLLOW_62_in_empty_collection_comparison_expression2369); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal234_tree = (Object)adaptor.create(string_literal234); + adaptor.addChild(root_0, string_literal234_tree); + } + + } + break; + + } + + string_literal235=(Token)match(input,82,FOLLOW_82_in_empty_collection_comparison_expression2373); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal235_tree = (Object)adaptor.create(string_literal235); + adaptor.addChild(root_0, string_literal235_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "empty_collection_comparison_expression" + + public static class collection_member_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "collection_member_expression" + // JPA.g:289:1: collection_member_expression : entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression ; + public final JPAParser.collection_member_expression_return collection_member_expression() throws RecognitionException { + JPAParser.collection_member_expression_return retval = new JPAParser.collection_member_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal237=null; + Token string_literal238=null; + Token string_literal239=null; + JPAParser.entity_expression_return entity_expression236 = null; + + JPAParser.path_expression_return path_expression240 = null; + + + Object string_literal237_tree=null; + Object string_literal238_tree=null; + Object string_literal239_tree=null; + + try { + // JPA.g:290:5: ( entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression ) + // JPA.g:290:7: entity_expression ( 'NOT' )? 'MEMBER' ( 'OF' )? path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_entity_expression_in_collection_member_expression2385); + entity_expression236=entity_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression236.getTree()); + // JPA.g:290:25: ( 'NOT' )? + int alt70=2; + int LA70_0 = input.LA(1); + + if ( (LA70_0==62) ) { + alt70=1; + } + switch (alt70) { + case 1 : + // JPA.g:290:26: 'NOT' + { + string_literal237=(Token)match(input,62,FOLLOW_62_in_collection_member_expression2388); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal237_tree = (Object)adaptor.create(string_literal237); + adaptor.addChild(root_0, string_literal237_tree); + } + + } + break; + + } + + string_literal238=(Token)match(input,83,FOLLOW_83_in_collection_member_expression2392); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal238_tree = (Object)adaptor.create(string_literal238); + adaptor.addChild(root_0, string_literal238_tree); + } + // JPA.g:290:43: ( 'OF' )? + int alt71=2; + int LA71_0 = input.LA(1); + + if ( (LA71_0==84) ) { + alt71=1; + } + switch (alt71) { + case 1 : + // JPA.g:290:44: 'OF' + { + string_literal239=(Token)match(input,84,FOLLOW_84_in_collection_member_expression2395); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal239_tree = (Object)adaptor.create(string_literal239); + adaptor.addChild(root_0, string_literal239_tree); + } + + } + break; + + } + + pushFollow(FOLLOW_path_expression_in_collection_member_expression2399); + path_expression240=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression240.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "collection_member_expression" + + public static class exists_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "exists_expression" + // JPA.g:292:1: exists_expression : ( 'NOT' )? 'EXISTS' subquery ; + public final JPAParser.exists_expression_return exists_expression() throws RecognitionException { + JPAParser.exists_expression_return retval = new JPAParser.exists_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal241=null; + Token string_literal242=null; + JPAParser.subquery_return subquery243 = null; + + + Object string_literal241_tree=null; + Object string_literal242_tree=null; + + try { + // JPA.g:293:5: ( ( 'NOT' )? 'EXISTS' subquery ) + // JPA.g:293:7: ( 'NOT' )? 'EXISTS' subquery + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:293:7: ( 'NOT' )? + int alt72=2; + int LA72_0 = input.LA(1); + + if ( (LA72_0==62) ) { + alt72=1; + } + switch (alt72) { + case 1 : + // JPA.g:293:8: 'NOT' + { + string_literal241=(Token)match(input,62,FOLLOW_62_in_exists_expression2412); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal241_tree = (Object)adaptor.create(string_literal241); + adaptor.addChild(root_0, string_literal241_tree); + } + + } + break; + + } + + string_literal242=(Token)match(input,85,FOLLOW_85_in_exists_expression2416); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal242_tree = (Object)adaptor.create(string_literal242); + adaptor.addChild(root_0, string_literal242_tree); + } + pushFollow(FOLLOW_subquery_in_exists_expression2418); + subquery243=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery243.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "exists_expression" + + public static class all_or_any_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "all_or_any_expression" + // JPA.g:295:1: all_or_any_expression : ( 'ALL' | 'ANY' | 'SOME' ) subquery ; + public final JPAParser.all_or_any_expression_return all_or_any_expression() throws RecognitionException { + JPAParser.all_or_any_expression_return retval = new JPAParser.all_or_any_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set244=null; + JPAParser.subquery_return subquery245 = null; + + + Object set244_tree=null; + + try { + // JPA.g:296:5: ( ( 'ALL' | 'ANY' | 'SOME' ) subquery ) + // JPA.g:296:7: ( 'ALL' | 'ANY' | 'SOME' ) subquery + { + root_0 = (Object)adaptor.nil(); + + set244=(Token)input.LT(1); + if ( (input.LA(1)>=86 && input.LA(1)<=88) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set244)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + pushFollow(FOLLOW_subquery_in_all_or_any_expression2443); + subquery245=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery245.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "all_or_any_expression" + + public static class comparison_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "comparison_expression" + // JPA.g:298:1: comparison_expression : ( string_expression comparison_operator ( string_expression | all_or_any_expression ) | boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) ); + public final JPAParser.comparison_expression_return comparison_expression() throws RecognitionException { + JPAParser.comparison_expression_return retval = new JPAParser.comparison_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set251=null; + Token set255=null; + Token set263=null; + JPAParser.string_expression_return string_expression246 = null; + + JPAParser.comparison_operator_return comparison_operator247 = null; + + JPAParser.string_expression_return string_expression248 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression249 = null; + + JPAParser.boolean_expression_return boolean_expression250 = null; + + JPAParser.boolean_expression_return boolean_expression252 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression253 = null; + + JPAParser.enum_expression_return enum_expression254 = null; + + JPAParser.enum_expression_return enum_expression256 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression257 = null; + + JPAParser.datetime_expression_return datetime_expression258 = null; + + JPAParser.comparison_operator_return comparison_operator259 = null; + + JPAParser.datetime_expression_return datetime_expression260 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression261 = null; + + JPAParser.entity_expression_return entity_expression262 = null; + + JPAParser.entity_expression_return entity_expression264 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression265 = null; + + JPAParser.arithmetic_expression_return arithmetic_expression266 = null; + + JPAParser.comparison_operator_return comparison_operator267 = null; + + JPAParser.arithmetic_expression_return arithmetic_expression268 = null; + + JPAParser.all_or_any_expression_return all_or_any_expression269 = null; + + + Object set251_tree=null; + Object set255_tree=null; + Object set263_tree=null; + + try { + // JPA.g:299:5: ( string_expression comparison_operator ( string_expression | all_or_any_expression ) | boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) ) + int alt79=6; + alt79 = dfa79.predict(input); + switch (alt79) { + case 1 : + // JPA.g:299:7: string_expression comparison_operator ( string_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_string_expression_in_comparison_expression2455); + string_expression246=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression246.getTree()); + pushFollow(FOLLOW_comparison_operator_in_comparison_expression2457); + comparison_operator247=comparison_operator(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator247.getTree()); + // JPA.g:299:45: ( string_expression | all_or_any_expression ) + int alt73=2; + int LA73_0 = input.LA(1); + + if ( ((LA73_0>=AVG && LA73_0<=COUNT)||LA73_0==STRINGLITERAL||(LA73_0>=WORD && LA73_0<=NAMED_PARAMETER)||LA73_0==56||(LA73_0>=106 && LA73_0<=110)||(LA73_0>=115 && LA73_0<=116)) ) { + alt73=1; + } + else if ( ((LA73_0>=86 && LA73_0<=88)) ) { + alt73=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 73, 0, input); + + throw nvae; + } + switch (alt73) { + case 1 : + // JPA.g:299:46: string_expression + { + pushFollow(FOLLOW_string_expression_in_comparison_expression2460); + string_expression248=string_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_expression248.getTree()); + + } + break; + case 2 : + // JPA.g:299:66: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2464); + all_or_any_expression249=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression249.getTree()); + + } + break; + + } + + + } + break; + case 2 : + // JPA.g:300:7: boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_boolean_expression_in_comparison_expression2473); + boolean_expression250=boolean_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_expression250.getTree()); + set251=(Token)input.LT(1); + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set251)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:300:39: ( boolean_expression | all_or_any_expression ) + int alt74=2; + int LA74_0 = input.LA(1); + + if ( ((LA74_0>=WORD && LA74_0<=NAMED_PARAMETER)||LA74_0==56||(LA74_0>=115 && LA74_0<=116)||(LA74_0>=118 && LA74_0<=119)) ) { + alt74=1; + } + else if ( ((LA74_0>=86 && LA74_0<=88)) ) { + alt74=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 74, 0, input); + + throw nvae; + } + switch (alt74) { + case 1 : + // JPA.g:300:40: boolean_expression + { + pushFollow(FOLLOW_boolean_expression_in_comparison_expression2484); + boolean_expression252=boolean_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_expression252.getTree()); + + } + break; + case 2 : + // JPA.g:300:61: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2488); + all_or_any_expression253=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression253.getTree()); + + } + break; + + } + + + } + break; + case 3 : + // JPA.g:301:7: enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_enum_expression_in_comparison_expression2497); + enum_expression254=enum_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_expression254.getTree()); + set255=(Token)input.LT(1); + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set255)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:301:34: ( enum_expression | all_or_any_expression ) + int alt75=2; + int LA75_0 = input.LA(1); + + if ( ((LA75_0>=WORD && LA75_0<=NAMED_PARAMETER)||LA75_0==56||(LA75_0>=115 && LA75_0<=116)) ) { + alt75=1; + } + else if ( ((LA75_0>=86 && LA75_0<=88)) ) { + alt75=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 75, 0, input); + + throw nvae; + } + switch (alt75) { + case 1 : + // JPA.g:301:35: enum_expression + { + pushFollow(FOLLOW_enum_expression_in_comparison_expression2506); + enum_expression256=enum_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_expression256.getTree()); + + } + break; + case 2 : + // JPA.g:301:53: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2510); + all_or_any_expression257=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression257.getTree()); + + } + break; + + } + + + } + break; + case 4 : + // JPA.g:302:7: datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_datetime_expression_in_comparison_expression2519); + datetime_expression258=datetime_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression258.getTree()); + pushFollow(FOLLOW_comparison_operator_in_comparison_expression2521); + comparison_operator259=comparison_operator(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator259.getTree()); + // JPA.g:302:47: ( datetime_expression | all_or_any_expression ) + int alt76=2; + int LA76_0 = input.LA(1); + + if ( ((LA76_0>=AVG && LA76_0<=COUNT)||(LA76_0>=WORD && LA76_0<=NAMED_PARAMETER)||LA76_0==56||(LA76_0>=103 && LA76_0<=105)||(LA76_0>=115 && LA76_0<=116)) ) { + alt76=1; + } + else if ( ((LA76_0>=86 && LA76_0<=88)) ) { + alt76=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 76, 0, input); + + throw nvae; + } + switch (alt76) { + case 1 : + // JPA.g:302:48: datetime_expression + { + pushFollow(FOLLOW_datetime_expression_in_comparison_expression2524); + datetime_expression260=datetime_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_expression260.getTree()); + + } + break; + case 2 : + // JPA.g:302:70: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2528); + all_or_any_expression261=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression261.getTree()); + + } + break; + + } + + + } + break; + case 5 : + // JPA.g:303:7: entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_entity_expression_in_comparison_expression2537); + entity_expression262=entity_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression262.getTree()); + set263=(Token)input.LT(1); + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set263)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:303:38: ( entity_expression | all_or_any_expression ) + int alt77=2; + int LA77_0 = input.LA(1); + + if ( ((LA77_0>=WORD && LA77_0<=NAMED_PARAMETER)||(LA77_0>=115 && LA77_0<=116)) ) { + alt77=1; + } + else if ( ((LA77_0>=86 && LA77_0<=88)) ) { + alt77=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 77, 0, input); + + throw nvae; + } + switch (alt77) { + case 1 : + // JPA.g:303:39: entity_expression + { + pushFollow(FOLLOW_entity_expression_in_comparison_expression2548); + entity_expression264=entity_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, entity_expression264.getTree()); + + } + break; + case 2 : + // JPA.g:303:59: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2552); + all_or_any_expression265=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression265.getTree()); + + } + break; + + } + + + } + break; + case 6 : + // JPA.g:304:7: arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_arithmetic_expression_in_comparison_expression2561); + arithmetic_expression266=arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression266.getTree()); + pushFollow(FOLLOW_comparison_operator_in_comparison_expression2563); + comparison_operator267=comparison_operator(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, comparison_operator267.getTree()); + // JPA.g:304:49: ( arithmetic_expression | all_or_any_expression ) + int alt78=2; + int LA78_0 = input.LA(1); + + if ( ((LA78_0>=AVG && LA78_0<=COUNT)||LA78_0==LPAREN||LA78_0==INT_NUMERAL||(LA78_0>=WORD && LA78_0<=NAMED_PARAMETER)||LA78_0==56||(LA78_0>=65 && LA78_0<=66)||(LA78_0>=97 && LA78_0<=102)||(LA78_0>=114 && LA78_0<=116)) ) { + alt78=1; + } + else if ( ((LA78_0>=86 && LA78_0<=88)) ) { + alt78=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 78, 0, input); + + throw nvae; + } + switch (alt78) { + case 1 : + // JPA.g:304:50: arithmetic_expression + { + pushFollow(FOLLOW_arithmetic_expression_in_comparison_expression2566); + arithmetic_expression268=arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_expression268.getTree()); + + } + break; + case 2 : + // JPA.g:304:74: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_comparison_expression2570); + all_or_any_expression269=all_or_any_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, all_or_any_expression269.getTree()); + + } + break; + + } + + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "comparison_expression" + + public static class comparison_operator_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "comparison_operator" + // JPA.g:306:1: comparison_operator : ( '=' | '>' | '>=' | '<' | '<=' | '<>' ); + public final JPAParser.comparison_operator_return comparison_operator() throws RecognitionException { + JPAParser.comparison_operator_return retval = new JPAParser.comparison_operator_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set270=null; + + Object set270_tree=null; + + try { + // JPA.g:307:5: ( '=' | '>' | '>=' | '<' | '<=' | '<>' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set270=(Token)input.LT(1); + if ( (input.LA(1)>=89 && input.LA(1)<=94) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set270)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "comparison_operator" + + public static class arithmetic_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "arithmetic_expression" + // JPA.g:314:1: arithmetic_expression : ( simple_arithmetic_expression | subquery ); + public final JPAParser.arithmetic_expression_return arithmetic_expression() throws RecognitionException { + JPAParser.arithmetic_expression_return retval = new JPAParser.arithmetic_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression271 = null; + + JPAParser.subquery_return subquery272 = null; + + + + try { + // JPA.g:315:5: ( simple_arithmetic_expression | subquery ) + int alt80=2; + int LA80_0 = input.LA(1); + + if ( ((LA80_0>=AVG && LA80_0<=COUNT)||LA80_0==LPAREN||LA80_0==INT_NUMERAL||(LA80_0>=WORD && LA80_0<=NAMED_PARAMETER)||(LA80_0>=65 && LA80_0<=66)||(LA80_0>=97 && LA80_0<=102)||(LA80_0>=114 && LA80_0<=116)) ) { + alt80=1; + } + else if ( (LA80_0==56) ) { + alt80=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 80, 0, input); + + throw nvae; + } + switch (alt80) { + case 1 : + // JPA.g:315:7: simple_arithmetic_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_simple_arithmetic_expression_in_arithmetic_expression2635); + simple_arithmetic_expression271=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression271.getTree()); + + } + break; + case 2 : + // JPA.g:316:7: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_arithmetic_expression2643); + subquery272=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery272.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "arithmetic_expression" + + public static class simple_arithmetic_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "simple_arithmetic_expression" + // JPA.g:318:1: simple_arithmetic_expression : ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* ; + public final JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression() throws RecognitionException { + JPAParser.simple_arithmetic_expression_return retval = new JPAParser.simple_arithmetic_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set274=null; + JPAParser.arithmetic_term_return arithmetic_term273 = null; + + JPAParser.arithmetic_term_return arithmetic_term275 = null; + + + Object set274_tree=null; + + try { + // JPA.g:319:5: ( ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* ) + // JPA.g:319:7: ( arithmetic_term ) ( ( '+' | '-' ) arithmetic_term )* + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:319:7: ( arithmetic_term ) + // JPA.g:319:8: arithmetic_term + { + pushFollow(FOLLOW_arithmetic_term_in_simple_arithmetic_expression2656); + arithmetic_term273=arithmetic_term(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_term273.getTree()); + + } + + // JPA.g:319:25: ( ( '+' | '-' ) arithmetic_term )* + loop81: + do { + int alt81=2; + int LA81_0 = input.LA(1); + + if ( ((LA81_0>=65 && LA81_0<=66)) ) { + alt81=1; + } + + + switch (alt81) { + case 1 : + // JPA.g:319:26: ( '+' | '-' ) arithmetic_term + { + set274=(Token)input.LT(1); + if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set274)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + pushFollow(FOLLOW_arithmetic_term_in_simple_arithmetic_expression2670); + arithmetic_term275=arithmetic_term(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_term275.getTree()); + + } + break; + + default : + break loop81; + } + } while (true); + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "simple_arithmetic_expression" + + public static class arithmetic_term_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "arithmetic_term" + // JPA.g:321:1: arithmetic_term : ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* ; + public final JPAParser.arithmetic_term_return arithmetic_term() throws RecognitionException { + JPAParser.arithmetic_term_return retval = new JPAParser.arithmetic_term_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set277=null; + JPAParser.arithmetic_factor_return arithmetic_factor276 = null; + + JPAParser.arithmetic_factor_return arithmetic_factor278 = null; + + + Object set277_tree=null; + + try { + // JPA.g:322:5: ( ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* ) + // JPA.g:322:7: ( arithmetic_factor ) ( ( '*' | '/' ) arithmetic_factor )* + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:322:7: ( arithmetic_factor ) + // JPA.g:322:8: arithmetic_factor + { + pushFollow(FOLLOW_arithmetic_factor_in_arithmetic_term2685); + arithmetic_factor276=arithmetic_factor(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_factor276.getTree()); + + } + + // JPA.g:322:27: ( ( '*' | '/' ) arithmetic_factor )* + loop82: + do { + int alt82=2; + int LA82_0 = input.LA(1); + + if ( ((LA82_0>=95 && LA82_0<=96)) ) { + alt82=1; + } + + + switch (alt82) { + case 1 : + // JPA.g:322:28: ( '*' | '/' ) arithmetic_factor + { + set277=(Token)input.LT(1); + if ( (input.LA(1)>=95 && input.LA(1)<=96) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set277)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + pushFollow(FOLLOW_arithmetic_factor_in_arithmetic_term2699); + arithmetic_factor278=arithmetic_factor(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_factor278.getTree()); + + } + break; + + default : + break loop82; + } + } while (true); + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "arithmetic_term" + + public static class arithmetic_factor_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "arithmetic_factor" + // JPA.g:324:1: arithmetic_factor : ( '+' | '-' )? arithmetic_primary ; + public final JPAParser.arithmetic_factor_return arithmetic_factor() throws RecognitionException { + JPAParser.arithmetic_factor_return retval = new JPAParser.arithmetic_factor_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set279=null; + JPAParser.arithmetic_primary_return arithmetic_primary280 = null; + + + Object set279_tree=null; + + try { + // JPA.g:325:5: ( ( '+' | '-' )? arithmetic_primary ) + // JPA.g:325:7: ( '+' | '-' )? arithmetic_primary + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:325:7: ( '+' | '-' )? + int alt83=2; + int LA83_0 = input.LA(1); + + if ( ((LA83_0>=65 && LA83_0<=66)) ) { + alt83=1; + } + switch (alt83) { + case 1 : + // JPA.g: + { + set279=(Token)input.LT(1); + if ( (input.LA(1)>=65 && input.LA(1)<=66) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set279)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + break; + + } + + pushFollow(FOLLOW_arithmetic_primary_in_arithmetic_factor2724); + arithmetic_primary280=arithmetic_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, arithmetic_primary280.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "arithmetic_factor" + + public static class arithmetic_primary_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "arithmetic_primary" + // JPA.g:327:1: arithmetic_primary : ( path_expression | numeric_literal | '(' simple_arithmetic_expression ')' | input_parameter | functions_returning_numerics | aggregate_expression ); + public final JPAParser.arithmetic_primary_return arithmetic_primary() throws RecognitionException { + JPAParser.arithmetic_primary_return retval = new JPAParser.arithmetic_primary_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal283=null; + Token char_literal285=null; + JPAParser.path_expression_return path_expression281 = null; + + JPAParser.numeric_literal_return numeric_literal282 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression284 = null; + + JPAParser.input_parameter_return input_parameter286 = null; + + JPAParser.functions_returning_numerics_return functions_returning_numerics287 = null; + + JPAParser.aggregate_expression_return aggregate_expression288 = null; + + + Object char_literal283_tree=null; + Object char_literal285_tree=null; + + try { + // JPA.g:328:5: ( path_expression | numeric_literal | '(' simple_arithmetic_expression ')' | input_parameter | functions_returning_numerics | aggregate_expression ) + int alt84=6; + switch ( input.LA(1) ) { + case WORD: + { + alt84=1; + } + break; + case INT_NUMERAL: + case 114: + { + alt84=2; + } + break; + case LPAREN: + { + alt84=3; + } + break; + case NAMED_PARAMETER: + case 115: + case 116: + { + alt84=4; + } + break; + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + { + alt84=5; + } + break; + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + { + alt84=6; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 84, 0, input); + + throw nvae; + } + + switch (alt84) { + case 1 : + // JPA.g:328:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_arithmetic_primary2736); + path_expression281=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression281.getTree()); + + } + break; + case 2 : + // JPA.g:329:7: numeric_literal + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_numeric_literal_in_arithmetic_primary2744); + numeric_literal282=numeric_literal(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, numeric_literal282.getTree()); + + } + break; + case 3 : + // JPA.g:330:7: '(' simple_arithmetic_expression ')' + { + root_0 = (Object)adaptor.nil(); + + char_literal283=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_arithmetic_primary2752); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal283_tree = (Object)adaptor.create(char_literal283); + adaptor.addChild(root_0, char_literal283_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_arithmetic_primary2753); + simple_arithmetic_expression284=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression284.getTree()); + char_literal285=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_arithmetic_primary2754); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal285_tree = (Object)adaptor.create(char_literal285); + adaptor.addChild(root_0, char_literal285_tree); + } + + } + break; + case 4 : + // JPA.g:331:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_arithmetic_primary2762); + input_parameter286=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter286.getTree()); + + } + break; + case 5 : + // JPA.g:332:7: functions_returning_numerics + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_functions_returning_numerics_in_arithmetic_primary2770); + functions_returning_numerics287=functions_returning_numerics(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_numerics287.getTree()); + + } + break; + case 6 : + // JPA.g:333:7: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_arithmetic_primary2778); + aggregate_expression288=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression288.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "arithmetic_primary" + + public static class string_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "string_expression" + // JPA.g:335:1: string_expression : ( string_primary | subquery ); + public final JPAParser.string_expression_return string_expression() throws RecognitionException { + JPAParser.string_expression_return retval = new JPAParser.string_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.string_primary_return string_primary289 = null; + + JPAParser.subquery_return subquery290 = null; + + + + try { + // JPA.g:336:5: ( string_primary | subquery ) + int alt85=2; + int LA85_0 = input.LA(1); + + if ( ((LA85_0>=AVG && LA85_0<=COUNT)||LA85_0==STRINGLITERAL||(LA85_0>=WORD && LA85_0<=NAMED_PARAMETER)||(LA85_0>=106 && LA85_0<=110)||(LA85_0>=115 && LA85_0<=116)) ) { + alt85=1; + } + else if ( (LA85_0==56) ) { + alt85=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 85, 0, input); + + throw nvae; + } + switch (alt85) { + case 1 : + // JPA.g:336:7: string_primary + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_string_primary_in_string_expression2790); + string_primary289=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary289.getTree()); + + } + break; + case 2 : + // JPA.g:336:24: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_string_expression2794); + subquery290=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery290.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "string_expression" + + public static class string_primary_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "string_primary" + // JPA.g:338:1: string_primary : ( path_expression | STRINGLITERAL | input_parameter | functions_returning_strings | aggregate_expression ); + public final JPAParser.string_primary_return string_primary() throws RecognitionException { + JPAParser.string_primary_return retval = new JPAParser.string_primary_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token STRINGLITERAL292=null; + JPAParser.path_expression_return path_expression291 = null; + + JPAParser.input_parameter_return input_parameter293 = null; + + JPAParser.functions_returning_strings_return functions_returning_strings294 = null; + + JPAParser.aggregate_expression_return aggregate_expression295 = null; + + + Object STRINGLITERAL292_tree=null; + + try { + // JPA.g:339:5: ( path_expression | STRINGLITERAL | input_parameter | functions_returning_strings | aggregate_expression ) + int alt86=5; + switch ( input.LA(1) ) { + case WORD: + { + alt86=1; + } + break; + case STRINGLITERAL: + { + alt86=2; + } + break; + case NAMED_PARAMETER: + case 115: + case 116: + { + alt86=3; + } + break; + case 106: + case 107: + case 108: + case 109: + case 110: + { + alt86=4; + } + break; + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + { + alt86=5; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 86, 0, input); + + throw nvae; + } + + switch (alt86) { + case 1 : + // JPA.g:339:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_string_primary2806); + path_expression291=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression291.getTree()); + + } + break; + case 2 : + // JPA.g:340:7: STRINGLITERAL + { + root_0 = (Object)adaptor.nil(); + + STRINGLITERAL292=(Token)match(input,STRINGLITERAL,FOLLOW_STRINGLITERAL_in_string_primary2814); if (state.failed) return retval; + if ( state.backtracking==0 ) { + STRINGLITERAL292_tree = (Object)adaptor.create(STRINGLITERAL292); + adaptor.addChild(root_0, STRINGLITERAL292_tree); + } + + } + break; + case 3 : + // JPA.g:341:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_string_primary2822); + input_parameter293=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter293.getTree()); + + } + break; + case 4 : + // JPA.g:342:7: functions_returning_strings + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_functions_returning_strings_in_string_primary2830); + functions_returning_strings294=functions_returning_strings(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_strings294.getTree()); + + } + break; + case 5 : + // JPA.g:343:7: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_string_primary2838); + aggregate_expression295=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression295.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "string_primary" + + public static class datetime_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "datetime_expression" + // JPA.g:345:1: datetime_expression : ( datetime_primary | subquery ); + public final JPAParser.datetime_expression_return datetime_expression() throws RecognitionException { + JPAParser.datetime_expression_return retval = new JPAParser.datetime_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.datetime_primary_return datetime_primary296 = null; + + JPAParser.subquery_return subquery297 = null; + + + + try { + // JPA.g:346:5: ( datetime_primary | subquery ) + int alt87=2; + int LA87_0 = input.LA(1); + + if ( ((LA87_0>=AVG && LA87_0<=COUNT)||(LA87_0>=WORD && LA87_0<=NAMED_PARAMETER)||(LA87_0>=103 && LA87_0<=105)||(LA87_0>=115 && LA87_0<=116)) ) { + alt87=1; + } + else if ( (LA87_0==56) ) { + alt87=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 87, 0, input); + + throw nvae; + } + switch (alt87) { + case 1 : + // JPA.g:346:7: datetime_primary + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_datetime_primary_in_datetime_expression2850); + datetime_primary296=datetime_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetime_primary296.getTree()); + + } + break; + case 2 : + // JPA.g:347:7: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_datetime_expression2858); + subquery297=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery297.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "datetime_expression" + + public static class datetime_primary_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "datetime_primary" + // JPA.g:349:1: datetime_primary : ( path_expression | input_parameter | functions_returning_datetime | aggregate_expression ); + public final JPAParser.datetime_primary_return datetime_primary() throws RecognitionException { + JPAParser.datetime_primary_return retval = new JPAParser.datetime_primary_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression298 = null; + + JPAParser.input_parameter_return input_parameter299 = null; + + JPAParser.functions_returning_datetime_return functions_returning_datetime300 = null; + + JPAParser.aggregate_expression_return aggregate_expression301 = null; + + + + try { + // JPA.g:350:5: ( path_expression | input_parameter | functions_returning_datetime | aggregate_expression ) + int alt88=4; + switch ( input.LA(1) ) { + case WORD: + { + alt88=1; + } + break; + case NAMED_PARAMETER: + case 115: + case 116: + { + alt88=2; + } + break; + case 103: + case 104: + case 105: + { + alt88=3; + } + break; + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + { + alt88=4; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 88, 0, input); + + throw nvae; + } + + switch (alt88) { + case 1 : + // JPA.g:350:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_datetime_primary2870); + path_expression298=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression298.getTree()); + + } + break; + case 2 : + // JPA.g:351:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_datetime_primary2878); + input_parameter299=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter299.getTree()); + + } + break; + case 3 : + // JPA.g:352:7: functions_returning_datetime + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_functions_returning_datetime_in_datetime_primary2886); + functions_returning_datetime300=functions_returning_datetime(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, functions_returning_datetime300.getTree()); + + } + break; + case 4 : + // JPA.g:353:7: aggregate_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_aggregate_expression_in_datetime_primary2894); + aggregate_expression301=aggregate_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, aggregate_expression301.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "datetime_primary" + + public static class boolean_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "boolean_expression" + // JPA.g:355:1: boolean_expression : ( boolean_primary | subquery ); + public final JPAParser.boolean_expression_return boolean_expression() throws RecognitionException { + JPAParser.boolean_expression_return retval = new JPAParser.boolean_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.boolean_primary_return boolean_primary302 = null; + + JPAParser.subquery_return subquery303 = null; + + + + try { + // JPA.g:356:5: ( boolean_primary | subquery ) + int alt89=2; + int LA89_0 = input.LA(1); + + if ( ((LA89_0>=WORD && LA89_0<=NAMED_PARAMETER)||(LA89_0>=115 && LA89_0<=116)||(LA89_0>=118 && LA89_0<=119)) ) { + alt89=1; + } + else if ( (LA89_0==56) ) { + alt89=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 89, 0, input); + + throw nvae; + } + switch (alt89) { + case 1 : + // JPA.g:356:7: boolean_primary + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_boolean_primary_in_boolean_expression2906); + boolean_primary302=boolean_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_primary302.getTree()); + + } + break; + case 2 : + // JPA.g:357:7: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_boolean_expression2914); + subquery303=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery303.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "boolean_expression" + + public static class boolean_primary_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "boolean_primary" + // JPA.g:359:1: boolean_primary : ( path_expression | boolean_literal | input_parameter ); + public final JPAParser.boolean_primary_return boolean_primary() throws RecognitionException { + JPAParser.boolean_primary_return retval = new JPAParser.boolean_primary_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression304 = null; + + JPAParser.boolean_literal_return boolean_literal305 = null; + + JPAParser.input_parameter_return input_parameter306 = null; + + + + try { + // JPA.g:360:5: ( path_expression | boolean_literal | input_parameter ) + int alt90=3; + switch ( input.LA(1) ) { + case WORD: + { + alt90=1; + } + break; + case 118: + case 119: + { + alt90=2; + } + break; + case NAMED_PARAMETER: + case 115: + case 116: + { + alt90=3; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 90, 0, input); + + throw nvae; + } + + switch (alt90) { + case 1 : + // JPA.g:360:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_boolean_primary2926); + path_expression304=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression304.getTree()); + + } + break; + case 2 : + // JPA.g:361:7: boolean_literal + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_boolean_literal_in_boolean_primary2934); + boolean_literal305=boolean_literal(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, boolean_literal305.getTree()); + + } + break; + case 3 : + // JPA.g:362:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_boolean_primary2942); + input_parameter306=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter306.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "boolean_primary" + + public static class enum_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "enum_expression" + // JPA.g:364:1: enum_expression : ( enum_primary | subquery ); + public final JPAParser.enum_expression_return enum_expression() throws RecognitionException { + JPAParser.enum_expression_return retval = new JPAParser.enum_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.enum_primary_return enum_primary307 = null; + + JPAParser.subquery_return subquery308 = null; + + + + try { + // JPA.g:365:5: ( enum_primary | subquery ) + int alt91=2; + int LA91_0 = input.LA(1); + + if ( ((LA91_0>=WORD && LA91_0<=NAMED_PARAMETER)||(LA91_0>=115 && LA91_0<=116)) ) { + alt91=1; + } + else if ( (LA91_0==56) ) { + alt91=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 91, 0, input); + + throw nvae; + } + switch (alt91) { + case 1 : + // JPA.g:365:7: enum_primary + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_enum_primary_in_enum_expression2954); + enum_primary307=enum_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_primary307.getTree()); + + } + break; + case 2 : + // JPA.g:366:7: subquery + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_subquery_in_enum_expression2962); + subquery308=subquery(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, subquery308.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "enum_expression" + + public static class enum_primary_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "enum_primary" + // JPA.g:368:1: enum_primary : ( path_expression | enum_literal | input_parameter ); + public final JPAParser.enum_primary_return enum_primary() throws RecognitionException { + JPAParser.enum_primary_return retval = new JPAParser.enum_primary_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression309 = null; + + JPAParser.enum_literal_return enum_literal310 = null; + + JPAParser.input_parameter_return input_parameter311 = null; + + + + try { + // JPA.g:369:5: ( path_expression | enum_literal | input_parameter ) + int alt92=3; + int LA92_0 = input.LA(1); + + if ( (LA92_0==WORD) ) { + int LA92_1 = input.LA(2); + + if ( (LA92_1==57) ) { + alt92=1; + } + else if ( (LA92_1==EOF||LA92_1==HAVING||(LA92_1>=OR && LA92_1<=AND)||LA92_1==RPAREN||(LA92_1>=ORDER && LA92_1<=GROUP)||(LA92_1>=89 && LA92_1<=90)) ) { + alt92=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 92, 1, input); + + throw nvae; + } + } + else if ( (LA92_0==NAMED_PARAMETER||(LA92_0>=115 && LA92_0<=116)) ) { + alt92=3; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 92, 0, input); + + throw nvae; + } + switch (alt92) { + case 1 : + // JPA.g:369:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_enum_primary2974); + path_expression309=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression309.getTree()); + + } + break; + case 2 : + // JPA.g:370:7: enum_literal + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_enum_literal_in_enum_primary2982); + enum_literal310=enum_literal(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, enum_literal310.getTree()); + + } + break; + case 3 : + // JPA.g:371:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_enum_primary2990); + input_parameter311=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter311.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "enum_primary" + + public static class entity_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "entity_expression" + // JPA.g:373:1: entity_expression : ( path_expression | simple_entity_expression ); + public final JPAParser.entity_expression_return entity_expression() throws RecognitionException { + JPAParser.entity_expression_return retval = new JPAParser.entity_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.path_expression_return path_expression312 = null; + + JPAParser.simple_entity_expression_return simple_entity_expression313 = null; + + + + try { + // JPA.g:374:5: ( path_expression | simple_entity_expression ) + int alt93=2; + int LA93_0 = input.LA(1); + + if ( (LA93_0==WORD) ) { + int LA93_1 = input.LA(2); + + if ( (LA93_1==57) ) { + alt93=1; + } + else if ( (LA93_1==EOF||LA93_1==HAVING||(LA93_1>=OR && LA93_1<=AND)||LA93_1==RPAREN||(LA93_1>=ORDER && LA93_1<=GROUP)||LA93_1==62||LA93_1==83||(LA93_1>=89 && LA93_1<=90)) ) { + alt93=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 93, 1, input); + + throw nvae; + } + } + else if ( (LA93_0==NAMED_PARAMETER||(LA93_0>=115 && LA93_0<=116)) ) { + alt93=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 93, 0, input); + + throw nvae; + } + switch (alt93) { + case 1 : + // JPA.g:374:7: path_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_path_expression_in_entity_expression3002); + path_expression312=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression312.getTree()); + + } + break; + case 2 : + // JPA.g:375:7: simple_entity_expression + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_simple_entity_expression_in_entity_expression3010); + simple_entity_expression313=simple_entity_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_entity_expression313.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "entity_expression" + + public static class simple_entity_expression_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "simple_entity_expression" + // JPA.g:377:1: simple_entity_expression : ( identification_variable | input_parameter ); + public final JPAParser.simple_entity_expression_return simple_entity_expression() throws RecognitionException { + JPAParser.simple_entity_expression_return retval = new JPAParser.simple_entity_expression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + JPAParser.identification_variable_return identification_variable314 = null; + + JPAParser.input_parameter_return input_parameter315 = null; + + + + try { + // JPA.g:378:5: ( identification_variable | input_parameter ) + int alt94=2; + int LA94_0 = input.LA(1); + + if ( (LA94_0==WORD) ) { + alt94=1; + } + else if ( (LA94_0==NAMED_PARAMETER||(LA94_0>=115 && LA94_0<=116)) ) { + alt94=2; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 94, 0, input); + + throw nvae; + } + switch (alt94) { + case 1 : + // JPA.g:378:7: identification_variable + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_identification_variable_in_simple_entity_expression3022); + identification_variable314=identification_variable(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identification_variable314.getTree()); + + } + break; + case 2 : + // JPA.g:379:7: input_parameter + { + root_0 = (Object)adaptor.nil(); + + pushFollow(FOLLOW_input_parameter_in_simple_entity_expression3030); + input_parameter315=input_parameter(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, input_parameter315.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "simple_entity_expression" + + public static class functions_returning_numerics_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "functions_returning_numerics" + // JPA.g:381:1: functions_returning_numerics : ( 'LENGTH' '(' string_primary ')' | 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' | 'ABS' '(' simple_arithmetic_expression ')' | 'SQRT' '(' simple_arithmetic_expression ')' | 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'SIZE' '(' path_expression ')' ); + public final JPAParser.functions_returning_numerics_return functions_returning_numerics() throws RecognitionException { + JPAParser.functions_returning_numerics_return retval = new JPAParser.functions_returning_numerics_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal316=null; + Token char_literal317=null; + Token char_literal319=null; + Token string_literal320=null; + Token char_literal321=null; + Token char_literal323=null; + Token char_literal325=null; + Token char_literal327=null; + Token string_literal328=null; + Token char_literal329=null; + Token char_literal331=null; + Token string_literal332=null; + Token char_literal333=null; + Token char_literal335=null; + Token string_literal336=null; + Token char_literal337=null; + Token char_literal339=null; + Token char_literal341=null; + Token string_literal342=null; + Token char_literal343=null; + Token char_literal345=null; + JPAParser.string_primary_return string_primary318 = null; + + JPAParser.string_primary_return string_primary322 = null; + + JPAParser.string_primary_return string_primary324 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression326 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression330 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression334 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression338 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression340 = null; + + JPAParser.path_expression_return path_expression344 = null; + + + Object string_literal316_tree=null; + Object char_literal317_tree=null; + Object char_literal319_tree=null; + Object string_literal320_tree=null; + Object char_literal321_tree=null; + Object char_literal323_tree=null; + Object char_literal325_tree=null; + Object char_literal327_tree=null; + Object string_literal328_tree=null; + Object char_literal329_tree=null; + Object char_literal331_tree=null; + Object string_literal332_tree=null; + Object char_literal333_tree=null; + Object char_literal335_tree=null; + Object string_literal336_tree=null; + Object char_literal337_tree=null; + Object char_literal339_tree=null; + Object char_literal341_tree=null; + Object string_literal342_tree=null; + Object char_literal343_tree=null; + Object char_literal345_tree=null; + + try { + // JPA.g:382:5: ( 'LENGTH' '(' string_primary ')' | 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' | 'ABS' '(' simple_arithmetic_expression ')' | 'SQRT' '(' simple_arithmetic_expression ')' | 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'SIZE' '(' path_expression ')' ) + int alt96=6; + switch ( input.LA(1) ) { + case 97: + { + alt96=1; + } + break; + case 98: + { + alt96=2; + } + break; + case 99: + { + alt96=3; + } + break; + case 100: + { + alt96=4; + } + break; + case 101: + { + alt96=5; + } + break; + case 102: + { + alt96=6; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 96, 0, input); + + throw nvae; + } + + switch (alt96) { + case 1 : + // JPA.g:382:7: 'LENGTH' '(' string_primary ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal316=(Token)match(input,97,FOLLOW_97_in_functions_returning_numerics3042); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal316_tree = (Object)adaptor.create(string_literal316); + adaptor.addChild(root_0, string_literal316_tree); + } + char_literal317=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3044); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal317_tree = (Object)adaptor.create(char_literal317); + adaptor.addChild(root_0, char_literal317_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3045); + string_primary318=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary318.getTree()); + char_literal319=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3046); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal319_tree = (Object)adaptor.create(char_literal319); + adaptor.addChild(root_0, char_literal319_tree); + } + + } + break; + case 2 : + // JPA.g:383:7: 'LOCATE' '(' string_primary ',' string_primary ( ',' simple_arithmetic_expression )? ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal320=(Token)match(input,98,FOLLOW_98_in_functions_returning_numerics3054); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal320_tree = (Object)adaptor.create(string_literal320); + adaptor.addChild(root_0, string_literal320_tree); + } + char_literal321=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3056); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal321_tree = (Object)adaptor.create(char_literal321); + adaptor.addChild(root_0, char_literal321_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3057); + string_primary322=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary322.getTree()); + char_literal323=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3058); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal323_tree = (Object)adaptor.create(char_literal323); + adaptor.addChild(root_0, char_literal323_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_numerics3060); + string_primary324=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary324.getTree()); + // JPA.g:383:51: ( ',' simple_arithmetic_expression )? + int alt95=2; + int LA95_0 = input.LA(1); + + if ( (LA95_0==54) ) { + alt95=1; + } + switch (alt95) { + case 1 : + // JPA.g:383:52: ',' simple_arithmetic_expression + { + char_literal325=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3062); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal325_tree = (Object)adaptor.create(char_literal325); + adaptor.addChild(root_0, char_literal325_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3064); + simple_arithmetic_expression326=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression326.getTree()); + + } + break; + + } + + char_literal327=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3067); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal327_tree = (Object)adaptor.create(char_literal327); + adaptor.addChild(root_0, char_literal327_tree); + } + + } + break; + case 3 : + // JPA.g:384:7: 'ABS' '(' simple_arithmetic_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal328=(Token)match(input,99,FOLLOW_99_in_functions_returning_numerics3075); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal328_tree = (Object)adaptor.create(string_literal328); + adaptor.addChild(root_0, string_literal328_tree); + } + char_literal329=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3077); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal329_tree = (Object)adaptor.create(char_literal329); + adaptor.addChild(root_0, char_literal329_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3078); + simple_arithmetic_expression330=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression330.getTree()); + char_literal331=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3079); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal331_tree = (Object)adaptor.create(char_literal331); + adaptor.addChild(root_0, char_literal331_tree); + } + + } + break; + case 4 : + // JPA.g:385:7: 'SQRT' '(' simple_arithmetic_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal332=(Token)match(input,100,FOLLOW_100_in_functions_returning_numerics3087); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal332_tree = (Object)adaptor.create(string_literal332); + adaptor.addChild(root_0, string_literal332_tree); + } + char_literal333=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3089); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal333_tree = (Object)adaptor.create(char_literal333); + adaptor.addChild(root_0, char_literal333_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3090); + simple_arithmetic_expression334=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression334.getTree()); + char_literal335=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3091); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal335_tree = (Object)adaptor.create(char_literal335); + adaptor.addChild(root_0, char_literal335_tree); + } + + } + break; + case 5 : + // JPA.g:386:7: 'MOD' '(' simple_arithmetic_expression ',' simple_arithmetic_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal336=(Token)match(input,101,FOLLOW_101_in_functions_returning_numerics3099); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal336_tree = (Object)adaptor.create(string_literal336); + adaptor.addChild(root_0, string_literal336_tree); + } + char_literal337=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3101); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal337_tree = (Object)adaptor.create(char_literal337); + adaptor.addChild(root_0, char_literal337_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3102); + simple_arithmetic_expression338=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression338.getTree()); + char_literal339=(Token)match(input,54,FOLLOW_54_in_functions_returning_numerics3103); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal339_tree = (Object)adaptor.create(char_literal339); + adaptor.addChild(root_0, char_literal339_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3105); + simple_arithmetic_expression340=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression340.getTree()); + char_literal341=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3106); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal341_tree = (Object)adaptor.create(char_literal341); + adaptor.addChild(root_0, char_literal341_tree); + } + + } + break; + case 6 : + // JPA.g:387:7: 'SIZE' '(' path_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal342=(Token)match(input,102,FOLLOW_102_in_functions_returning_numerics3114); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal342_tree = (Object)adaptor.create(string_literal342); + adaptor.addChild(root_0, string_literal342_tree); + } + char_literal343=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_numerics3116); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal343_tree = (Object)adaptor.create(char_literal343); + adaptor.addChild(root_0, char_literal343_tree); + } + pushFollow(FOLLOW_path_expression_in_functions_returning_numerics3117); + path_expression344=path_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, path_expression344.getTree()); + char_literal345=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_numerics3118); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal345_tree = (Object)adaptor.create(char_literal345); + adaptor.addChild(root_0, char_literal345_tree); + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "functions_returning_numerics" + + public static class functions_returning_datetime_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "functions_returning_datetime" + // JPA.g:389:1: functions_returning_datetime : ( 'CURRENT_DATE' | 'CURRENT_TIME' | 'CURRENT_TIMESTAMP' ); + public final JPAParser.functions_returning_datetime_return functions_returning_datetime() throws RecognitionException { + JPAParser.functions_returning_datetime_return retval = new JPAParser.functions_returning_datetime_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set346=null; + + Object set346_tree=null; + + try { + // JPA.g:390:5: ( 'CURRENT_DATE' | 'CURRENT_TIME' | 'CURRENT_TIMESTAMP' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set346=(Token)input.LT(1); + if ( (input.LA(1)>=103 && input.LA(1)<=105) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set346)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "functions_returning_datetime" + + public static class functions_returning_strings_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "functions_returning_strings" + // JPA.g:394:1: functions_returning_strings : ( 'CONCAT' '(' string_primary ',' string_primary ')' | 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' | 'LOWER' '(' string_primary ')' | 'UPPER' '(' string_primary ')' ); + public final JPAParser.functions_returning_strings_return functions_returning_strings() throws RecognitionException { + JPAParser.functions_returning_strings_return retval = new JPAParser.functions_returning_strings_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal347=null; + Token char_literal348=null; + Token char_literal350=null; + Token char_literal352=null; + Token string_literal353=null; + Token char_literal354=null; + Token char_literal356=null; + Token char_literal358=null; + Token char_literal360=null; + Token string_literal361=null; + Token char_literal362=null; + Token TRIM_CHARACTER364=null; + Token string_literal365=null; + Token char_literal367=null; + Token string_literal368=null; + Token char_literal369=null; + Token char_literal371=null; + Token string_literal372=null; + Token char_literal373=null; + Token char_literal375=null; + JPAParser.string_primary_return string_primary349 = null; + + JPAParser.string_primary_return string_primary351 = null; + + JPAParser.string_primary_return string_primary355 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression357 = null; + + JPAParser.simple_arithmetic_expression_return simple_arithmetic_expression359 = null; + + JPAParser.trim_specification_return trim_specification363 = null; + + JPAParser.string_primary_return string_primary366 = null; + + JPAParser.string_primary_return string_primary370 = null; + + JPAParser.string_primary_return string_primary374 = null; + + + Object string_literal347_tree=null; + Object char_literal348_tree=null; + Object char_literal350_tree=null; + Object char_literal352_tree=null; + Object string_literal353_tree=null; + Object char_literal354_tree=null; + Object char_literal356_tree=null; + Object char_literal358_tree=null; + Object char_literal360_tree=null; + Object string_literal361_tree=null; + Object char_literal362_tree=null; + Object TRIM_CHARACTER364_tree=null; + Object string_literal365_tree=null; + Object char_literal367_tree=null; + Object string_literal368_tree=null; + Object char_literal369_tree=null; + Object char_literal371_tree=null; + Object string_literal372_tree=null; + Object char_literal373_tree=null; + Object char_literal375_tree=null; + + try { + // JPA.g:395:5: ( 'CONCAT' '(' string_primary ',' string_primary ')' | 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' | 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' | 'LOWER' '(' string_primary ')' | 'UPPER' '(' string_primary ')' ) + int alt100=5; + switch ( input.LA(1) ) { + case 106: + { + alt100=1; + } + break; + case 107: + { + alt100=2; + } + break; + case 108: + { + alt100=3; + } + break; + case 109: + { + alt100=4; + } + break; + case 110: + { + alt100=5; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 100, 0, input); + + throw nvae; + } + + switch (alt100) { + case 1 : + // JPA.g:395:7: 'CONCAT' '(' string_primary ',' string_primary ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal347=(Token)match(input,106,FOLLOW_106_in_functions_returning_strings3158); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal347_tree = (Object)adaptor.create(string_literal347); + adaptor.addChild(root_0, string_literal347_tree); + } + char_literal348=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3160); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal348_tree = (Object)adaptor.create(char_literal348); + adaptor.addChild(root_0, char_literal348_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3161); + string_primary349=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary349.getTree()); + char_literal350=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3162); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal350_tree = (Object)adaptor.create(char_literal350); + adaptor.addChild(root_0, char_literal350_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3164); + string_primary351=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary351.getTree()); + char_literal352=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3165); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal352_tree = (Object)adaptor.create(char_literal352); + adaptor.addChild(root_0, char_literal352_tree); + } + + } + break; + case 2 : + // JPA.g:396:7: 'SUBSTRING' '(' string_primary ',' simple_arithmetic_expression ',' simple_arithmetic_expression ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal353=(Token)match(input,107,FOLLOW_107_in_functions_returning_strings3173); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal353_tree = (Object)adaptor.create(string_literal353); + adaptor.addChild(root_0, string_literal353_tree); + } + char_literal354=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3175); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal354_tree = (Object)adaptor.create(char_literal354); + adaptor.addChild(root_0, char_literal354_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3176); + string_primary355=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary355.getTree()); + char_literal356=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3177); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal356_tree = (Object)adaptor.create(char_literal356); + adaptor.addChild(root_0, char_literal356_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3178); + simple_arithmetic_expression357=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression357.getTree()); + char_literal358=(Token)match(input,54,FOLLOW_54_in_functions_returning_strings3179); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal358_tree = (Object)adaptor.create(char_literal358); + adaptor.addChild(root_0, char_literal358_tree); + } + pushFollow(FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3181); + simple_arithmetic_expression359=simple_arithmetic_expression(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, simple_arithmetic_expression359.getTree()); + char_literal360=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3182); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal360_tree = (Object)adaptor.create(char_literal360); + adaptor.addChild(root_0, char_literal360_tree); + } + + } + break; + case 3 : + // JPA.g:397:7: 'TRIM' '(' ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? string_primary ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal361=(Token)match(input,108,FOLLOW_108_in_functions_returning_strings3190); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal361_tree = (Object)adaptor.create(string_literal361); + adaptor.addChild(root_0, string_literal361_tree); + } + char_literal362=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3192); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal362_tree = (Object)adaptor.create(char_literal362); + adaptor.addChild(root_0, char_literal362_tree); + } + // JPA.g:397:17: ( ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' )? + int alt99=2; + int LA99_0 = input.LA(1); + + if ( (LA99_0==TRIM_CHARACTER||LA99_0==53||(LA99_0>=111 && LA99_0<=113)) ) { + alt99=1; + } + switch (alt99) { + case 1 : + // JPA.g:397:18: ( trim_specification )? ( TRIM_CHARACTER )? 'FROM' + { + // JPA.g:397:18: ( trim_specification )? + int alt97=2; + int LA97_0 = input.LA(1); + + if ( ((LA97_0>=111 && LA97_0<=113)) ) { + alt97=1; + } + switch (alt97) { + case 1 : + // JPA.g:397:19: trim_specification + { + pushFollow(FOLLOW_trim_specification_in_functions_returning_strings3195); + trim_specification363=trim_specification(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, trim_specification363.getTree()); + + } + break; + + } + + // JPA.g:397:40: ( TRIM_CHARACTER )? + int alt98=2; + int LA98_0 = input.LA(1); + + if ( (LA98_0==TRIM_CHARACTER) ) { + alt98=1; + } + switch (alt98) { + case 1 : + // JPA.g:397:41: TRIM_CHARACTER + { + TRIM_CHARACTER364=(Token)match(input,TRIM_CHARACTER,FOLLOW_TRIM_CHARACTER_in_functions_returning_strings3200); if (state.failed) return retval; + if ( state.backtracking==0 ) { + TRIM_CHARACTER364_tree = (Object)adaptor.create(TRIM_CHARACTER364); + adaptor.addChild(root_0, TRIM_CHARACTER364_tree); + } + + } + break; + + } + + string_literal365=(Token)match(input,53,FOLLOW_53_in_functions_returning_strings3204); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal365_tree = (Object)adaptor.create(string_literal365); + adaptor.addChild(root_0, string_literal365_tree); + } + + } + break; + + } + + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3208); + string_primary366=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary366.getTree()); + char_literal367=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3209); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal367_tree = (Object)adaptor.create(char_literal367); + adaptor.addChild(root_0, char_literal367_tree); + } + + } + break; + case 4 : + // JPA.g:398:7: 'LOWER' '(' string_primary ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal368=(Token)match(input,109,FOLLOW_109_in_functions_returning_strings3217); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal368_tree = (Object)adaptor.create(string_literal368); + adaptor.addChild(root_0, string_literal368_tree); + } + char_literal369=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3219); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal369_tree = (Object)adaptor.create(char_literal369); + adaptor.addChild(root_0, char_literal369_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3220); + string_primary370=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary370.getTree()); + char_literal371=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3221); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal371_tree = (Object)adaptor.create(char_literal371); + adaptor.addChild(root_0, char_literal371_tree); + } + + } + break; + case 5 : + // JPA.g:399:7: 'UPPER' '(' string_primary ')' + { + root_0 = (Object)adaptor.nil(); + + string_literal372=(Token)match(input,110,FOLLOW_110_in_functions_returning_strings3229); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal372_tree = (Object)adaptor.create(string_literal372); + adaptor.addChild(root_0, string_literal372_tree); + } + char_literal373=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_functions_returning_strings3231); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal373_tree = (Object)adaptor.create(char_literal373); + adaptor.addChild(root_0, char_literal373_tree); + } + pushFollow(FOLLOW_string_primary_in_functions_returning_strings3232); + string_primary374=string_primary(); + + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, string_primary374.getTree()); + char_literal375=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_functions_returning_strings3233); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal375_tree = (Object)adaptor.create(char_literal375); + adaptor.addChild(root_0, char_literal375_tree); + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "functions_returning_strings" + + public static class trim_specification_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "trim_specification" + // JPA.g:401:1: trim_specification : ( 'LEADING' | 'TRAILING' | 'BOTH' ); + public final JPAParser.trim_specification_return trim_specification() throws RecognitionException { + JPAParser.trim_specification_return retval = new JPAParser.trim_specification_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set376=null; + + Object set376_tree=null; + + try { + // JPA.g:402:5: ( 'LEADING' | 'TRAILING' | 'BOTH' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set376=(Token)input.LT(1); + if ( (input.LA(1)>=111 && input.LA(1)<=113) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set376)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "trim_specification" + + public static class abstract_schema_name_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "abstract_schema_name" + // JPA.g:407:1: abstract_schema_name : WORD ; + public final JPAParser.abstract_schema_name_return abstract_schema_name() throws RecognitionException { + JPAParser.abstract_schema_name_return retval = new JPAParser.abstract_schema_name_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD377=null; + + Object WORD377_tree=null; + + try { + // JPA.g:408:5: ( WORD ) + // JPA.g:408:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD377=(Token)match(input,WORD,FOLLOW_WORD_in_abstract_schema_name3274); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD377_tree = (Object)adaptor.create(WORD377); + adaptor.addChild(root_0, WORD377_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "abstract_schema_name" + + public static class pattern_value_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "pattern_value" + // JPA.g:411:1: pattern_value : WORD ; + public final JPAParser.pattern_value_return pattern_value() throws RecognitionException { + JPAParser.pattern_value_return retval = new JPAParser.pattern_value_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD378=null; + + Object WORD378_tree=null; + + try { + // JPA.g:412:5: ( WORD ) + // JPA.g:412:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD378=(Token)match(input,WORD,FOLLOW_WORD_in_pattern_value3287); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD378_tree = (Object)adaptor.create(WORD378); + adaptor.addChild(root_0, WORD378_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "pattern_value" + + public static class numeric_literal_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "numeric_literal" + // JPA.g:415:1: numeric_literal : ( '0x' )? INT_NUMERAL ; + public final JPAParser.numeric_literal_return numeric_literal() throws RecognitionException { + JPAParser.numeric_literal_return retval = new JPAParser.numeric_literal_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token string_literal379=null; + Token INT_NUMERAL380=null; + + Object string_literal379_tree=null; + Object INT_NUMERAL380_tree=null; + + try { + // JPA.g:416:5: ( ( '0x' )? INT_NUMERAL ) + // JPA.g:416:7: ( '0x' )? INT_NUMERAL + { + root_0 = (Object)adaptor.nil(); + + // JPA.g:416:7: ( '0x' )? + int alt101=2; + int LA101_0 = input.LA(1); + + if ( (LA101_0==114) ) { + alt101=1; + } + switch (alt101) { + case 1 : + // JPA.g:416:8: '0x' + { + string_literal379=(Token)match(input,114,FOLLOW_114_in_numeric_literal3301); if (state.failed) return retval; + if ( state.backtracking==0 ) { + string_literal379_tree = (Object)adaptor.create(string_literal379); + adaptor.addChild(root_0, string_literal379_tree); + } + + } + break; + + } + + INT_NUMERAL380=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_numeric_literal3305); if (state.failed) return retval; + if ( state.backtracking==0 ) { + INT_NUMERAL380_tree = (Object)adaptor.create(INT_NUMERAL380); + adaptor.addChild(root_0, INT_NUMERAL380_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "numeric_literal" + + public static class input_parameter_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "input_parameter" + // JPA.g:418:1: input_parameter : ( '?' INT_NUMERAL -> ^( T_PARAMETER[] '?' INT_NUMERAL ) | NAMED_PARAMETER -> ^( T_PARAMETER[] NAMED_PARAMETER ) | '${' WORD '}' -> ^( T_PARAMETER[] '${' WORD '}' ) ); + public final JPAParser.input_parameter_return input_parameter() throws RecognitionException { + JPAParser.input_parameter_return retval = new JPAParser.input_parameter_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token char_literal381=null; + Token INT_NUMERAL382=null; + Token NAMED_PARAMETER383=null; + Token string_literal384=null; + Token WORD385=null; + Token char_literal386=null; + + Object char_literal381_tree=null; + Object INT_NUMERAL382_tree=null; + Object NAMED_PARAMETER383_tree=null; + Object string_literal384_tree=null; + Object WORD385_tree=null; + Object char_literal386_tree=null; + RewriteRuleTokenStream stream_116=new RewriteRuleTokenStream(adaptor,"token 116"); + RewriteRuleTokenStream stream_WORD=new RewriteRuleTokenStream(adaptor,"token WORD"); + RewriteRuleTokenStream stream_117=new RewriteRuleTokenStream(adaptor,"token 117"); + RewriteRuleTokenStream stream_115=new RewriteRuleTokenStream(adaptor,"token 115"); + RewriteRuleTokenStream stream_NAMED_PARAMETER=new RewriteRuleTokenStream(adaptor,"token NAMED_PARAMETER"); + RewriteRuleTokenStream stream_INT_NUMERAL=new RewriteRuleTokenStream(adaptor,"token INT_NUMERAL"); + + try { + // JPA.g:419:5: ( '?' INT_NUMERAL -> ^( T_PARAMETER[] '?' INT_NUMERAL ) | NAMED_PARAMETER -> ^( T_PARAMETER[] NAMED_PARAMETER ) | '${' WORD '}' -> ^( T_PARAMETER[] '${' WORD '}' ) ) + int alt102=3; + switch ( input.LA(1) ) { + case 115: + { + alt102=1; + } + break; + case NAMED_PARAMETER: + { + alt102=2; + } + break; + case 116: + { + alt102=3; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 102, 0, input); + + throw nvae; + } + + switch (alt102) { + case 1 : + // JPA.g:419:7: '?' INT_NUMERAL + { + char_literal381=(Token)match(input,115,FOLLOW_115_in_input_parameter3318); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_115.add(char_literal381); + + INT_NUMERAL382=(Token)match(input,INT_NUMERAL,FOLLOW_INT_NUMERAL_in_input_parameter3320); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_INT_NUMERAL.add(INT_NUMERAL382); + + + + // AST REWRITE + // elements: 115, INT_NUMERAL + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 419:23: -> ^( T_PARAMETER[] '?' INT_NUMERAL ) + { + // JPA.g:419:26: ^( T_PARAMETER[] '?' INT_NUMERAL ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); + + adaptor.addChild(root_1, stream_115.nextNode()); + adaptor.addChild(root_1, stream_INT_NUMERAL.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 2 : + // JPA.g:420:7: NAMED_PARAMETER + { + NAMED_PARAMETER383=(Token)match(input,NAMED_PARAMETER,FOLLOW_NAMED_PARAMETER_in_input_parameter3343); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NAMED_PARAMETER.add(NAMED_PARAMETER383); + + + + // AST REWRITE + // elements: NAMED_PARAMETER + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 420:23: -> ^( T_PARAMETER[] NAMED_PARAMETER ) + { + // JPA.g:420:26: ^( T_PARAMETER[] NAMED_PARAMETER ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); + + adaptor.addChild(root_1, stream_NAMED_PARAMETER.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + case 3 : + // JPA.g:421:7: '${' WORD '}' + { + string_literal384=(Token)match(input,116,FOLLOW_116_in_input_parameter3364); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_116.add(string_literal384); + + WORD385=(Token)match(input,WORD,FOLLOW_WORD_in_input_parameter3366); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_WORD.add(WORD385); + + char_literal386=(Token)match(input,117,FOLLOW_117_in_input_parameter3368); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_117.add(char_literal386); + + + + // AST REWRITE + // elements: 117, 116, WORD + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (Object)adaptor.nil(); + // 421:21: -> ^( T_PARAMETER[] '${' WORD '}' ) + { + // JPA.g:421:24: ^( T_PARAMETER[] '${' WORD '}' ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(new ParameterNode(T_PARAMETER), root_1); + + adaptor.addChild(root_1, stream_116.nextNode()); + adaptor.addChild(root_1, stream_WORD.nextNode()); + adaptor.addChild(root_1, stream_117.nextNode()); + + adaptor.addChild(root_0, root_1); + } + + } + + retval.tree = root_0;} + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "input_parameter" + + public static class literal_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "literal" + // JPA.g:423:1: literal : WORD ; + public final JPAParser.literal_return literal() throws RecognitionException { + JPAParser.literal_return retval = new JPAParser.literal_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD387=null; + + Object WORD387_tree=null; + + try { + // JPA.g:424:5: ( WORD ) + // JPA.g:424:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD387=(Token)match(input,WORD,FOLLOW_WORD_in_literal3396); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD387_tree = (Object)adaptor.create(WORD387); + adaptor.addChild(root_0, WORD387_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "literal" + + public static class constructor_name_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "constructor_name" + // JPA.g:426:1: constructor_name : WORD ; + public final JPAParser.constructor_name_return constructor_name() throws RecognitionException { + JPAParser.constructor_name_return retval = new JPAParser.constructor_name_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD388=null; + + Object WORD388_tree=null; + + try { + // JPA.g:427:5: ( WORD ) + // JPA.g:427:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD388=(Token)match(input,WORD,FOLLOW_WORD_in_constructor_name3408); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD388_tree = (Object)adaptor.create(WORD388); + adaptor.addChild(root_0, WORD388_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "constructor_name" + + public static class enum_literal_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "enum_literal" + // JPA.g:429:1: enum_literal : WORD ; + public final JPAParser.enum_literal_return enum_literal() throws RecognitionException { + JPAParser.enum_literal_return retval = new JPAParser.enum_literal_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD389=null; + + Object WORD389_tree=null; + + try { + // JPA.g:430:5: ( WORD ) + // JPA.g:430:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD389=(Token)match(input,WORD,FOLLOW_WORD_in_enum_literal3452); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD389_tree = (Object)adaptor.create(WORD389); + adaptor.addChild(root_0, WORD389_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "enum_literal" + + public static class boolean_literal_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "boolean_literal" + // JPA.g:432:1: boolean_literal : ( 'true' | 'false' ); + public final JPAParser.boolean_literal_return boolean_literal() throws RecognitionException { + JPAParser.boolean_literal_return retval = new JPAParser.boolean_literal_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set390=null; + + Object set390_tree=null; + + try { + // JPA.g:433:5: ( 'true' | 'false' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set390=(Token)input.LT(1); + if ( (input.LA(1)>=118 && input.LA(1)<=119) ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set390)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "boolean_literal" + + public static class field_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "field" + // JPA.g:437:1: field : ( WORD | 'GROUP' ); + public final JPAParser.field_return field() throws RecognitionException { + JPAParser.field_return retval = new JPAParser.field_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set391=null; + + Object set391_tree=null; + + try { + // JPA.g:438:5: ( WORD | 'GROUP' ) + // JPA.g: + { + root_0 = (Object)adaptor.nil(); + + set391=(Token)input.LT(1); + if ( input.LA(1)==GROUP||input.LA(1)==WORD ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set391)); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "field" + + public static class identification_variable_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "identification_variable" + // JPA.g:440:1: identification_variable : WORD ; + public final JPAParser.identification_variable_return identification_variable() throws RecognitionException { + JPAParser.identification_variable_return retval = new JPAParser.identification_variable_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD392=null; + + Object WORD392_tree=null; + + try { + // JPA.g:441:5: ( WORD ) + // JPA.g:441:7: WORD + { + root_0 = (Object)adaptor.nil(); + + WORD392=(Token)match(input,WORD,FOLLOW_WORD_in_identification_variable3501); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD392_tree = (Object)adaptor.create(WORD392); + adaptor.addChild(root_0, WORD392_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "identification_variable" + + public static class parameter_name_return extends ParserRuleReturnScope { + Object tree; + public Object getTree() { return tree; } + }; + + // $ANTLR start "parameter_name" + // JPA.g:443:1: parameter_name : WORD ( '.' WORD )* ; + public final JPAParser.parameter_name_return parameter_name() throws RecognitionException { + JPAParser.parameter_name_return retval = new JPAParser.parameter_name_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WORD393=null; + Token char_literal394=null; + Token WORD395=null; + + Object WORD393_tree=null; + Object char_literal394_tree=null; + Object WORD395_tree=null; + + try { + // JPA.g:444:5: ( WORD ( '.' WORD )* ) + // JPA.g:444:7: WORD ( '.' WORD )* + { + root_0 = (Object)adaptor.nil(); + + WORD393=(Token)match(input,WORD,FOLLOW_WORD_in_parameter_name3513); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD393_tree = (Object)adaptor.create(WORD393); + adaptor.addChild(root_0, WORD393_tree); + } + // JPA.g:444:12: ( '.' WORD )* + loop103: + do { + int alt103=2; + int LA103_0 = input.LA(1); + + if ( (LA103_0==57) ) { + alt103=1; + } + + + switch (alt103) { + case 1 : + // JPA.g:444:13: '.' WORD + { + char_literal394=(Token)match(input,57,FOLLOW_57_in_parameter_name3516); if (state.failed) return retval; + if ( state.backtracking==0 ) { + char_literal394_tree = (Object)adaptor.create(char_literal394); + adaptor.addChild(root_0, char_literal394_tree); + } + WORD395=(Token)match(input,WORD,FOLLOW_WORD_in_parameter_name3519); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WORD395_tree = (Object)adaptor.create(WORD395); + adaptor.addChild(root_0, WORD395_tree); + } + + } + break; + + default : + break loop103; + } + } while (true); + + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + catch (RecognitionException re) { + reportError(re); + recover(input,re); + retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re); + + } + finally { + } + return retval; + } + // $ANTLR end "parameter_name" + + // $ANTLR start synpred20_JPA + public final void synpred20_JPA_fragment() throws RecognitionException { + // JPA.g:130:47: ( field ) + // JPA.g:130:47: field + { + pushFollow(FOLLOW_field_in_synpred20_JPA887); + field(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred20_JPA + + // $ANTLR start synpred23_JPA + public final void synpred23_JPA_fragment() throws RecognitionException { + // JPA.g:140:49: ( field ) + // JPA.g:140:49: field + { + pushFollow(FOLLOW_field_in_synpred23_JPA982); + field(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred23_JPA + + // $ANTLR start synpred57_JPA + public final void synpred57_JPA_fragment() throws RecognitionException { + // JPA.g:228:8: ( 'NOT' ) + // JPA.g:228:8: 'NOT' + { + match(input,62,FOLLOW_62_in_synpred57_JPA1823); if (state.failed) return ; + + } + } + // $ANTLR end synpred57_JPA + + // $ANTLR start synpred58_JPA + public final void synpred58_JPA_fragment() throws RecognitionException { + // JPA.g:228:7: ( ( 'NOT' )? simple_cond_expression ) + // JPA.g:228:7: ( 'NOT' )? simple_cond_expression + { + // JPA.g:228:7: ( 'NOT' )? + int alt108=2; + int LA108_0 = input.LA(1); + + if ( (LA108_0==62) ) { + int LA108_1 = input.LA(2); + + if ( (synpred57_JPA()) ) { + alt108=1; + } + } + switch (alt108) { + case 1 : + // JPA.g:228:8: 'NOT' + { + match(input,62,FOLLOW_62_in_synpred58_JPA1823); if (state.failed) return ; + + } + break; + + } + + pushFollow(FOLLOW_simple_cond_expression_in_synpred58_JPA1827); + simple_cond_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred58_JPA + + // $ANTLR start synpred59_JPA + public final void synpred59_JPA_fragment() throws RecognitionException { + // JPA.g:232:7: ( comparison_expression ) + // JPA.g:232:7: comparison_expression + { + pushFollow(FOLLOW_comparison_expression_in_synpred59_JPA1866); + comparison_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred59_JPA + + // $ANTLR start synpred60_JPA + public final void synpred60_JPA_fragment() throws RecognitionException { + // JPA.g:233:7: ( between_expression ) + // JPA.g:233:7: between_expression + { + pushFollow(FOLLOW_between_expression_in_synpred60_JPA1874); + between_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred60_JPA + + // $ANTLR start synpred61_JPA + public final void synpred61_JPA_fragment() throws RecognitionException { + // JPA.g:234:7: ( like_expression ) + // JPA.g:234:7: like_expression + { + pushFollow(FOLLOW_like_expression_in_synpred61_JPA1882); + like_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred61_JPA + + // $ANTLR start synpred62_JPA + public final void synpred62_JPA_fragment() throws RecognitionException { + // JPA.g:235:7: ( in_expression ) + // JPA.g:235:7: in_expression + { + pushFollow(FOLLOW_in_expression_in_synpred62_JPA1890); + in_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred62_JPA + + // $ANTLR start synpred63_JPA + public final void synpred63_JPA_fragment() throws RecognitionException { + // JPA.g:236:7: ( null_comparison_expression ) + // JPA.g:236:7: null_comparison_expression + { + pushFollow(FOLLOW_null_comparison_expression_in_synpred63_JPA1898); + null_comparison_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred63_JPA + + // $ANTLR start synpred64_JPA + public final void synpred64_JPA_fragment() throws RecognitionException { + // JPA.g:237:7: ( empty_collection_comparison_expression ) + // JPA.g:237:7: empty_collection_comparison_expression + { + pushFollow(FOLLOW_empty_collection_comparison_expression_in_synpred64_JPA1906); + empty_collection_comparison_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred64_JPA + + // $ANTLR start synpred65_JPA + public final void synpred65_JPA_fragment() throws RecognitionException { + // JPA.g:238:7: ( collection_member_expression ) + // JPA.g:238:7: collection_member_expression + { + pushFollow(FOLLOW_collection_member_expression_in_synpred65_JPA1914); + collection_member_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred65_JPA + + // $ANTLR start synpred84_JPA + public final void synpred84_JPA_fragment() throws RecognitionException { + // JPA.g:265:7: ( arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression ) + // JPA.g:265:7: arithmetic_expression ( 'NOT' )? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression + { + pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2165); + arithmetic_expression(); + + state._fsp--; + if (state.failed) return ; + // JPA.g:265:29: ( 'NOT' )? + int alt109=2; + int LA109_0 = input.LA(1); + + if ( (LA109_0==62) ) { + alt109=1; + } + switch (alt109) { + case 1 : + // JPA.g:265:30: 'NOT' + { + match(input,62,FOLLOW_62_in_synpred84_JPA2168); if (state.failed) return ; + + } + break; + + } + + match(input,77,FOLLOW_77_in_synpred84_JPA2172); if (state.failed) return ; + pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2174); + arithmetic_expression(); + + state._fsp--; + if (state.failed) return ; + match(input,AND,FOLLOW_AND_in_synpred84_JPA2176); if (state.failed) return ; + pushFollow(FOLLOW_arithmetic_expression_in_synpred84_JPA2178); + arithmetic_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred84_JPA + + // $ANTLR start synpred86_JPA + public final void synpred86_JPA_fragment() throws RecognitionException { + // JPA.g:266:7: ( string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression ) + // JPA.g:266:7: string_expression ( 'NOT' )? 'BETWEEN' string_expression 'AND' string_expression + { + pushFollow(FOLLOW_string_expression_in_synpred86_JPA2186); + string_expression(); + + state._fsp--; + if (state.failed) return ; + // JPA.g:266:25: ( 'NOT' )? + int alt110=2; + int LA110_0 = input.LA(1); + + if ( (LA110_0==62) ) { + alt110=1; + } + switch (alt110) { + case 1 : + // JPA.g:266:26: 'NOT' + { + match(input,62,FOLLOW_62_in_synpred86_JPA2189); if (state.failed) return ; + + } + break; + + } + + match(input,77,FOLLOW_77_in_synpred86_JPA2193); if (state.failed) return ; + pushFollow(FOLLOW_string_expression_in_synpred86_JPA2195); + string_expression(); + + state._fsp--; + if (state.failed) return ; + match(input,AND,FOLLOW_AND_in_synpred86_JPA2197); if (state.failed) return ; + pushFollow(FOLLOW_string_expression_in_synpred86_JPA2199); + string_expression(); + + state._fsp--; + if (state.failed) return ; + + } + } + // $ANTLR end synpred86_JPA + + // $ANTLR start synpred104_JPA + public final void synpred104_JPA_fragment() throws RecognitionException { + // JPA.g:299:7: ( string_expression comparison_operator ( string_expression | all_or_any_expression ) ) + // JPA.g:299:7: string_expression comparison_operator ( string_expression | all_or_any_expression ) + { + pushFollow(FOLLOW_string_expression_in_synpred104_JPA2455); + string_expression(); + + state._fsp--; + if (state.failed) return ; + pushFollow(FOLLOW_comparison_operator_in_synpred104_JPA2457); + comparison_operator(); + + state._fsp--; + if (state.failed) return ; + // JPA.g:299:45: ( string_expression | all_or_any_expression ) + int alt112=2; + int LA112_0 = input.LA(1); + + if ( ((LA112_0>=AVG && LA112_0<=COUNT)||LA112_0==STRINGLITERAL||(LA112_0>=WORD && LA112_0<=NAMED_PARAMETER)||LA112_0==56||(LA112_0>=106 && LA112_0<=110)||(LA112_0>=115 && LA112_0<=116)) ) { + alt112=1; + } + else if ( ((LA112_0>=86 && LA112_0<=88)) ) { + alt112=2; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + NoViableAltException nvae = + new NoViableAltException("", 112, 0, input); + + throw nvae; + } + switch (alt112) { + case 1 : + // JPA.g:299:46: string_expression + { + pushFollow(FOLLOW_string_expression_in_synpred104_JPA2460); + string_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + case 2 : + // JPA.g:299:66: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_synpred104_JPA2464); + all_or_any_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + + } + + + } + } + // $ANTLR end synpred104_JPA + + // $ANTLR start synpred107_JPA + public final void synpred107_JPA_fragment() throws RecognitionException { + // JPA.g:300:7: ( boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) ) + // JPA.g:300:7: boolean_expression ( '=' | '<>' ) ( boolean_expression | all_or_any_expression ) + { + pushFollow(FOLLOW_boolean_expression_in_synpred107_JPA2473); + boolean_expression(); + + state._fsp--; + if (state.failed) return ; + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:300:39: ( boolean_expression | all_or_any_expression ) + int alt113=2; + int LA113_0 = input.LA(1); + + if ( ((LA113_0>=WORD && LA113_0<=NAMED_PARAMETER)||LA113_0==56||(LA113_0>=115 && LA113_0<=116)||(LA113_0>=118 && LA113_0<=119)) ) { + alt113=1; + } + else if ( ((LA113_0>=86 && LA113_0<=88)) ) { + alt113=2; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + NoViableAltException nvae = + new NoViableAltException("", 113, 0, input); + + throw nvae; + } + switch (alt113) { + case 1 : + // JPA.g:300:40: boolean_expression + { + pushFollow(FOLLOW_boolean_expression_in_synpred107_JPA2484); + boolean_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + case 2 : + // JPA.g:300:61: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_synpred107_JPA2488); + all_or_any_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + + } + + + } + } + // $ANTLR end synpred107_JPA + + // $ANTLR start synpred110_JPA + public final void synpred110_JPA_fragment() throws RecognitionException { + // JPA.g:301:7: ( enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) ) + // JPA.g:301:7: enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) + { + pushFollow(FOLLOW_enum_expression_in_synpred110_JPA2497); + enum_expression(); + + state._fsp--; + if (state.failed) return ; + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:301:34: ( enum_expression | all_or_any_expression ) + int alt114=2; + int LA114_0 = input.LA(1); + + if ( ((LA114_0>=WORD && LA114_0<=NAMED_PARAMETER)||LA114_0==56||(LA114_0>=115 && LA114_0<=116)) ) { + alt114=1; + } + else if ( ((LA114_0>=86 && LA114_0<=88)) ) { + alt114=2; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + NoViableAltException nvae = + new NoViableAltException("", 114, 0, input); + + throw nvae; + } + switch (alt114) { + case 1 : + // JPA.g:301:35: enum_expression + { + pushFollow(FOLLOW_enum_expression_in_synpred110_JPA2506); + enum_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + case 2 : + // JPA.g:301:53: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_synpred110_JPA2510); + all_or_any_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + + } + + + } + } + // $ANTLR end synpred110_JPA + + // $ANTLR start synpred112_JPA + public final void synpred112_JPA_fragment() throws RecognitionException { + // JPA.g:302:7: ( datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) ) + // JPA.g:302:7: datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) + { + pushFollow(FOLLOW_datetime_expression_in_synpred112_JPA2519); + datetime_expression(); + + state._fsp--; + if (state.failed) return ; + pushFollow(FOLLOW_comparison_operator_in_synpred112_JPA2521); + comparison_operator(); + + state._fsp--; + if (state.failed) return ; + // JPA.g:302:47: ( datetime_expression | all_or_any_expression ) + int alt115=2; + int LA115_0 = input.LA(1); + + if ( ((LA115_0>=AVG && LA115_0<=COUNT)||(LA115_0>=WORD && LA115_0<=NAMED_PARAMETER)||LA115_0==56||(LA115_0>=103 && LA115_0<=105)||(LA115_0>=115 && LA115_0<=116)) ) { + alt115=1; + } + else if ( ((LA115_0>=86 && LA115_0<=88)) ) { + alt115=2; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + NoViableAltException nvae = + new NoViableAltException("", 115, 0, input); + + throw nvae; + } + switch (alt115) { + case 1 : + // JPA.g:302:48: datetime_expression + { + pushFollow(FOLLOW_datetime_expression_in_synpred112_JPA2524); + datetime_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + case 2 : + // JPA.g:302:70: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_synpred112_JPA2528); + all_or_any_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + + } + + + } + } + // $ANTLR end synpred112_JPA + + // $ANTLR start synpred115_JPA + public final void synpred115_JPA_fragment() throws RecognitionException { + // JPA.g:303:7: ( entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) ) + // JPA.g:303:7: entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) + { + pushFollow(FOLLOW_entity_expression_in_synpred115_JPA2537); + entity_expression(); + + state._fsp--; + if (state.failed) return ; + if ( (input.LA(1)>=89 && input.LA(1)<=90) ) { + input.consume(); + state.errorRecovery=false;state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + + // JPA.g:303:38: ( entity_expression | all_or_any_expression ) + int alt116=2; + int LA116_0 = input.LA(1); + + if ( ((LA116_0>=WORD && LA116_0<=NAMED_PARAMETER)||(LA116_0>=115 && LA116_0<=116)) ) { + alt116=1; + } + else if ( ((LA116_0>=86 && LA116_0<=88)) ) { + alt116=2; + } + else { + if (state.backtracking>0) {state.failed=true; return ;} + NoViableAltException nvae = + new NoViableAltException("", 116, 0, input); + + throw nvae; + } + switch (alt116) { + case 1 : + // JPA.g:303:39: entity_expression + { + pushFollow(FOLLOW_entity_expression_in_synpred115_JPA2548); + entity_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + case 2 : + // JPA.g:303:59: all_or_any_expression + { + pushFollow(FOLLOW_all_or_any_expression_in_synpred115_JPA2552); + all_or_any_expression(); + + state._fsp--; + if (state.failed) return ; + + } + break; + + } + + + } + } + // $ANTLR end synpred115_JPA + + // Delegated rules + + public final boolean synpred115_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred115_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred110_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred110_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred112_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred112_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred60_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred60_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred64_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred64_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred65_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred65_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred20_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred20_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred104_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred104_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred84_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred84_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred62_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred62_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred63_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred63_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred23_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred23_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred59_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred59_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred107_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred107_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred58_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred58_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred86_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred86_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred57_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred57_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred61_JPA() { + state.backtracking++; + int start = input.mark(); + try { + synpred61_JPA_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + + + protected DFA31 dfa31 = new DFA31(this); + protected DFA36 dfa36 = new DFA36(this); + protected DFA48 dfa48 = new DFA48(this); + protected DFA49 dfa49 = new DFA49(this); + protected DFA59 dfa59 = new DFA59(this); + protected DFA79 dfa79 = new DFA79(this); + static final String DFA31_eotS = + "\11\uffff"; + static final String DFA31_eofS = + "\4\uffff\3\7\1\uffff\1\7"; + static final String DFA31_minS = + "\1\75\1\30\1\71\1\uffff\3\25\1\uffff\1\25"; + static final String DFA31_maxS = + "\1\75\1\167\1\132\1\uffff\3\140\1\uffff\1\140"; + static final String DFA31_acceptS = + "\3\uffff\1\1\3\uffff\1\2\1\uffff"; + static final String DFA31_specialS = + "\11\uffff}>"; + static final String[] DFA31_transitionS = { + "\1\1", + "\5\3\2\uffff\1\3\12\uffff\1\3\1\uffff\1\3\1\uffff\1\2\1\3"+ + "\10\uffff\1\3\5\uffff\2\3\1\uffff\2\3\6\uffff\4\3\10\uffff\1"+ + "\3\13\uffff\16\3\3\uffff\3\3\1\uffff\2\3", + "\1\4\4\uffff\1\3\24\uffff\1\3\5\uffff\2\3", + "", + "\1\7\12\uffff\1\7\6\uffff\1\7\1\5\5\uffff\1\6\13\uffff\1\3"+ + "\3\uffff\1\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1"+ + "\3\5\uffff\10\3", + "\1\7\12\uffff\1\7\6\uffff\3\7\17\uffff\1\10\1\3\3\uffff\1"+ + "\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1\3\5\uffff"+ + "\10\3", + "\1\7\12\uffff\1\7\6\uffff\2\7\20\uffff\1\10\1\3\3\uffff\1"+ + "\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1\3\5\uffff"+ + "\10\3", + "", + "\1\7\12\uffff\1\7\6\uffff\1\7\1\5\5\uffff\1\6\13\uffff\1\3"+ + "\3\uffff\1\3\2\uffff\2\3\12\uffff\2\3\1\uffff\1\3\2\uffff\1"+ + "\3\5\uffff\10\3" + }; + + static final short[] DFA31_eot = DFA.unpackEncodedString(DFA31_eotS); + static final short[] DFA31_eof = DFA.unpackEncodedString(DFA31_eofS); + static final char[] DFA31_min = DFA.unpackEncodedStringToUnsignedChars(DFA31_minS); + static final char[] DFA31_max = DFA.unpackEncodedStringToUnsignedChars(DFA31_maxS); + static final short[] DFA31_accept = DFA.unpackEncodedString(DFA31_acceptS); + static final short[] DFA31_special = DFA.unpackEncodedString(DFA31_specialS); + static final short[][] DFA31_transition; + + static { + int numStates = DFA31_transitionS.length; + DFA31_transition = new short[numStates][]; + for (int i=0; i ^( T_CONDITION[$wh] conditional_expression ) | 'WHERE' path_expression -> ^( T_CONDITION[$wh] path_expression ) );"; + } + } + static final String DFA36_eotS = + "\7\uffff"; + static final String DFA36_eofS = + "\2\uffff\2\5\2\uffff\1\5"; + static final String DFA36_minS = + "\1\56\1\71\2\26\2\uffff\1\26"; + static final String DFA36_maxS = + "\1\56\1\71\1\66\1\71\2\uffff\1\66"; + static final String DFA36_acceptS = + "\4\uffff\1\2\1\1\1\uffff"; + static final String DFA36_specialS = + "\7\uffff}>"; + static final String[] DFA36_transitionS = { + "\1\1", + "\1\2", + "\1\5\1\4\10\uffff\1\5\7\uffff\1\3\5\uffff\1\3\7\uffff\1\5", + "\1\5\1\4\10\uffff\1\5\25\uffff\1\5\2\uffff\1\6", + "", + "", + "\1\5\1\4\10\uffff\1\5\7\uffff\1\3\5\uffff\1\3\7\uffff\1\5" + }; + + static final short[] DFA36_eot = DFA.unpackEncodedString(DFA36_eotS); + static final short[] DFA36_eof = DFA.unpackEncodedString(DFA36_eofS); + static final char[] DFA36_min = DFA.unpackEncodedStringToUnsignedChars(DFA36_minS); + static final char[] DFA36_max = DFA.unpackEncodedStringToUnsignedChars(DFA36_maxS); + static final short[] DFA36_accept = DFA.unpackEncodedString(DFA36_acceptS); + static final short[] DFA36_special = DFA.unpackEncodedString(DFA36_specialS); + static final short[][] DFA36_transition; + + static { + int numStates = DFA36_transitionS.length; + DFA36_transition = new short[numStates][]; + for (int i=0; i ^( T_ORDER_BY_FIELD[] path_expression ( 'ASC' )? ) | path_expression 'DESC' -> ^( T_ORDER_BY_FIELD[] path_expression 'DESC' ) );"; + } + } + static final String DFA48_eotS = + "\42\uffff"; + static final String DFA48_eofS = + "\42\uffff"; + static final String DFA48_minS = + "\1\30\23\uffff\1\0\15\uffff"; + static final String DFA48_maxS = + "\1\167\23\uffff\1\0\15\uffff"; + static final String DFA48_acceptS = + "\1\uffff\1\1\37\uffff\1\2"; + static final String DFA48_specialS = + "\24\uffff\1\0\15\uffff}>"; + static final String[] DFA48_transitionS = { + "\5\1\2\uffff\1\24\12\uffff\1\1\1\uffff\1\1\1\uffff\2\1\10\uffff"+ + "\1\1\5\uffff\2\1\1\uffff\2\1\6\uffff\4\1\10\uffff\1\1\13\uffff"+ + "\16\1\3\uffff\3\1\1\uffff\2\1", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + }; + + static final short[] DFA48_eot = DFA.unpackEncodedString(DFA48_eotS); + static final short[] DFA48_eof = DFA.unpackEncodedString(DFA48_eofS); + static final char[] DFA48_min = DFA.unpackEncodedStringToUnsignedChars(DFA48_minS); + static final char[] DFA48_max = DFA.unpackEncodedStringToUnsignedChars(DFA48_maxS); + static final short[] DFA48_accept = DFA.unpackEncodedString(DFA48_acceptS); + static final short[] DFA48_special = DFA.unpackEncodedString(DFA48_specialS); + static final short[][] DFA48_transition; + + static { + int numStates = DFA48_transitionS.length; + DFA48_transition = new short[numStates][]; + for (int i=0; i ^( T_SIMPLE_CONDITION[] ( 'NOT' )? simple_cond_expression ) | '(' conditional_expression ')' );"; + } + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA48_20 = input.LA(1); + + + int index48_20 = input.index(); + input.rewind(); + s = -1; + if ( (synpred58_JPA()) ) {s = 1;} + + else if ( (true) ) {s = 33;} + + + input.seek(index48_20); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 48, _s, input); + error(nvae); + throw nvae; + } + } + static final String DFA49_eotS = + "\47\uffff"; + static final String DFA49_eofS = + "\47\uffff"; + static final String DFA49_minS = + "\1\30\15\0\1\uffff\13\0\15\uffff"; + static final String DFA49_maxS = + "\1\167\15\0\1\uffff\13\0\15\uffff"; + static final String DFA49_acceptS = + "\16\uffff\1\1\13\uffff\1\10\1\uffff\1\11\4\uffff\1\2\1\3\1\4\1"+ + "\5\1\6\1\7"; + static final String DFA49_specialS = + "\1\uffff\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\11\1\12\1\13\1"+ + "\14\1\uffff\1\15\1\16\1\17\1\20\1\21\1\22\1\23\1\24\1\25\1\26\1"+ + "\27\15\uffff}>"; + static final String[] DFA49_transitionS = { + "\4\14\1\13\2\uffff\1\23\12\uffff\1\22\1\uffff\1\2\1\uffff\1"+ + "\1\1\4\10\uffff\1\15\5\uffff\1\32\1\34\1\uffff\2\20\6\uffff"+ + "\4\34\10\uffff\1\32\13\uffff\1\24\1\25\1\26\1\27\1\30\1\31\3"+ + "\17\1\6\1\7\1\10\1\11\1\12\3\uffff\1\21\1\3\1\5\1\uffff\2\16", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + }; + + static final short[] DFA49_eot = DFA.unpackEncodedString(DFA49_eotS); + static final short[] DFA49_eof = DFA.unpackEncodedString(DFA49_eofS); + static final char[] DFA49_min = DFA.unpackEncodedStringToUnsignedChars(DFA49_minS); + static final char[] DFA49_max = DFA.unpackEncodedStringToUnsignedChars(DFA49_maxS); + static final short[] DFA49_accept = DFA.unpackEncodedString(DFA49_acceptS); + static final short[] DFA49_special = DFA.unpackEncodedString(DFA49_specialS); + static final short[][] DFA49_transition; + + static { + int numStates = DFA49_transitionS.length; + DFA49_transition = new short[numStates][]; + for (int i=0; i=0 ) return s; + break; + case 1 : + int LA49_2 = input.LA(1); + + + int index49_2 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_2); + if ( s>=0 ) return s; + break; + case 2 : + int LA49_3 = input.LA(1); + + + int index49_3 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + else if ( (synpred63_JPA()) ) {s = 36;} + + else if ( (synpred65_JPA()) ) {s = 38;} + + + input.seek(index49_3); + if ( s>=0 ) return s; + break; + case 3 : + int LA49_4 = input.LA(1); + + + int index49_4 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + else if ( (synpred63_JPA()) ) {s = 36;} + + else if ( (synpred65_JPA()) ) {s = 38;} + + + input.seek(index49_4); + if ( s>=0 ) return s; + break; + case 4 : + int LA49_5 = input.LA(1); + + + int index49_5 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + else if ( (synpred63_JPA()) ) {s = 36;} + + else if ( (synpred65_JPA()) ) {s = 38;} + + + input.seek(index49_5); + if ( s>=0 ) return s; + break; + case 5 : + int LA49_6 = input.LA(1); + + + int index49_6 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_6); + if ( s>=0 ) return s; + break; + case 6 : + int LA49_7 = input.LA(1); + + + int index49_7 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_7); + if ( s>=0 ) return s; + break; + case 7 : + int LA49_8 = input.LA(1); + + + int index49_8 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_8); + if ( s>=0 ) return s; + break; + case 8 : + int LA49_9 = input.LA(1); + + + int index49_9 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_9); + if ( s>=0 ) return s; + break; + case 9 : + int LA49_10 = input.LA(1); + + + int index49_10 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_10); + if ( s>=0 ) return s; + break; + case 10 : + int LA49_11 = input.LA(1); + + + int index49_11 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_11); + if ( s>=0 ) return s; + break; + case 11 : + int LA49_12 = input.LA(1); + + + int index49_12 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_12); + if ( s>=0 ) return s; + break; + case 12 : + int LA49_13 = input.LA(1); + + + int index49_13 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + else if ( (synpred61_JPA()) ) {s = 34;} + + + input.seek(index49_13); + if ( s>=0 ) return s; + break; + case 13 : + int LA49_15 = input.LA(1); + + + int index49_15 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_15); + if ( s>=0 ) return s; + break; + case 14 : + int LA49_16 = input.LA(1); + + + int index49_16 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_16); + if ( s>=0 ) return s; + break; + case 15 : + int LA49_17 = input.LA(1); + + + int index49_17 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_17); + if ( s>=0 ) return s; + break; + case 16 : + int LA49_18 = input.LA(1); + + + int index49_18 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_18); + if ( s>=0 ) return s; + break; + case 17 : + int LA49_19 = input.LA(1); + + + int index49_19 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_19); + if ( s>=0 ) return s; + break; + case 18 : + int LA49_20 = input.LA(1); + + + int index49_20 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_20); + if ( s>=0 ) return s; + break; + case 19 : + int LA49_21 = input.LA(1); + + + int index49_21 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_21); + if ( s>=0 ) return s; + break; + case 20 : + int LA49_22 = input.LA(1); + + + int index49_22 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_22); + if ( s>=0 ) return s; + break; + case 21 : + int LA49_23 = input.LA(1); + + + int index49_23 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_23); + if ( s>=0 ) return s; + break; + case 22 : + int LA49_24 = input.LA(1); + + + int index49_24 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_24); + if ( s>=0 ) return s; + break; + case 23 : + int LA49_25 = input.LA(1); + + + int index49_25 = input.index(); + input.rewind(); + s = -1; + if ( (synpred59_JPA()) ) {s = 14;} + + else if ( (synpred60_JPA()) ) {s = 33;} + + + input.seek(index49_25); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 49, _s, input); + error(nvae); + throw nvae; + } + } + static final String DFA59_eotS = + "\31\uffff"; + static final String DFA59_eofS = + "\31\uffff"; + static final String DFA59_minS = + "\1\30\1\uffff\1\0\3\uffff\3\0\6\uffff\3\0\7\uffff"; + static final String DFA59_maxS = + "\1\164\1\uffff\1\0\3\uffff\3\0\6\uffff\3\0\7\uffff"; + static final String DFA59_acceptS = + "\1\uffff\1\1\20\uffff\1\2\5\uffff\1\3"; + static final String DFA59_specialS = + "\2\uffff\1\0\3\uffff\1\1\1\2\1\3\6\uffff\1\4\1\5\1\6\7\uffff}>"; + static final String[] DFA59_transitionS = { + "\4\20\1\17\2\uffff\1\1\12\uffff\1\1\1\uffff\1\22\1\uffff\1"+ + "\2\1\7\10\uffff\1\21\10\uffff\2\1\36\uffff\6\1\3\30\5\22\3\uffff"+ + "\1\1\1\6\1\10", + "", + "\1\uffff", + "", + "", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "" + }; + + static final short[] DFA59_eot = DFA.unpackEncodedString(DFA59_eotS); + static final short[] DFA59_eof = DFA.unpackEncodedString(DFA59_eofS); + static final char[] DFA59_min = DFA.unpackEncodedStringToUnsignedChars(DFA59_minS); + static final char[] DFA59_max = DFA.unpackEncodedStringToUnsignedChars(DFA59_maxS); + static final short[] DFA59_accept = DFA.unpackEncodedString(DFA59_acceptS); + static final short[] DFA59_special = DFA.unpackEncodedString(DFA59_specialS); + static final short[][] DFA59_transition; + + static { + int numStates = DFA59_transitionS.length; + DFA59_transition = new short[numStates][]; + for (int i=0; i=0 ) return s; + break; + case 1 : + int LA59_6 = input.LA(1); + + + int index59_6 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_6); + if ( s>=0 ) return s; + break; + case 2 : + int LA59_7 = input.LA(1); + + + int index59_7 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_7); + if ( s>=0 ) return s; + break; + case 3 : + int LA59_8 = input.LA(1); + + + int index59_8 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_8); + if ( s>=0 ) return s; + break; + case 4 : + int LA59_15 = input.LA(1); + + + int index59_15 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_15); + if ( s>=0 ) return s; + break; + case 5 : + int LA59_16 = input.LA(1); + + + int index59_16 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_16); + if ( s>=0 ) return s; + break; + case 6 : + int LA59_17 = input.LA(1); + + + int index59_17 = input.index(); + input.rewind(); + s = -1; + if ( (synpred84_JPA()) ) {s = 1;} + + else if ( (synpred86_JPA()) ) {s = 18;} + + else if ( (true) ) {s = 24;} + + + input.seek(index59_17); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 59, _s, input); + error(nvae); + throw nvae; + } + } + static final String DFA79_eotS = + "\34\uffff"; + static final String DFA79_eofS = + "\34\uffff"; + static final String DFA79_minS = + "\1\30\1\0\1\uffff\3\0\5\uffff\3\0\16\uffff"; + static final String DFA79_maxS = + "\1\167\1\0\1\uffff\3\0\5\uffff\3\0\16\uffff"; + static final String DFA79_acceptS = + "\2\uffff\1\1\13\uffff\1\2\1\4\1\6\11\uffff\1\3\1\5"; + static final String DFA79_specialS = + "\1\uffff\1\0\1\uffff\1\1\1\2\1\3\5\uffff\1\4\1\5\1\6\16\uffff}>"; + static final String[] DFA79_transitionS = { + "\4\14\1\13\2\uffff\1\20\12\uffff\1\20\1\uffff\1\2\1\uffff\1"+ + "\1\1\4\10\uffff\1\15\10\uffff\2\20\36\uffff\6\20\3\17\5\2\3"+ + "\uffff\1\20\1\3\1\5\1\uffff\2\16", + "\1\uffff", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + }; + + static final short[] DFA79_eot = DFA.unpackEncodedString(DFA79_eotS); + static final short[] DFA79_eof = DFA.unpackEncodedString(DFA79_eofS); + static final char[] DFA79_min = DFA.unpackEncodedStringToUnsignedChars(DFA79_minS); + static final char[] DFA79_max = DFA.unpackEncodedStringToUnsignedChars(DFA79_maxS); + static final short[] DFA79_accept = DFA.unpackEncodedString(DFA79_acceptS); + static final short[] DFA79_special = DFA.unpackEncodedString(DFA79_specialS); + static final short[][] DFA79_transition; + + static { + int numStates = DFA79_transitionS.length; + DFA79_transition = new short[numStates][]; + for (int i=0; i' ) ( boolean_expression | all_or_any_expression ) | enum_expression ( '=' | '<>' ) ( enum_expression | all_or_any_expression ) | datetime_expression comparison_operator ( datetime_expression | all_or_any_expression ) | entity_expression ( '=' | '<>' ) ( entity_expression | all_or_any_expression ) | arithmetic_expression comparison_operator ( arithmetic_expression | all_or_any_expression ) );"; + } + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA79_1 = input.LA(1); + + + int index79_1 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred107_JPA()) ) {s = 14;} + + else if ( (synpred110_JPA()) ) {s = 26;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (synpred115_JPA()) ) {s = 27;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_1); + if ( s>=0 ) return s; + break; + case 1 : + int LA79_3 = input.LA(1); + + + int index79_3 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred107_JPA()) ) {s = 14;} + + else if ( (synpred110_JPA()) ) {s = 26;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (synpred115_JPA()) ) {s = 27;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_3); + if ( s>=0 ) return s; + break; + case 2 : + int LA79_4 = input.LA(1); + + + int index79_4 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred107_JPA()) ) {s = 14;} + + else if ( (synpred110_JPA()) ) {s = 26;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (synpred115_JPA()) ) {s = 27;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_4); + if ( s>=0 ) return s; + break; + case 3 : + int LA79_5 = input.LA(1); + + + int index79_5 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred107_JPA()) ) {s = 14;} + + else if ( (synpred110_JPA()) ) {s = 26;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (synpred115_JPA()) ) {s = 27;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_5); + if ( s>=0 ) return s; + break; + case 4 : + int LA79_11 = input.LA(1); + + + int index79_11 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_11); + if ( s>=0 ) return s; + break; + case 5 : + int LA79_12 = input.LA(1); + + + int index79_12 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_12); + if ( s>=0 ) return s; + break; + case 6 : + int LA79_13 = input.LA(1); + + + int index79_13 = input.index(); + input.rewind(); + s = -1; + if ( (synpred104_JPA()) ) {s = 2;} + + else if ( (synpred107_JPA()) ) {s = 14;} + + else if ( (synpred110_JPA()) ) {s = 26;} + + else if ( (synpred112_JPA()) ) {s = 15;} + + else if ( (true) ) {s = 16;} + + + input.seek(index79_13); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 79, _s, input); + error(nvae); + throw nvae; + } + } + + + public static final BitSet FOLLOW_select_statement_in_ql_statement426 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_52_in_select_statement441 = new BitSet(new long[]{0x180040021F000000L}); + public static final BitSet FOLLOW_select_clause_in_select_statement443 = new BitSet(new long[]{0x0020000000000000L}); + public static final BitSet FOLLOW_from_clause_in_select_statement445 = new BitSet(new long[]{0x2000018000200002L}); + public static final BitSet FOLLOW_where_clause_in_select_statement448 = new BitSet(new long[]{0x0000018000200002L}); + public static final BitSet FOLLOW_groupby_clause_in_select_statement453 = new BitSet(new long[]{0x0000008000200002L}); + public static final BitSet FOLLOW_having_clause_in_select_statement458 = new BitSet(new long[]{0x0000008000000002L}); + public static final BitSet FOLLOW_orderby_clause_in_select_statement462 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_53_in_from_clause523 = new BitSet(new long[]{0x0100400000000000L}); + public static final BitSet FOLLOW_identification_variable_declaration_in_from_clause525 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_54_in_from_clause528 = new BitSet(new long[]{0x0500400000000000L}); + public static final BitSet FOLLOW_identification_variable_or_collection_declaration_in_from_clause530 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_identification_variable_declaration_in_identification_variable_or_collection_declaration563 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_collection_member_declaration_in_identification_variable_or_collection_declaration571 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_range_variable_declaration_in_identification_variable_declaration594 = new BitSet(new long[]{0x0000003400000002L}); + public static final BitSet FOLLOW_joined_clause_in_identification_variable_declaration596 = new BitSet(new long[]{0x0000003400000002L}); + public static final BitSet FOLLOW_join_in_joined_clause627 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fetch_join_in_joined_clause631 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_range_variable_declaration_source_in_range_variable_declaration643 = new BitSet(new long[]{0x0080400000000000L}); + public static final BitSet FOLLOW_55_in_range_variable_declaration646 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_range_variable_declaration650 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_abstract_schema_name_in_range_variable_declaration_source686 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_56_in_range_variable_declaration_source696 = new BitSet(new long[]{0x180040021F000000L}); + public static final BitSet FOLLOW_select_clause_in_range_variable_declaration_source698 = new BitSet(new long[]{0x0020000000000000L}); + public static final BitSet FOLLOW_from_clause_in_range_variable_declaration_source700 = new BitSet(new long[]{0x2000018100200000L}); + public static final BitSet FOLLOW_where_clause_in_range_variable_declaration_source703 = new BitSet(new long[]{0x0000018100200000L}); + public static final BitSet FOLLOW_groupby_clause_in_range_variable_declaration_source708 = new BitSet(new long[]{0x0000008100200000L}); + public static final BitSet FOLLOW_having_clause_in_range_variable_declaration_source713 = new BitSet(new long[]{0x0000008100000000L}); + public static final BitSet FOLLOW_orderby_clause_in_range_variable_declaration_source717 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_range_variable_declaration_source723 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_join_spec_in_join786 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_join_association_path_expression_in_join788 = new BitSet(new long[]{0x0080400000000000L}); + public static final BitSet FOLLOW_55_in_join791 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_join795 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_join_spec_in_fetch_join833 = new BitSet(new long[]{0x0000004000000000L}); + public static final BitSet FOLLOW_FETCH_in_fetch_join835 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_join_association_path_expression_in_fetch_join837 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LEFT_in_join_spec850 = new BitSet(new long[]{0x0000002800000000L}); + public static final BitSet FOLLOW_OUTER_in_join_spec854 = new BitSet(new long[]{0x0000002000000000L}); + public static final BitSet FOLLOW_INNER_in_join_spec860 = new BitSet(new long[]{0x0000002000000000L}); + public static final BitSet FOLLOW_JOIN_in_join_spec865 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_join_association_path_expression877 = new BitSet(new long[]{0x0200000000000000L}); + public static final BitSet FOLLOW_57_in_join_association_path_expression879 = new BitSet(new long[]{0x0000410000000002L}); + public static final BitSet FOLLOW_field_in_join_association_path_expression882 = new BitSet(new long[]{0x0200000000000000L}); + public static final BitSet FOLLOW_57_in_join_association_path_expression883 = new BitSet(new long[]{0x0000410000000002L}); + public static final BitSet FOLLOW_field_in_join_association_path_expression887 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_58_in_collection_member_declaration924 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_collection_member_declaration925 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_collection_member_declaration927 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_collection_member_declaration929 = new BitSet(new long[]{0x0080400000000000L}); + public static final BitSet FOLLOW_55_in_collection_member_declaration932 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_collection_member_declaration936 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_path_expression971 = new BitSet(new long[]{0x0200000000000000L}); + public static final BitSet FOLLOW_57_in_path_expression973 = new BitSet(new long[]{0x0000410000000002L}); + public static final BitSet FOLLOW_field_in_path_expression976 = new BitSet(new long[]{0x0200000000000000L}); + public static final BitSet FOLLOW_57_in_path_expression977 = new BitSet(new long[]{0x0000410000000002L}); + public static final BitSet FOLLOW_field_in_path_expression982 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DISTINCT_in_select_clause1021 = new BitSet(new long[]{0x180040021F000000L}); + public static final BitSet FOLLOW_select_expression_in_select_clause1025 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_54_in_select_clause1028 = new BitSet(new long[]{0x180040021F000000L}); + public static final BitSet FOLLOW_select_expression_in_select_clause1030 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_path_expression_in_select_expression1075 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_select_expression1083 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_select_expression1091 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_59_in_select_expression1109 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_select_expression1111 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_select_expression1112 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_select_expression1113 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_constructor_expression_in_select_expression1121 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_60_in_constructor_expression1133 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_constructor_name_in_constructor_expression1135 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_constructor_expression1137 = new BitSet(new long[]{0x000040001F000000L}); + public static final BitSet FOLLOW_constructor_item_in_constructor_expression1139 = new BitSet(new long[]{0x0040000100000000L}); + public static final BitSet FOLLOW_54_in_constructor_expression1142 = new BitSet(new long[]{0x000040001F000000L}); + public static final BitSet FOLLOW_constructor_item_in_constructor_expression1144 = new BitSet(new long[]{0x0040000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_constructor_expression1148 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_constructor_item1160 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_constructor_item1164 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_function_name_in_aggregate_expression1176 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_aggregate_expression1178 = new BitSet(new long[]{0x0000400200000000L}); + public static final BitSet FOLLOW_DISTINCT_in_aggregate_expression1181 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_aggregate_expression1185 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_aggregate_expression1186 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_COUNT_in_aggregate_expression1220 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_aggregate_expression1222 = new BitSet(new long[]{0x0000400200000000L}); + public static final BitSet FOLLOW_DISTINCT_in_aggregate_expression1225 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_aggregate_expression1229 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_aggregate_expression1231 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_aggregate_expression_function_name0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_61_in_where_clause1299 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_conditional_expression_in_where_clause1301 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_61_in_where_clause1320 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_where_clause1322 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_GROUP_in_groupby_clause1346 = new BitSet(new long[]{0x0000020000000000L}); + public static final BitSet FOLLOW_BY_in_groupby_clause1348 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_groupby_item_in_groupby_clause1350 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_54_in_groupby_clause1353 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_groupby_item_in_groupby_clause1355 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_path_expression_in_groupby_item1395 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_groupby_item1399 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_HAVING_in_having_clause1411 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_conditional_expression_in_having_clause1413 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ORDER_in_orderby_clause1425 = new BitSet(new long[]{0x0000020000000000L}); + public static final BitSet FOLLOW_BY_in_orderby_clause1427 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_orderby_item_in_orderby_clause1429 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_54_in_orderby_clause1432 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_orderby_item_in_orderby_clause1434 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_path_expression_in_orderby_item1469 = new BitSet(new long[]{0x0000000000400002L}); + public static final BitSet FOLLOW_ASC_in_orderby_item1474 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_orderby_item1506 = new BitSet(new long[]{0x0000000000800000L}); + public static final BitSet FOLLOW_DESC_in_orderby_item1510 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_56_in_subquery1542 = new BitSet(new long[]{0x000040021F000000L}); + public static final BitSet FOLLOW_simple_select_clause_in_subquery1544 = new BitSet(new long[]{0x0020000000000000L}); + public static final BitSet FOLLOW_subquery_from_clause_in_subquery1546 = new BitSet(new long[]{0x2000010100200000L}); + public static final BitSet FOLLOW_where_clause_in_subquery1549 = new BitSet(new long[]{0x0000010100200000L}); + public static final BitSet FOLLOW_groupby_clause_in_subquery1554 = new BitSet(new long[]{0x0000000100200000L}); + public static final BitSet FOLLOW_having_clause_in_subquery1559 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_subquery1565 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_53_in_subquery_from_clause1614 = new BitSet(new long[]{0x0500400000000000L}); + public static final BitSet FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1616 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_54_in_subquery_from_clause1619 = new BitSet(new long[]{0x0500400000000000L}); + public static final BitSet FOLLOW_subselect_identification_variable_declaration_in_subquery_from_clause1621 = new BitSet(new long[]{0x0040000000000002L}); + public static final BitSet FOLLOW_identification_variable_declaration_in_subselect_identification_variable_declaration1659 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_association_path_expression_in_subselect_identification_variable_declaration1667 = new BitSet(new long[]{0x0080400000000000L}); + public static final BitSet FOLLOW_55_in_subselect_identification_variable_declaration1670 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_identification_variable_in_subselect_identification_variable_declaration1674 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_collection_member_declaration_in_subselect_identification_variable_declaration1682 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_association_path_expression1694 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DISTINCT_in_simple_select_clause1707 = new BitSet(new long[]{0x000040021F000000L}); + public static final BitSet FOLLOW_simple_select_expression_in_simple_select_clause1711 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_simple_select_expression1748 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_simple_select_expression1756 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_simple_select_expression1764 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_conditional_term_in_conditional_expression1777 = new BitSet(new long[]{0x0000000020000002L}); + public static final BitSet FOLLOW_OR_in_conditional_expression1781 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_conditional_term_in_conditional_expression1783 = new BitSet(new long[]{0x0000000020000002L}); + public static final BitSet FOLLOW_conditional_factor_in_conditional_term1798 = new BitSet(new long[]{0x0000000040000002L}); + public static final BitSet FOLLOW_AND_in_conditional_term1802 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_conditional_factor_in_conditional_term1804 = new BitSet(new long[]{0x0000000040000002L}); + public static final BitSet FOLLOW_62_in_conditional_factor1823 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_simple_cond_expression_in_conditional_factor1827 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_conditional_factor1852 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_conditional_expression_in_conditional_factor1853 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_conditional_factor1854 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_comparison_expression_in_simple_cond_expression1866 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_between_expression_in_simple_cond_expression1874 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_like_expression_in_simple_cond_expression1882 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_in_expression_in_simple_cond_expression1890 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_null_comparison_expression_in_simple_cond_expression1898 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_empty_collection_comparison_expression_in_simple_cond_expression1906 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_collection_member_expression_in_simple_cond_expression1914 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_exists_expression_in_simple_cond_expression1922 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_macro_expression_in_simple_cond_expression1930 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_between_macro_expression_in_date_macro_expression1942 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_before_macro_expression_in_date_macro_expression1950 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_after_macro_expression_in_date_macro_expression1958 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_equals_macro_expression_in_date_macro_expression1966 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_date_today_macro_expression_in_date_macro_expression1974 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_63_in_date_between_macro_expression1986 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_date_between_macro_expression1988 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_between_macro_expression1990 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_between_macro_expression1992 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000001L}); + public static final BitSet FOLLOW_64_in_date_between_macro_expression1994 = new BitSet(new long[]{0x0040000000000000L,0x0000000000000006L}); + public static final BitSet FOLLOW_set_in_date_between_macro_expression1997 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_INT_NUMERAL_in_date_between_macro_expression2005 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_between_macro_expression2009 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000001L}); + public static final BitSet FOLLOW_64_in_date_between_macro_expression2011 = new BitSet(new long[]{0x0040000000000000L,0x0000000000000006L}); + public static final BitSet FOLLOW_set_in_date_between_macro_expression2014 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_INT_NUMERAL_in_date_between_macro_expression2022 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_between_macro_expression2026 = new BitSet(new long[]{0x0000000000000000L,0x00000000000001F8L}); + public static final BitSet FOLLOW_set_in_date_between_macro_expression2028 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_date_between_macro_expression2051 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_73_in_date_before_macro_expression2063 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_date_before_macro_expression2065 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_before_macro_expression2067 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_before_macro_expression2069 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_before_macro_expression2072 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_input_parameter_in_date_before_macro_expression2076 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_date_before_macro_expression2079 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_74_in_date_after_macro_expression2091 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_date_after_macro_expression2093 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_after_macro_expression2095 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_after_macro_expression2097 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_after_macro_expression2100 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_input_parameter_in_date_after_macro_expression2104 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_date_after_macro_expression2107 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_75_in_date_equals_macro_expression2119 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_date_equals_macro_expression2121 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_equals_macro_expression2123 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_date_equals_macro_expression2125 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_equals_macro_expression2128 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_input_parameter_in_date_equals_macro_expression2132 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_date_equals_macro_expression2135 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_76_in_date_today_macro_expression2147 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_date_today_macro_expression2149 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_date_today_macro_expression2151 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_date_today_macro_expression2153 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2165 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_62_in_between_expression2168 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_77_in_between_expression2172 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); + public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2174 = new BitSet(new long[]{0x0000000040000000L}); + public static final BitSet FOLLOW_AND_in_between_expression2176 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); + public static final BitSet FOLLOW_arithmetic_expression_in_between_expression2178 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_expression_in_between_expression2186 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_62_in_between_expression2189 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_77_in_between_expression2193 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_expression_in_between_expression2195 = new BitSet(new long[]{0x0000000040000000L}); + public static final BitSet FOLLOW_AND_in_between_expression2197 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_expression_in_between_expression2199 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_datetime_expression_in_between_expression2207 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_62_in_between_expression2210 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_77_in_between_expression2214 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8000000000L}); + public static final BitSet FOLLOW_datetime_expression_in_between_expression2216 = new BitSet(new long[]{0x0000000040000000L}); + public static final BitSet FOLLOW_AND_in_between_expression2218 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8000000000L}); + public static final BitSet FOLLOW_datetime_expression_in_between_expression2220 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_in_expression2232 = new BitSet(new long[]{0x4400000000000000L}); + public static final BitSet FOLLOW_62_in_in_expression2235 = new BitSet(new long[]{0x0400000000000000L}); + public static final BitSet FOLLOW_58_in_in_expression2239 = new BitSet(new long[]{0x0100D0009F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_in_expression_right_part_in_in_expression2241 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_in_expression_right_part2253 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_in_item_in_in_expression_right_part2255 = new BitSet(new long[]{0x0040000100000000L}); + public static final BitSet FOLLOW_54_in_in_expression_right_part2258 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_in_item_in_in_expression_right_part2260 = new BitSet(new long[]{0x0040000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_in_expression_right_part2264 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_in_expression_right_part2272 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_literal_in_in_item2284 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_in_item2292 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_expression_in_like_expression2304 = new BitSet(new long[]{0x4000000000000000L,0x0000000000004000L}); + public static final BitSet FOLLOW_62_in_like_expression2307 = new BitSet(new long[]{0x0000000000000000L,0x0000000000004000L}); + public static final BitSet FOLLOW_78_in_like_expression2311 = new BitSet(new long[]{0x0000C00000000000L,0x0018000000000000L}); + public static final BitSet FOLLOW_pattern_value_in_like_expression2314 = new BitSet(new long[]{0x0000000000000002L,0x0000000000008000L}); + public static final BitSet FOLLOW_input_parameter_in_like_expression2318 = new BitSet(new long[]{0x0000000000000002L,0x0000000000008000L}); + public static final BitSet FOLLOW_79_in_like_expression2321 = new BitSet(new long[]{0x0000080000000000L}); + public static final BitSet FOLLOW_ESCAPE_CHARACTER_in_like_expression2323 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_null_comparison_expression2338 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); + public static final BitSet FOLLOW_input_parameter_in_null_comparison_expression2342 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); + public static final BitSet FOLLOW_80_in_null_comparison_expression2345 = new BitSet(new long[]{0x4000000000000000L,0x0000000000020000L}); + public static final BitSet FOLLOW_62_in_null_comparison_expression2348 = new BitSet(new long[]{0x0000000000000000L,0x0000000000020000L}); + public static final BitSet FOLLOW_81_in_null_comparison_expression2352 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_empty_collection_comparison_expression2364 = new BitSet(new long[]{0x0000000000000000L,0x0000000000010000L}); + public static final BitSet FOLLOW_80_in_empty_collection_comparison_expression2366 = new BitSet(new long[]{0x4000000000000000L,0x0000000000040000L}); + public static final BitSet FOLLOW_62_in_empty_collection_comparison_expression2369 = new BitSet(new long[]{0x0000000000000000L,0x0000000000040000L}); + public static final BitSet FOLLOW_82_in_empty_collection_comparison_expression2373 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_entity_expression_in_collection_member_expression2385 = new BitSet(new long[]{0x4000000000000000L,0x0000000000080000L}); + public static final BitSet FOLLOW_62_in_collection_member_expression2388 = new BitSet(new long[]{0x0000000000000000L,0x0000000000080000L}); + public static final BitSet FOLLOW_83_in_collection_member_expression2392 = new BitSet(new long[]{0x0000400000000000L,0x0000000000100000L}); + public static final BitSet FOLLOW_84_in_collection_member_expression2395 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_collection_member_expression2399 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_62_in_exists_expression2412 = new BitSet(new long[]{0x0000000000000000L,0x0000000000200000L}); + public static final BitSet FOLLOW_85_in_exists_expression2416 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_subquery_in_exists_expression2418 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_all_or_any_expression2430 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_subquery_in_all_or_any_expression2443 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_expression_in_comparison_expression2455 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); + public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2457 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_string_expression_in_comparison_expression2460 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2464 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_boolean_expression_in_comparison_expression2473 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_comparison_expression2475 = new BitSet(new long[]{0x0100D0001F000000L,0x00D87C0001C00000L}); + public static final BitSet FOLLOW_boolean_expression_in_comparison_expression2484 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2488 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_enum_expression_in_comparison_expression2497 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_comparison_expression2499 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_enum_expression_in_comparison_expression2506 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2510 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_datetime_expression_in_comparison_expression2519 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); + public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2521 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8001C00000L}); + public static final BitSet FOLLOW_datetime_expression_in_comparison_expression2524 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2528 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_entity_expression_in_comparison_expression2537 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_comparison_expression2539 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_entity_expression_in_comparison_expression2548 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2552 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_arithmetic_expression_in_comparison_expression2561 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); + public static final BitSet FOLLOW_comparison_operator_in_comparison_expression2563 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE01C00006L}); + public static final BitSet FOLLOW_arithmetic_expression_in_comparison_expression2566 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_comparison_expression2570 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_comparison_operator0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_arithmetic_expression2635 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_arithmetic_expression2643 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_arithmetic_term_in_simple_arithmetic_expression2656 = new BitSet(new long[]{0x0000000000000002L,0x0000000000000006L}); + public static final BitSet FOLLOW_set_in_simple_arithmetic_expression2660 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_arithmetic_term_in_simple_arithmetic_expression2670 = new BitSet(new long[]{0x0000000000000002L,0x0000000000000006L}); + public static final BitSet FOLLOW_arithmetic_factor_in_arithmetic_term2685 = new BitSet(new long[]{0x0000000000000002L,0x0000000180000000L}); + public static final BitSet FOLLOW_set_in_arithmetic_term2689 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_arithmetic_factor_in_arithmetic_term2699 = new BitSet(new long[]{0x0000000000000002L,0x0000000180000000L}); + public static final BitSet FOLLOW_set_in_arithmetic_factor2713 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_arithmetic_primary_in_arithmetic_factor2724 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_arithmetic_primary2736 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_numeric_literal_in_arithmetic_primary2744 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_arithmetic_primary2752 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_arithmetic_primary2753 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_arithmetic_primary2754 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_arithmetic_primary2762 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_functions_returning_numerics_in_arithmetic_primary2770 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_arithmetic_primary2778 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_primary_in_string_expression2790 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_string_expression2794 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_string_primary2806 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STRINGLITERAL_in_string_primary2814 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_string_primary2822 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_functions_returning_strings_in_string_primary2830 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_string_primary2838 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_datetime_primary_in_datetime_expression2850 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_datetime_expression2858 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_datetime_primary2870 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_datetime_primary2878 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_functions_returning_datetime_in_datetime_primary2886 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_aggregate_expression_in_datetime_primary2894 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_boolean_primary_in_boolean_expression2906 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_boolean_expression2914 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_boolean_primary2926 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_boolean_literal_in_boolean_primary2934 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_boolean_primary2942 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_enum_primary_in_enum_expression2954 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_subquery_in_enum_expression2962 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_enum_primary2974 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_enum_literal_in_enum_primary2982 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_enum_primary2990 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_path_expression_in_entity_expression3002 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_simple_entity_expression_in_entity_expression3010 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identification_variable_in_simple_entity_expression3022 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_input_parameter_in_simple_entity_expression3030 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_97_in_functions_returning_numerics3042 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3044 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3045 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3046 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_98_in_functions_returning_numerics3054 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3056 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3057 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_numerics3058 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_numerics3060 = new BitSet(new long[]{0x0040000100000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_numerics3062 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3064 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3067 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_99_in_functions_returning_numerics3075 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3077 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3078 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3079 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_100_in_functions_returning_numerics3087 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3089 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3090 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3091 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_101_in_functions_returning_numerics3099 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3101 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3102 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_numerics3103 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_numerics3105 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3106 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_102_in_functions_returning_numerics3114 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_numerics3116 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_path_expression_in_functions_returning_numerics3117 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_numerics3118 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_functions_returning_datetime0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_106_in_functions_returning_strings3158 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3160 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3161 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_strings3162 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3164 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3165 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_107_in_functions_returning_strings3173 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3175 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3176 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_strings3177 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3178 = new BitSet(new long[]{0x0040000000000000L}); + public static final BitSet FOLLOW_54_in_functions_returning_strings3179 = new BitSet(new long[]{0x0000C4009F000000L,0x001C007E00000006L}); + public static final BitSet FOLLOW_simple_arithmetic_expression_in_functions_returning_strings3181 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3182 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_108_in_functions_returning_strings3190 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3192 = new BitSet(new long[]{0x0020F0001F000000L,0x001BFC0000000000L}); + public static final BitSet FOLLOW_trim_specification_in_functions_returning_strings3195 = new BitSet(new long[]{0x0020200000000000L}); + public static final BitSet FOLLOW_TRIM_CHARACTER_in_functions_returning_strings3200 = new BitSet(new long[]{0x0020000000000000L}); + public static final BitSet FOLLOW_53_in_functions_returning_strings3204 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3208 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3209 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_109_in_functions_returning_strings3217 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3219 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3220 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3221 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_110_in_functions_returning_strings3229 = new BitSet(new long[]{0x0000000080000000L}); + public static final BitSet FOLLOW_LPAREN_in_functions_returning_strings3231 = new BitSet(new long[]{0x0000D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_primary_in_functions_returning_strings3232 = new BitSet(new long[]{0x0000000100000000L}); + public static final BitSet FOLLOW_RPAREN_in_functions_returning_strings3233 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_trim_specification0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_abstract_schema_name3274 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_pattern_value3287 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_114_in_numeric_literal3301 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_INT_NUMERAL_in_numeric_literal3305 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_115_in_input_parameter3318 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_INT_NUMERAL_in_input_parameter3320 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NAMED_PARAMETER_in_input_parameter3343 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_116_in_input_parameter3364 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_WORD_in_input_parameter3366 = new BitSet(new long[]{0x0000000000000000L,0x0020000000000000L}); + public static final BitSet FOLLOW_117_in_input_parameter3368 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_literal3396 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_constructor_name3408 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_enum_literal3452 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_boolean_literal0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_field0 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_identification_variable3501 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WORD_in_parameter_name3513 = new BitSet(new long[]{0x0200000000000002L}); + public static final BitSet FOLLOW_57_in_parameter_name3516 = new BitSet(new long[]{0x0000400000000000L}); + public static final BitSet FOLLOW_WORD_in_parameter_name3519 = new BitSet(new long[]{0x0200000000000002L}); + public static final BitSet FOLLOW_field_in_synpred20_JPA887 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_field_in_synpred23_JPA982 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_62_in_synpred57_JPA1823 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_62_in_synpred58_JPA1823 = new BitSet(new long[]{0xC100D4009F000000L,0x00DC7FFE00201E06L}); + public static final BitSet FOLLOW_simple_cond_expression_in_synpred58_JPA1827 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_comparison_expression_in_synpred59_JPA1866 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_between_expression_in_synpred60_JPA1874 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_like_expression_in_synpred61_JPA1882 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_in_expression_in_synpred62_JPA1890 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_null_comparison_expression_in_synpred63_JPA1898 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_empty_collection_comparison_expression_in_synpred64_JPA1906 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_collection_member_expression_in_synpred65_JPA1914 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2165 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_62_in_synpred84_JPA2168 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_77_in_synpred84_JPA2172 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); + public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2174 = new BitSet(new long[]{0x0000000040000000L}); + public static final BitSet FOLLOW_AND_in_synpred84_JPA2176 = new BitSet(new long[]{0x0100D4009F000000L,0x00DC7FFE00000006L}); + public static final BitSet FOLLOW_arithmetic_expression_in_synpred84_JPA2178 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2186 = new BitSet(new long[]{0x4000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_62_in_synpred86_JPA2189 = new BitSet(new long[]{0x0000000000000000L,0x0000000000002000L}); + public static final BitSet FOLLOW_77_in_synpred86_JPA2193 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2195 = new BitSet(new long[]{0x0000000040000000L}); + public static final BitSet FOLLOW_AND_in_synpred86_JPA2197 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0000000000L}); + public static final BitSet FOLLOW_string_expression_in_synpred86_JPA2199 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_string_expression_in_synpred104_JPA2455 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); + public static final BitSet FOLLOW_comparison_operator_in_synpred104_JPA2457 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_string_expression_in_synpred104_JPA2460 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_synpred104_JPA2464 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_boolean_expression_in_synpred107_JPA2473 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_synpred107_JPA2475 = new BitSet(new long[]{0x0100D0001F000000L,0x00D87C0001C00000L}); + public static final BitSet FOLLOW_boolean_expression_in_synpred107_JPA2484 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_synpred107_JPA2488 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_enum_expression_in_synpred110_JPA2497 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_synpred110_JPA2499 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_enum_expression_in_synpred110_JPA2506 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_synpred110_JPA2510 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_datetime_expression_in_synpred112_JPA2519 = new BitSet(new long[]{0x0000000000000000L,0x000000007E000000L}); + public static final BitSet FOLLOW_comparison_operator_in_synpred112_JPA2521 = new BitSet(new long[]{0x0100D0001F000000L,0x00187F8001C00000L}); + public static final BitSet FOLLOW_datetime_expression_in_synpred112_JPA2524 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_synpred112_JPA2528 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_entity_expression_in_synpred115_JPA2537 = new BitSet(new long[]{0x0000000000000000L,0x0000000006000000L}); + public static final BitSet FOLLOW_set_in_synpred115_JPA2539 = new BitSet(new long[]{0x0100D0001F000000L,0x00187C0001C00000L}); + public static final BitSet FOLLOW_entity_expression_in_synpred115_JPA2548 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_all_or_any_expression_in_synpred115_JPA2552 = new BitSet(new long[]{0x0000000000000002L}); + + @Override + public void emitErrorMessage(String msg) { + //do nothing + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/JPA2.g b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/JPA2.g index 28bcdc9420..ff22e21e6a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/JPA2.g +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/JPA2.g @@ -1,583 +1,583 @@ -grammar JPA2; - -options{ - backtrack=true;//todo eude this is the source of bad performance - try to get rid of it - output=AST; -} - -tokens { - T_SELECTED_ITEMS; - T_SELECTED_ITEM; - T_SOURCES; - T_SOURCE; - T_SELECTED_FIELD; - T_SELECTED_ENTITY; - T_ID_VAR; - T_JOIN_VAR; - T_COLLECTION_MEMBER; - T_QUERY; - T_CONDITION; - T_SIMPLE_CONDITION; - T_PARAMETER; - T_GROUP_BY; - T_ORDER_BY; - T_ORDER_BY_FIELD; - T_AGGREGATE_EXPR; - T_ENUM_MACROS; - HAVING = 'HAVING'; - ASC = 'ASC'; - DESC = 'DESC'; - AVG = 'AVG'; - MAX = 'MAX'; - MIN = 'MIN'; - SUM = 'SUM'; - COUNT = 'COUNT'; - LOWER = 'LOWER'; - OR = 'OR'; - AND = 'AND'; - LPAREN = '('; - RPAREN = ')'; - DISTINCT = 'DISTINCT'; - LEFT = 'LEFT'; - OUTER = 'OUTER'; - INNER = 'INNER'; - JOIN = 'JOIN'; - FETCH = 'FETCH'; - ORDER = 'ORDER'; - GROUP = 'GROUP'; - BY = 'BY'; - SET = 'SET'; - AS = 'AS'; -} - - -@header { -package com.haulmont.cuba.core.sys.jpql.antlr2; - -import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; -import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import com.haulmont.cuba.core.sys.jpql.tree.FromNode; -import com.haulmont.cuba.core.sys.jpql.tree.SelectionSourceNode; -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.CollectionMemberNode; -import com.haulmont.cuba.core.sys.jpql.tree.WhereNode; -import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; -import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; -import com.haulmont.cuba.core.sys.jpql.tree.GroupByNode; -import com.haulmont.cuba.core.sys.jpql.tree.OrderByNode; -import com.haulmont.cuba.core.sys.jpql.tree.OrderByFieldNode; -import com.haulmont.cuba.core.sys.jpql.tree.AggregateExpressionNode; -import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemsNode; -import com.haulmont.cuba.core.sys.jpql.tree.UpdateSetNode; -import com.haulmont.cuba.core.sys.jpql.tree.EnumConditionNode; -} - -@lexer::header { -package com.haulmont.cuba.core.sys.jpql.antlr2; - -} - -ql_statement - : select_statement | update_statement | delete_statement; - -select_statement - : sl='SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)? - -> ^(T_QUERY[$sl] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?); - -update_statement - : up='UPDATE' update_clause (where_clause)? - -> ^(T_QUERY[$up] update_clause (where_clause)?); -delete_statement - : dl='DELETE' delete_clause (where_clause)? - -> ^(T_QUERY[$dl] delete_clause (where_clause)?); - -from_clause - : fr='FROM' identification_variable_declaration (',' identification_variable_declaration_or_collection_member_declaration)* - -> ^(T_SOURCES[$fr] identification_variable_declaration identification_variable_declaration_or_collection_member_declaration*); -identification_variable_declaration_or_collection_member_declaration - : identification_variable_declaration - | collection_member_declaration -> ^(T_SOURCE collection_member_declaration); - -identification_variable_declaration - : range_variable_declaration joined_clause* - -> ^(T_SOURCE range_variable_declaration joined_clause*); -join_section : - joined_clause*; -joined_clause : join | fetch_join; -range_variable_declaration - : entity_name (AS)? identification_variable - -> ^(T_ID_VAR[$identification_variable.text] entity_name); -join - : join_spec join_association_path_expression (AS)? identification_variable ('ON' conditional_expression)? - -> ^(T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression conditional_expression?); -fetch_join - : join_spec 'FETCH' join_association_path_expression; -join_spec - : (('LEFT') ('OUTER')? | 'INNER' )? 'JOIN'; - -//Start : here we have simplified joins -join_association_path_expression - : identification_variable '.' (field'.')* field? - -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) - | 'TREAT(' identification_variable '.' (field'.')* field? AS subtype ')' - -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) - | entity_name; -//End : here we have simplified joins - -collection_member_declaration - : 'IN''(' path_expression ')' (AS)? identification_variable - -> ^(T_COLLECTION_MEMBER[$identification_variable.text] path_expression ); - -qualified_identification_variable - : map_field_identification_variable - | 'ENTRY('identification_variable')'; -map_field_identification_variable : 'KEY('identification_variable')' | 'VALUE('identification_variable')'; - -//Start : here we have simplified paths -path_expression - : identification_variable '.' (field'.')* field? - -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) - ; -//todo eude treated path -//End : here we have simplified paths - -general_identification_variable - : identification_variable - | map_field_identification_variable; - -//todo eude implement separate node instead of SelectionSourceNode for update and delete? -update_clause - : identification_variable_declaration SET update_item (',' update_item)* - -> ^(T_SOURCES identification_variable_declaration SET update_item (',' update_item)*); -update_item - : path_expression '=' new_value; -new_value - : scalar_expression - | simple_entity_expression - | 'NULL'; - -delete_clause - : fr='FROM' identification_variable_declaration - -> ^(T_SOURCES[$fr] identification_variable_declaration); -select_clause - : ('DISTINCT')? select_item (',' select_item)* - -> ^(T_SELECTED_ITEMS[] ('DISTINCT')? ^(T_SELECTED_ITEM[] select_item)*); -select_item - : select_expression ((AS)? result_variable)?; -select_expression - : path_expression (('+' | '-' | '*' | '/') scalar_expression)? - | identification_variable -> ^(T_SELECTED_ENTITY[$identification_variable.text]) - | scalar_expression - | aggregate_expression - | 'OBJECT' '('identification_variable')' - | constructor_expression; -constructor_expression - : 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')'; -constructor_item - : path_expression - | scalar_expression - | aggregate_expression - | identification_variable; -aggregate_expression - : aggregate_expression_function_name '('(DISTINCT)? arithmetic_expression')' - -> ^(T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ('DISTINCT')? arithmetic_expression')') - | 'COUNT' '('(DISTINCT)? count_argument ')' - -> ^(T_AGGREGATE_EXPR[] 'COUNT' '(' ('DISTINCT')? count_argument ')') - | function_invocation; -aggregate_expression_function_name - : 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT'; -count_argument - : identification_variable | path_expression; -where_clause - : wh='WHERE' conditional_expression-> ^(T_CONDITION[$wh] conditional_expression); -groupby_clause - : 'GROUP' 'BY' groupby_item (',' groupby_item)* - -> ^(T_GROUP_BY[] 'GROUP' 'BY' groupby_item*); -groupby_item - : path_expression | identification_variable | extract_function; -having_clause - : 'HAVING' conditional_expression; -orderby_clause - : 'ORDER' 'BY' orderby_item (',' orderby_item)* - -> ^(T_ORDER_BY[] 'ORDER' 'BY' orderby_item*); -orderby_item - : orderby_variable sort? sortNulls? - -> ^(T_ORDER_BY_FIELD[] orderby_variable sort? sortNulls?); -orderby_variable - : path_expression | general_identification_variable | result_variable | scalar_expression | aggregate_expression; -sort - : ('ASC' | 'DESC'); -sortNulls - : ('NULLS FIRST' | 'NULLS LAST'); -subquery - : lp='(' 'SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')' - -> ^(T_QUERY[$lp,$rp] 'SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? ); -subquery_from_clause - : fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)* - -> ^(T_SOURCES[$fr] ^(T_SOURCE subselect_identification_variable_declaration)*); - -subselect_identification_variable_declaration - : identification_variable_declaration - | derived_path_expression AS identification_variable (join)* - | derived_collection_member_declaration; -derived_path_expression - : general_derived_path'.'single_valued_object_field - | general_derived_path'.'collection_valued_field; -general_derived_path - : simple_derived_path - | treated_derived_path('.'single_valued_object_field)* - ; -simple_derived_path - : superquery_identification_variable //todo eude ('.' single_valued_object_field)* - ; -treated_derived_path - : 'TREAT('general_derived_path AS subtype ')'; -derived_collection_member_declaration - : 'IN' superquery_identification_variable'.'(single_valued_object_field '.')*collection_valued_field; - -simple_select_clause - : ('DISTINCT')? simple_select_expression - -> ^(T_SELECTED_ITEMS[] ^(T_SELECTED_ITEM[] ('DISTINCT')? simple_select_expression)); -simple_select_expression - : path_expression - | scalar_expression - | aggregate_expression - | identification_variable; -scalar_expression - : arithmetic_expression - | string_expression - | enum_expression - | datetime_expression - | boolean_expression - | case_expression - | entity_type_expression; -conditional_expression - : (conditional_term) ('OR' conditional_term)*; -conditional_term - : (conditional_factor) ('AND' conditional_factor)*; -conditional_factor - : ('NOT')? conditional_primary; -conditional_primary - : simple_cond_expression - -> ^(T_SIMPLE_CONDITION[] simple_cond_expression) - | '('conditional_expression')'; -simple_cond_expression - : comparison_expression - | between_expression - | in_expression - | like_expression - | null_comparison_expression - | empty_collection_comparison_expression - | collection_member_expression - | exists_expression - | date_macro_expression; - -//Start: Here we insert our custom macroses -date_macro_expression - : date_between_macro_expression - | date_before_macro_expression - | date_after_macro_expression - | date_equals_macro_expression - | date_today_macro_expression; - -date_between_macro_expression - : '@BETWEEN' '(' path_expression ',' 'NOW' (('+' | '-') numeric_literal)? ',' 'NOW' (('+' | '-') numeric_literal)? ',' ('YEAR' | 'MONTH' | 'DAY' | 'HOUR' |'MINUTE' | 'SECOND') ')'; - -date_before_macro_expression - : '@DATEBEFORE' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_after_macro_expression - : '@DATEAFTER' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_equals_macro_expression - : '@DATEEQUALS' '(' path_expression ',' (path_expression | input_parameter) ')'; - -date_today_macro_expression - : '@TODAY' '(' path_expression ')'; -//End: Here we insert our custom macroses - -between_expression - : arithmetic_expression ('NOT')? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression - | string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression - | datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression; -in_expression - : (path_expression | type_discriminator | identification_variable) (NOT)? IN - ( '(' in_item (',' in_item)* ')' - | subquery - | collection_valued_input_parameter - | '(' path_expression ')' ); - -NOT: 'NOT'; - -IN: 'IN'; - -in_item - : string_literal | numeric_literal | single_valued_input_parameter | enum_function; -like_expression - : string_expression ('NOT')? 'LIKE' (string_expression | pattern_value | input_parameter)('ESCAPE' escape_character)?; -null_comparison_expression - : (path_expression | input_parameter | join_association_path_expression) 'IS' ('NOT')? 'NULL'; -empty_collection_comparison_expression - : path_expression 'IS' ('NOT')? 'EMPTY'; -collection_member_expression - : entity_or_value_expression ('NOT')? 'MEMBER' ('OF')? path_expression; -entity_or_value_expression - : path_expression - | simple_entity_or_value_expression - | subquery; -simple_entity_or_value_expression - : identification_variable - | input_parameter - | literal; -exists_expression - : ('NOT')? 'EXISTS' subquery; -all_or_any_expression - : ( 'ALL' | 'ANY' | 'SOME') subquery; -comparison_expression - : string_expression (comparison_operator | 'REGEXP') (string_expression | all_or_any_expression) - | boolean_expression ('=' | '<>') (boolean_expression | all_or_any_expression) - | enum_expression ('='|'<>') (enum_expression | all_or_any_expression) - | datetime_expression comparison_operator (datetime_expression | all_or_any_expression) - | entity_expression ('=' | '<>') (entity_expression | all_or_any_expression) - | entity_type_expression ('=' | '<>') entity_type_expression - | arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression); - -comparison_operator - : '=' - | '>' - | '>=' - | '<' - | '<=' - | '<>'; -arithmetic_expression - : arithmetic_term ('+' | '-') arithmetic_term - | arithmetic_term; -arithmetic_term - : arithmetic_factor ( '*' | '/') arithmetic_factor - | arithmetic_factor; -arithmetic_factor - : (( '+' | '-'))? arithmetic_primary; -arithmetic_primary - : path_expression - | numeric_literal - | '('arithmetic_expression')' - | input_parameter - | functions_returning_numerics - | aggregate_expression - | case_expression - | function_invocation - | extension_functions - | subquery; -string_expression - : path_expression - | string_literal - | input_parameter - | functions_returning_strings - | aggregate_expression - | case_expression - | function_invocation - | extension_functions - | subquery; -datetime_expression - : path_expression - | input_parameter - | functions_returning_datetime - | aggregate_expression - | case_expression - | function_invocation - | extension_functions - | date_time_timestamp_literal - | subquery; -boolean_expression - : path_expression - | boolean_literal - | input_parameter - | case_expression - | function_invocation - | extension_functions - | subquery; -enum_expression - : path_expression - | enum_literal - | input_parameter - | case_expression - | subquery; -entity_expression - : path_expression - | simple_entity_expression; -simple_entity_expression - : identification_variable - | input_parameter; -entity_type_expression - : type_discriminator - | entity_type_literal - | input_parameter; -type_discriminator - : 'TYPE(' (general_identification_variable | path_expression | input_parameter) ')'; -functions_returning_numerics - : 'LENGTH('string_expression')' - | 'LOCATE(' string_expression',' string_expression(','arithmetic_expression)?')' - | 'ABS('arithmetic_expression')' - | 'SQRT('arithmetic_expression')' - | 'MOD('arithmetic_expression',' arithmetic_expression')' - | 'SIZE('path_expression')' - | 'INDEX('identification_variable')'; -functions_returning_datetime - : 'CURRENT_DATE' - | 'CURRENT_TIME' - | 'CURRENT_TIMESTAMP'; -functions_returning_strings - : 'CONCAT('string_expression',' string_expression (',' string_expression)*')' - | 'SUBSTRING(' string_expression',' arithmetic_expression (',' arithmetic_expression)?')' - | 'TRIM('((trim_specification)? (trim_character)? 'FROM')? string_expression ')' - | 'LOWER' '('string_expression')' - | 'UPPER('string_expression')'; -trim_specification - : 'LEADING' | 'TRAILING' | 'BOTH'; -function_invocation - : 'FUNCTION('function_name (',' function_arg)* ')'; -function_arg - : literal - | path_expression - | input_parameter - | scalar_expression; -case_expression - : general_case_expression - | simple_case_expression - | coalesce_expression - | nullif_expression; -general_case_expression - : 'CASE' when_clause (when_clause)* 'ELSE' scalar_expression 'END'; -when_clause - : 'WHEN' conditional_expression 'THEN' scalar_expression; -simple_case_expression - : 'CASE' case_operand simple_when_clause (simple_when_clause)* 'ELSE' scalar_expression 'END'; -case_operand - : path_expression - | type_discriminator; -simple_when_clause - : 'WHEN' scalar_expression 'THEN' scalar_expression; -coalesce_expression - : 'COALESCE('scalar_expression (',' scalar_expression)+')'; -nullif_expression - : 'NULLIF('scalar_expression ',' scalar_expression')'; - -extension_functions - : 'CAST(' function_arg WORD ('('INT_NUMERAL (',' INT_NUMERAL)* ')')* ')' - | extract_function - | enum_function; - -extract_function - : 'EXTRACT(' date_part 'FROM' function_arg ')'; - -enum_function - : '@ENUM' '(' enum_value_literal ')' -> ^(T_ENUM_MACROS[$enum_value_literal.text]); - -fragment date_part - : 'EPOCH' | 'YEAR' | 'QUARTER' | 'MONTH' | 'WEEK' |'DAY' | 'HOUR' |'MINUTE' | 'SECOND'; - -//Start : Here we insert tail from old grammar -input_parameter - : '?' numeric_literal -> ^(T_PARAMETER[] '?' numeric_literal ) - | NAMED_PARAMETER -> ^(T_PARAMETER[] NAMED_PARAMETER ) - | '${' WORD '}' -> ^(T_PARAMETER[] '${' WORD '}'); - -literal - : WORD; - -constructor_name - : WORD; - -enum_literal - : WORD; - -boolean_literal - : 'true' - | 'false'; - -//todo eude the following is just a workaround for entity fields equal to keywords. We need to get rid of it somehow. -field - : WORD | 'SELECT' | 'FROM' | 'GROUP' | 'ORDER' | 'MAX' | 'MIN' | 'SUM' | 'AVG' | 'COUNT' | 'AS' | 'MEMBER' | date_part; - -identification_variable - : WORD | 'GROUP'; - -parameter_name - : WORD ('.' WORD)*; - -//todo eude ESCAPE_CHARACTER should be here instead of STRING_LITERAL, but it does not work for some reason, so workarounded with STRING_LITERAL -escape_character - : '\'.\'' | STRING_LITERAL; -trim_character - : TRIM_CHARACTER; -string_literal - : STRING_LITERAL; -numeric_literal - : ('0x')? INT_NUMERAL ; -single_valued_object_field - : WORD; -single_valued_embeddable_object_field - : WORD; -collection_valued_field - : WORD; -entity_name - : WORD; -subtype - : WORD; -entity_type_literal - : WORD; -function_name - : STRING_LITERAL; -state_field - : WORD; -result_variable - : WORD; -superquery_identification_variable - : WORD; -date_time_timestamp_literal - : WORD; -pattern_value - : string_literal; -collection_valued_input_parameter - : input_parameter; -single_valued_input_parameter - : input_parameter; -enum_value_literal - : WORD ('.' WORD)*; - -// Lexical Rules -//fix trim character -TRIM_CHARACTER - : '\'.\''; - -STRING_LITERAL - : '\'' (~('\'' | '"') )* '\'' ; - -WORD - : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')*; - -RUSSIAN_SYMBOLS - : ('\u0400'..'\u04FF'|'\u0500'..'\u052F' ) {if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol");}; - -NAMED_PARAMETER - : ':' ('(?i)'|'(?I)')? ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* (('.') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')+)*; - -WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} - ; - -COMMENT - : '/*' .* '*/' {$channel=HIDDEN;}; - -LINE_COMMENT - : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}; - -ESCAPE_CHARACTER - : '\'' (~('\''|'\\') ) '\''; - -INT_NUMERAL - : ('0'..'9')+; -//End : Here we insert tail from old grammar - - +grammar JPA2; + +options{ + backtrack=true;//todo eude this is the source of bad performance - try to get rid of it + output=AST; +} + +tokens { + T_SELECTED_ITEMS; + T_SELECTED_ITEM; + T_SOURCES; + T_SOURCE; + T_SELECTED_FIELD; + T_SELECTED_ENTITY; + T_ID_VAR; + T_JOIN_VAR; + T_COLLECTION_MEMBER; + T_QUERY; + T_CONDITION; + T_SIMPLE_CONDITION; + T_PARAMETER; + T_GROUP_BY; + T_ORDER_BY; + T_ORDER_BY_FIELD; + T_AGGREGATE_EXPR; + T_ENUM_MACROS; + HAVING = 'HAVING'; + ASC = 'ASC'; + DESC = 'DESC'; + AVG = 'AVG'; + MAX = 'MAX'; + MIN = 'MIN'; + SUM = 'SUM'; + COUNT = 'COUNT'; + LOWER = 'LOWER'; + OR = 'OR'; + AND = 'AND'; + LPAREN = '('; + RPAREN = ')'; + DISTINCT = 'DISTINCT'; + LEFT = 'LEFT'; + OUTER = 'OUTER'; + INNER = 'INNER'; + JOIN = 'JOIN'; + FETCH = 'FETCH'; + ORDER = 'ORDER'; + GROUP = 'GROUP'; + BY = 'BY'; + SET = 'SET'; + AS = 'AS'; +} + + +@header { +package com.haulmont.cuba.core.sys.jpql.antlr2; + +import com.haulmont.cuba.core.sys.jpql.tree.QueryNode; +import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import com.haulmont.cuba.core.sys.jpql.tree.FromNode; +import com.haulmont.cuba.core.sys.jpql.tree.SelectionSourceNode; +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.CollectionMemberNode; +import com.haulmont.cuba.core.sys.jpql.tree.WhereNode; +import com.haulmont.cuba.core.sys.jpql.tree.SimpleConditionNode; +import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; +import com.haulmont.cuba.core.sys.jpql.tree.GroupByNode; +import com.haulmont.cuba.core.sys.jpql.tree.OrderByNode; +import com.haulmont.cuba.core.sys.jpql.tree.OrderByFieldNode; +import com.haulmont.cuba.core.sys.jpql.tree.AggregateExpressionNode; +import com.haulmont.cuba.core.sys.jpql.tree.SelectedItemsNode; +import com.haulmont.cuba.core.sys.jpql.tree.UpdateSetNode; +import com.haulmont.cuba.core.sys.jpql.tree.EnumConditionNode; +} + +@lexer::header { +package com.haulmont.cuba.core.sys.jpql.antlr2; + +} + +ql_statement + : select_statement | update_statement | delete_statement; + +select_statement + : sl='SELECT' select_clause from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)? + -> ^(T_QUERY[$sl] (select_clause)? from_clause (where_clause)? (groupby_clause)? (having_clause)? (orderby_clause)?); + +update_statement + : up='UPDATE' update_clause (where_clause)? + -> ^(T_QUERY[$up] update_clause (where_clause)?); +delete_statement + : dl='DELETE' delete_clause (where_clause)? + -> ^(T_QUERY[$dl] delete_clause (where_clause)?); + +from_clause + : fr='FROM' identification_variable_declaration (',' identification_variable_declaration_or_collection_member_declaration)* + -> ^(T_SOURCES[$fr] identification_variable_declaration identification_variable_declaration_or_collection_member_declaration*); +identification_variable_declaration_or_collection_member_declaration + : identification_variable_declaration + | collection_member_declaration -> ^(T_SOURCE collection_member_declaration); + +identification_variable_declaration + : range_variable_declaration joined_clause* + -> ^(T_SOURCE range_variable_declaration joined_clause*); +join_section : + joined_clause*; +joined_clause : join | fetch_join; +range_variable_declaration + : entity_name (AS)? identification_variable + -> ^(T_ID_VAR[$identification_variable.text] entity_name); +join + : join_spec join_association_path_expression (AS)? identification_variable ('ON' conditional_expression)? + -> ^(T_JOIN_VAR[$join_spec.text, $identification_variable.text] join_association_path_expression conditional_expression?); +fetch_join + : join_spec 'FETCH' join_association_path_expression; +join_spec + : (('LEFT') ('OUTER')? | 'INNER' )? 'JOIN'; + +//Start : here we have simplified joins +join_association_path_expression + : identification_variable '.' (field'.')* field? + -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) + | 'TREAT(' identification_variable '.' (field'.')* field? AS subtype ')' + -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) + | entity_name; +//End : here we have simplified joins + +collection_member_declaration + : 'IN''(' path_expression ')' (AS)? identification_variable + -> ^(T_COLLECTION_MEMBER[$identification_variable.text] path_expression ); + +qualified_identification_variable + : map_field_identification_variable + | 'ENTRY('identification_variable')'; +map_field_identification_variable : 'KEY('identification_variable')' | 'VALUE('identification_variable')'; + +//Start : here we have simplified paths +path_expression + : identification_variable '.' (field'.')* field? + -> ^(T_SELECTED_FIELD[$identification_variable.text] (field)*) + ; +//todo eude treated path +//End : here we have simplified paths + +general_identification_variable + : identification_variable + | map_field_identification_variable; + +//todo eude implement separate node instead of SelectionSourceNode for update and delete? +update_clause + : identification_variable_declaration SET update_item (',' update_item)* + -> ^(T_SOURCES identification_variable_declaration SET update_item (',' update_item)*); +update_item + : path_expression '=' new_value; +new_value + : scalar_expression + | simple_entity_expression + | 'NULL'; + +delete_clause + : fr='FROM' identification_variable_declaration + -> ^(T_SOURCES[$fr] identification_variable_declaration); +select_clause + : ('DISTINCT')? select_item (',' select_item)* + -> ^(T_SELECTED_ITEMS[] ('DISTINCT')? ^(T_SELECTED_ITEM[] select_item)*); +select_item + : select_expression ((AS)? result_variable)?; +select_expression + : path_expression (('+' | '-' | '*' | '/') scalar_expression)? + | identification_variable -> ^(T_SELECTED_ENTITY[$identification_variable.text]) + | scalar_expression + | aggregate_expression + | 'OBJECT' '('identification_variable')' + | constructor_expression; +constructor_expression + : 'NEW' constructor_name '(' constructor_item (',' constructor_item)* ')'; +constructor_item + : path_expression + | scalar_expression + | aggregate_expression + | identification_variable; +aggregate_expression + : aggregate_expression_function_name '('(DISTINCT)? arithmetic_expression')' + -> ^(T_AGGREGATE_EXPR[] aggregate_expression_function_name '(' ('DISTINCT')? arithmetic_expression')') + | 'COUNT' '('(DISTINCT)? count_argument ')' + -> ^(T_AGGREGATE_EXPR[] 'COUNT' '(' ('DISTINCT')? count_argument ')') + | function_invocation; +aggregate_expression_function_name + : 'AVG' | 'MAX' | 'MIN' |'SUM' | 'COUNT'; +count_argument + : identification_variable | path_expression; +where_clause + : wh='WHERE' conditional_expression-> ^(T_CONDITION[$wh] conditional_expression); +groupby_clause + : 'GROUP' 'BY' groupby_item (',' groupby_item)* + -> ^(T_GROUP_BY[] 'GROUP' 'BY' groupby_item*); +groupby_item + : path_expression | identification_variable | extract_function; +having_clause + : 'HAVING' conditional_expression; +orderby_clause + : 'ORDER' 'BY' orderby_item (',' orderby_item)* + -> ^(T_ORDER_BY[] 'ORDER' 'BY' orderby_item*); +orderby_item + : orderby_variable sort? sortNulls? + -> ^(T_ORDER_BY_FIELD[] orderby_variable sort? sortNulls?); +orderby_variable + : path_expression | general_identification_variable | result_variable | scalar_expression | aggregate_expression; +sort + : ('ASC' | 'DESC'); +sortNulls + : ('NULLS FIRST' | 'NULLS LAST'); +subquery + : lp='(' 'SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? rp=')' + -> ^(T_QUERY[$lp,$rp] 'SELECT' simple_select_clause subquery_from_clause (where_clause)? (groupby_clause)? (having_clause)? ); +subquery_from_clause + : fr='FROM' subselect_identification_variable_declaration (',' subselect_identification_variable_declaration)* + -> ^(T_SOURCES[$fr] ^(T_SOURCE subselect_identification_variable_declaration)*); + +subselect_identification_variable_declaration + : identification_variable_declaration + | derived_path_expression AS identification_variable (join)* + | derived_collection_member_declaration; +derived_path_expression + : general_derived_path'.'single_valued_object_field + | general_derived_path'.'collection_valued_field; +general_derived_path + : simple_derived_path + | treated_derived_path('.'single_valued_object_field)* + ; +simple_derived_path + : superquery_identification_variable //todo eude ('.' single_valued_object_field)* + ; +treated_derived_path + : 'TREAT('general_derived_path AS subtype ')'; +derived_collection_member_declaration + : 'IN' superquery_identification_variable'.'(single_valued_object_field '.')*collection_valued_field; + +simple_select_clause + : ('DISTINCT')? simple_select_expression + -> ^(T_SELECTED_ITEMS[] ^(T_SELECTED_ITEM[] ('DISTINCT')? simple_select_expression)); +simple_select_expression + : path_expression + | scalar_expression + | aggregate_expression + | identification_variable; +scalar_expression + : arithmetic_expression + | string_expression + | enum_expression + | datetime_expression + | boolean_expression + | case_expression + | entity_type_expression; +conditional_expression + : (conditional_term) ('OR' conditional_term)*; +conditional_term + : (conditional_factor) ('AND' conditional_factor)*; +conditional_factor + : ('NOT')? conditional_primary; +conditional_primary + : simple_cond_expression + -> ^(T_SIMPLE_CONDITION[] simple_cond_expression) + | '('conditional_expression')'; +simple_cond_expression + : comparison_expression + | between_expression + | in_expression + | like_expression + | null_comparison_expression + | empty_collection_comparison_expression + | collection_member_expression + | exists_expression + | date_macro_expression; + +//Start: Here we insert our custom macroses +date_macro_expression + : date_between_macro_expression + | date_before_macro_expression + | date_after_macro_expression + | date_equals_macro_expression + | date_today_macro_expression; + +date_between_macro_expression + : '@BETWEEN' '(' path_expression ',' 'NOW' (('+' | '-') numeric_literal)? ',' 'NOW' (('+' | '-') numeric_literal)? ',' ('YEAR' | 'MONTH' | 'DAY' | 'HOUR' |'MINUTE' | 'SECOND') ')'; + +date_before_macro_expression + : '@DATEBEFORE' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_after_macro_expression + : '@DATEAFTER' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_equals_macro_expression + : '@DATEEQUALS' '(' path_expression ',' (path_expression | input_parameter) ')'; + +date_today_macro_expression + : '@TODAY' '(' path_expression ')'; +//End: Here we insert our custom macroses + +between_expression + : arithmetic_expression ('NOT')? 'BETWEEN' arithmetic_expression 'AND' arithmetic_expression + | string_expression ('NOT')? 'BETWEEN' string_expression 'AND' string_expression + | datetime_expression ('NOT')? 'BETWEEN' datetime_expression 'AND' datetime_expression; +in_expression + : (path_expression | type_discriminator | identification_variable) (NOT)? IN + ( '(' in_item (',' in_item)* ')' + | subquery + | collection_valued_input_parameter + | '(' path_expression ')' ); + +NOT: 'NOT'; + +IN: 'IN'; + +in_item + : string_literal | numeric_literal | single_valued_input_parameter | enum_function; +like_expression + : string_expression ('NOT')? 'LIKE' (string_expression | pattern_value | input_parameter)('ESCAPE' escape_character)?; +null_comparison_expression + : (path_expression | input_parameter | join_association_path_expression) 'IS' ('NOT')? 'NULL'; +empty_collection_comparison_expression + : path_expression 'IS' ('NOT')? 'EMPTY'; +collection_member_expression + : entity_or_value_expression ('NOT')? 'MEMBER' ('OF')? path_expression; +entity_or_value_expression + : path_expression + | simple_entity_or_value_expression + | subquery; +simple_entity_or_value_expression + : identification_variable + | input_parameter + | literal; +exists_expression + : ('NOT')? 'EXISTS' subquery; +all_or_any_expression + : ( 'ALL' | 'ANY' | 'SOME') subquery; +comparison_expression + : string_expression (comparison_operator | 'REGEXP') (string_expression | all_or_any_expression) + | boolean_expression ('=' | '<>') (boolean_expression | all_or_any_expression) + | enum_expression ('='|'<>') (enum_expression | all_or_any_expression) + | datetime_expression comparison_operator (datetime_expression | all_or_any_expression) + | entity_expression ('=' | '<>') (entity_expression | all_or_any_expression) + | entity_type_expression ('=' | '<>') entity_type_expression + | arithmetic_expression comparison_operator (arithmetic_expression | all_or_any_expression); + +comparison_operator + : '=' + | '>' + | '>=' + | '<' + | '<=' + | '<>'; +arithmetic_expression + : arithmetic_term ('+' | '-') arithmetic_term + | arithmetic_term; +arithmetic_term + : arithmetic_factor ( '*' | '/') arithmetic_factor + | arithmetic_factor; +arithmetic_factor + : (( '+' | '-'))? arithmetic_primary; +arithmetic_primary + : path_expression + | numeric_literal + | '('arithmetic_expression')' + | input_parameter + | functions_returning_numerics + | aggregate_expression + | case_expression + | function_invocation + | extension_functions + | subquery; +string_expression + : path_expression + | string_literal + | input_parameter + | functions_returning_strings + | aggregate_expression + | case_expression + | function_invocation + | extension_functions + | subquery; +datetime_expression + : path_expression + | input_parameter + | functions_returning_datetime + | aggregate_expression + | case_expression + | function_invocation + | extension_functions + | date_time_timestamp_literal + | subquery; +boolean_expression + : path_expression + | boolean_literal + | input_parameter + | case_expression + | function_invocation + | extension_functions + | subquery; +enum_expression + : path_expression + | enum_literal + | input_parameter + | case_expression + | subquery; +entity_expression + : path_expression + | simple_entity_expression; +simple_entity_expression + : identification_variable + | input_parameter; +entity_type_expression + : type_discriminator + | entity_type_literal + | input_parameter; +type_discriminator + : 'TYPE(' (general_identification_variable | path_expression | input_parameter) ')'; +functions_returning_numerics + : 'LENGTH('string_expression')' + | 'LOCATE(' string_expression',' string_expression(','arithmetic_expression)?')' + | 'ABS('arithmetic_expression')' + | 'SQRT('arithmetic_expression')' + | 'MOD('arithmetic_expression',' arithmetic_expression')' + | 'SIZE('path_expression')' + | 'INDEX('identification_variable')'; +functions_returning_datetime + : 'CURRENT_DATE' + | 'CURRENT_TIME' + | 'CURRENT_TIMESTAMP'; +functions_returning_strings + : 'CONCAT('string_expression',' string_expression (',' string_expression)*')' + | 'SUBSTRING(' string_expression',' arithmetic_expression (',' arithmetic_expression)?')' + | 'TRIM('((trim_specification)? (trim_character)? 'FROM')? string_expression ')' + | 'LOWER' '('string_expression')' + | 'UPPER('string_expression')'; +trim_specification + : 'LEADING' | 'TRAILING' | 'BOTH'; +function_invocation + : 'FUNCTION('function_name (',' function_arg)* ')'; +function_arg + : literal + | path_expression + | input_parameter + | scalar_expression; +case_expression + : general_case_expression + | simple_case_expression + | coalesce_expression + | nullif_expression; +general_case_expression + : 'CASE' when_clause (when_clause)* 'ELSE' scalar_expression 'END'; +when_clause + : 'WHEN' conditional_expression 'THEN' scalar_expression; +simple_case_expression + : 'CASE' case_operand simple_when_clause (simple_when_clause)* 'ELSE' scalar_expression 'END'; +case_operand + : path_expression + | type_discriminator; +simple_when_clause + : 'WHEN' scalar_expression 'THEN' scalar_expression; +coalesce_expression + : 'COALESCE('scalar_expression (',' scalar_expression)+')'; +nullif_expression + : 'NULLIF('scalar_expression ',' scalar_expression')'; + +extension_functions + : 'CAST(' function_arg WORD ('('INT_NUMERAL (',' INT_NUMERAL)* ')')* ')' + | extract_function + | enum_function; + +extract_function + : 'EXTRACT(' date_part 'FROM' function_arg ')'; + +enum_function + : '@ENUM' '(' enum_value_literal ')' -> ^(T_ENUM_MACROS[$enum_value_literal.text]); + +fragment date_part + : 'EPOCH' | 'YEAR' | 'QUARTER' | 'MONTH' | 'WEEK' |'DAY' | 'HOUR' |'MINUTE' | 'SECOND'; + +//Start : Here we insert tail from old grammar +input_parameter + : '?' numeric_literal -> ^(T_PARAMETER[] '?' numeric_literal ) + | NAMED_PARAMETER -> ^(T_PARAMETER[] NAMED_PARAMETER ) + | '${' WORD '}' -> ^(T_PARAMETER[] '${' WORD '}'); + +literal + : WORD; + +constructor_name + : WORD; + +enum_literal + : WORD; + +boolean_literal + : 'true' + | 'false'; + +//todo eude the following is just a workaround for entity fields equal to keywords. We need to get rid of it somehow. +field + : WORD | 'SELECT' | 'FROM' | 'GROUP' | 'ORDER' | 'MAX' | 'MIN' | 'SUM' | 'AVG' | 'COUNT' | 'AS' | 'MEMBER' | date_part; + +identification_variable + : WORD | 'GROUP'; + +parameter_name + : WORD ('.' WORD)*; + +//todo eude ESCAPE_CHARACTER should be here instead of STRING_LITERAL, but it does not work for some reason, so workarounded with STRING_LITERAL +escape_character + : '\'.\'' | STRING_LITERAL; +trim_character + : TRIM_CHARACTER; +string_literal + : STRING_LITERAL; +numeric_literal + : ('0x')? INT_NUMERAL ; +single_valued_object_field + : WORD; +single_valued_embeddable_object_field + : WORD; +collection_valued_field + : WORD; +entity_name + : WORD; +subtype + : WORD; +entity_type_literal + : WORD; +function_name + : STRING_LITERAL; +state_field + : WORD; +result_variable + : WORD; +superquery_identification_variable + : WORD; +date_time_timestamp_literal + : WORD; +pattern_value + : string_literal; +collection_valued_input_parameter + : input_parameter; +single_valued_input_parameter + : input_parameter; +enum_value_literal + : WORD ('.' WORD)*; + +// Lexical Rules +//fix trim character +TRIM_CHARACTER + : '\'.\''; + +STRING_LITERAL + : '\'' (~('\'' | '"') )* '\'' ; + +WORD + : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')*; + +RUSSIAN_SYMBOLS + : ('\u0400'..'\u04FF'|'\u0500'..'\u052F' ) {if ( 1 == 1) throw new IllegalArgumentException("Incorrect symbol");}; + +NAMED_PARAMETER + : ':' ('(?i)'|'(?I)')? ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')* (('.') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'$')+)*; + +WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} + ; + +COMMENT + : '/*' .* '*/' {$channel=HIDDEN;}; + +LINE_COMMENT + : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}; + +ESCAPE_CHARACTER + : '\'' (~('\''|'\\') ) '\''; + +INT_NUMERAL + : ('0'..'9')+; +//End : Here we insert tail from old grammar + + diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/jpql21.bnf b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/jpql21.bnf index 4c3841e80d..4298c9943c 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/jpql21.bnf +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/antlr2/jpql21.bnf @@ -1,273 +1,273 @@ -QL_statement ::= select_statement | update_statement | delete_statement -select_statement ::= select_clause from_clause [where_clause] [groupby_clause] -[having_clause] [orderby_clause] -update_statement ::= update_clause [where_clause] -delete_statement ::= delete_clause [where_clause] -from_clause ::= -FROM identification_variable_declaration -{, {identification_variable_declaration | collection_member_declaration}}* -identification_variable_declaration ::= range_variable_declaration { join | fetch_join }* -range_variable_declaration ::= entity_name [AS] identification_variable -join ::= join_spec join_association_path_expression [AS] identification_variable -[join_condition] -fetch_join ::= join_spec FETCH join_association_path_expression -join_spec::= [ LEFT [OUTER] | INNER ] JOIN -join_condition ::= ON conditional_expression -join_association_path_expression ::= -join_collection_valued_path_expression | -join_single_valued_path_expression | -TREAT(join_collection_valued_path_expression AS subtype) | -TREAT(join_single_valued_path_expression AS subtype) -join_collection_valued_path_expression::= -identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field -join_single_valued_path_expression::= -identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field -collection_member_declaration ::= -IN (collection_valued_path_expression) [AS] identification_variable -qualified_identification_variable :: = -map_field_identification_variable | -ENTRY(identification_variable) -map_field_identification_variable :: = -KEY(identification_variable) | -VALUE(identification_variable) -single_valued_path_expression ::= -qualified_identification_variable | -TREAT(qualified_identification_variable AS subtype) | -state_field_path_expression | -single_valued_object_path_expression -general_identification_variable ::= -identification_variable | -map_field_identification_variable -general_subpath ::= simple_subpath | treated_subpath{.single_valued_object_field}* -simple_subpath ::= -general_identification_variable | -general_identification_variable{.single_valued_object_field}* -treated_subpath ::= TREAT(general_subpath AS subtype) -state_field_path_expression ::= general_subpath.state_field -state_valued_path_expression ::= -state_field_path_expression | general_identification_variable -single_valued_object_path_expression ::= general_subpath.single_valued_object_field -collection_valued_path_expression ::= general_subpath.{collection_valued_field -update_clause ::= UPDATE entity_name [[AS] identification_variable] -SET update_item {, update_item}* -update_item ::= [identification_variable.]{single_valued_embeddable_object_field.}* -{state_field | single_valued_object_field} = new_value -new_value ::= -scalar_expression | -simple_entity_expression | -NULL -delete_clause ::= DELETE FROM entity_name [[AS] identification_variable] -select_clause ::= SELECT [DISTINCT] select_item {, select_item}* -select_item ::= select_expression [[AS] result_variable] -select_expression ::= -single_valued_path_expression | -scalar_expression | -aggregate_expression | -identification_variable | -OBJECT(identification_variable) | -constructor_expression -constructor_expression ::= -NEW constructor_name ( constructor_item {, constructor_item}* ) -constructor_item ::= -single_valued_path_expression | -scalar_expression | -aggregate_expression | -identification_variable -aggregate_expression ::= -{ AVG | MAX | MIN | SUM } ([DISTINCT] state_valued_path_expression) | -COUNT ([DISTINCT] identification_variable | state_valued_path_expression | -single_valued_object_path_expression) | -function_invocation -where_clause ::= WHERE conditional_expression -groupby_clause ::= GROUP BY groupby_item {, groupby_item}* -groupby_item ::= single_valued_path_expression | identification_variable -having_clause ::= HAVING conditional_expression -orderby_clause ::= ORDER BY orderby_item {, orderby_item}* -orderby_item ::= -state_field_path_expression | general_identification_variable | result_variable -[ ASC | DESC ] -subquery ::= simple_select_clause subquery_from_clause [where_clause] -[groupby_clause] [having_clause] -subquery_from_clause ::= -FROM subselect_identification_variable_declaration -{, subselect_identification_variable_declaration | - collection_member_declaration}* -subselect_identification_variable_declaration ::= -identification_variable_declaration | -derived_path_expression [AS] identification_variable {join}*| -derived_collection_member_declaration -derived_path_expression ::= -general_derived_path.single_valued_object_field | -general_derived_path.collection_valued_field -general_derived_path ::= -simple_derived_path | -treated_derived_path{.single_valued_object_field}* -simple_derived_path ::= superquery_identification_variable{.single_valued_object_field}* -treated_derived_path ::= TREAT(general_derived_path AS subtype) -derived_collection_member_declaration ::= -IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field -simple_select_clause ::= SELECT [DISTINCT] simple_select_expression -simple_select_expression::= -single_valued_path_expression | -scalar_expression | -aggregate_expression | -identification_variable -scalar_expression ::= -arithmetic_expression | -string_expression | -enum_expression | -datetime_expression | -boolean_expression | -case_expression | -entity_type_expression -conditional_expression ::= conditional_term | conditional_expression OR conditional_term -conditional_term ::= conditional_factor | conditional_term AND conditional_factor -conditional_factor ::= [ NOT ] conditional_primary -conditional_primary ::= simple_cond_expression | (conditional_expression) -simple_cond_expression ::= -comparison_expression | -between_expression | -in_expression | -like_expression | -null_comparison_expression | -empty_collection_comparison_expression | -collection_member_expression | -exists_expression -between_expression ::= -arithmetic_expression [NOT] BETWEEN -arithmetic_expression AND arithmetic_expression | -string_expression [NOT] BETWEEN string_expression AND string_expression | -datetime_expression [NOT] BETWEEN -datetime_expression AND datetime_expression -in_expression ::= -{state_valued_path_expression | type_discriminator} [NOT] IN -{ ( in_item {, in_item}* ) | (subquery) | collection_valued_input_parameter } -in_item ::= literal | single_valued_input_parameter -like_expression ::= -string_expression [NOT] LIKE pattern_value [ESCAPE escape_character] -null_comparison_expression ::= -{single_valued_path_expression | input_parameter} IS [NOT] NULL -empty_collection_comparison_expression ::= -collection_valued_path_expression IS [NOT] EMPTY -collection_member_expression ::= entity_or_value_expression -[NOT] MEMBER [OF] collection_valued_path_expression -entity_or_value_expression ::= -single_valued_object_path_expression | -state_field_path_expression | -simple_entity_or_value_expression -simple_entity_or_value_expression ::= -identification_variable | -input_parameter | -literal -exists_expression::= [NOT] EXISTS (subquery) -all_or_any_expression ::= { ALL | ANY | SOME} (subquery) -comparison_expression ::= -string_expression comparison_operator {string_expression | all_or_any_expression} | -boolean_expression { =|<>} {boolean_expression | all_or_any_expression} | -enum_expression { =|<>} {enum_expression | all_or_any_expression} | -datetime_expression comparison_operator -{datetime_expression | all_or_any_expression} | -entity_expression { = | <>} {entity_expression | all_or_any_expression} | -arithmetic_expression comparison_operator -{arithmetic_expression | all_or_any_expression} | -entity_type_expression { =|<>} entity_type_expression} -comparison_operator ::= = | > | >= | < | <= | <> -arithmetic_expression ::= -arithmetic_term | arithmetic_expression { + | - } arithmetic_term -arithmetic_term ::= arithmetic_factor | arithmetic_term { * | / } arithmetic_factor -arithmetic_factor ::= [{ + | - }] arithmetic_primary -arithmetic_primary ::= -state_valued_path_expression | -numeric_literal | -(arithmetic_expression) | -input_parameter | -functions_returning_numerics | -aggregate_expression | -case_expression | -function_invocation | -(subquery) -string_expression ::= -state_valued_path_expression | -string_literal | -input_parameter | -functions_returning_strings | -aggregate_expression | -case_expression | -function_invocation | -(subquery) -datetime_expression ::= -state_valued_path_expression | -input_parameter | -functions_returning_datetime | -aggregate_expression | -case_expression | -function_invocation | -date_time_timestamp_literal | -(subquery) -boolean_expression ::= -state_valued_path_expression | -boolean_literal | -input_parameter | -case_expression | -function_invocation | -(subquery) -enum_expression ::= -state_valued_path_expression | -enum_literal | -input_parameter | -case_expression | -(subquery) -entity_expression ::= -single_valued_object_path_expression | simple_entity_expression -simple_entity_expression ::= -identification_variable | -input_parameter -entity_type_expression ::= -type_discriminator | -entity_type_literal | -input_parameter -type_discriminator ::= -TYPE(general_identification_variable | -single_valued_object_path_expression | -input_parameter) -functions_returning_numerics::= -LENGTH(string_expression) | -LOCATE(string_expression, string_expression[, arithmetic_expression]) | -ABS(arithmetic_expression) | -SQRT(arithmetic_expression) | -MOD(arithmetic_expression, arithmetic_expression) | -SIZE(collection_valued_path_expression) | -INDEX(identification_variable) -functions_returning_datetime ::= -CURRENT_DATE | -CURRENT_TIME | -CURRENT_TIMESTAMP -functions_returning_strings ::= -CONCAT(string_expression, string_expression {, string_expression}*) | -SUBSTRING(string_expression, arithmetic_expression [, arithmetic_expression]) | -TRIM([[trim_specification] [trim_character] FROM] string_expression) | -LOWER(string_expression) | -UPPER(string_expression) -trim_specification ::= LEADING | TRAILING | BOTH -function_invocation::= FUNCTION(function_name {, function_arg}*) -function_arg ::= -literal | -state_valued_path_expression | -input_parameter | -scalar_expression -case_expression ::= -general_case_expression | -simple_case_expression | -coalesce_expression | -nullif_expression -general_case_expression::= -CASE when_clause {when_clause}* ELSE scalar_expression END -when_clause::= WHEN conditional_expression THEN scalar_expression -simple_case_expression::= -CASE case_operand simple_when_clause {simple_when_clause}* -ELSE scalar_expression -END -case_operand::= state_valued_path_expression | type_discriminator -simple_when_clause::= WHEN scalar_expression THEN scalar_expression -coalesce_expression::= COALESCE(scalar_expression {, scalar_expression}+) +QL_statement ::= select_statement | update_statement | delete_statement +select_statement ::= select_clause from_clause [where_clause] [groupby_clause] +[having_clause] [orderby_clause] +update_statement ::= update_clause [where_clause] +delete_statement ::= delete_clause [where_clause] +from_clause ::= +FROM identification_variable_declaration +{, {identification_variable_declaration | collection_member_declaration}}* +identification_variable_declaration ::= range_variable_declaration { join | fetch_join }* +range_variable_declaration ::= entity_name [AS] identification_variable +join ::= join_spec join_association_path_expression [AS] identification_variable +[join_condition] +fetch_join ::= join_spec FETCH join_association_path_expression +join_spec::= [ LEFT [OUTER] | INNER ] JOIN +join_condition ::= ON conditional_expression +join_association_path_expression ::= +join_collection_valued_path_expression | +join_single_valued_path_expression | +TREAT(join_collection_valued_path_expression AS subtype) | +TREAT(join_single_valued_path_expression AS subtype) +join_collection_valued_path_expression::= +identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field +join_single_valued_path_expression::= +identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field +collection_member_declaration ::= +IN (collection_valued_path_expression) [AS] identification_variable +qualified_identification_variable :: = +map_field_identification_variable | +ENTRY(identification_variable) +map_field_identification_variable :: = +KEY(identification_variable) | +VALUE(identification_variable) +single_valued_path_expression ::= +qualified_identification_variable | +TREAT(qualified_identification_variable AS subtype) | +state_field_path_expression | +single_valued_object_path_expression +general_identification_variable ::= +identification_variable | +map_field_identification_variable +general_subpath ::= simple_subpath | treated_subpath{.single_valued_object_field}* +simple_subpath ::= +general_identification_variable | +general_identification_variable{.single_valued_object_field}* +treated_subpath ::= TREAT(general_subpath AS subtype) +state_field_path_expression ::= general_subpath.state_field +state_valued_path_expression ::= +state_field_path_expression | general_identification_variable +single_valued_object_path_expression ::= general_subpath.single_valued_object_field +collection_valued_path_expression ::= general_subpath.{collection_valued_field +update_clause ::= UPDATE entity_name [[AS] identification_variable] +SET update_item {, update_item}* +update_item ::= [identification_variable.]{single_valued_embeddable_object_field.}* +{state_field | single_valued_object_field} = new_value +new_value ::= +scalar_expression | +simple_entity_expression | +NULL +delete_clause ::= DELETE FROM entity_name [[AS] identification_variable] +select_clause ::= SELECT [DISTINCT] select_item {, select_item}* +select_item ::= select_expression [[AS] result_variable] +select_expression ::= +single_valued_path_expression | +scalar_expression | +aggregate_expression | +identification_variable | +OBJECT(identification_variable) | +constructor_expression +constructor_expression ::= +NEW constructor_name ( constructor_item {, constructor_item}* ) +constructor_item ::= +single_valued_path_expression | +scalar_expression | +aggregate_expression | +identification_variable +aggregate_expression ::= +{ AVG | MAX | MIN | SUM } ([DISTINCT] state_valued_path_expression) | +COUNT ([DISTINCT] identification_variable | state_valued_path_expression | +single_valued_object_path_expression) | +function_invocation +where_clause ::= WHERE conditional_expression +groupby_clause ::= GROUP BY groupby_item {, groupby_item}* +groupby_item ::= single_valued_path_expression | identification_variable +having_clause ::= HAVING conditional_expression +orderby_clause ::= ORDER BY orderby_item {, orderby_item}* +orderby_item ::= +state_field_path_expression | general_identification_variable | result_variable +[ ASC | DESC ] +subquery ::= simple_select_clause subquery_from_clause [where_clause] +[groupby_clause] [having_clause] +subquery_from_clause ::= +FROM subselect_identification_variable_declaration +{, subselect_identification_variable_declaration | + collection_member_declaration}* +subselect_identification_variable_declaration ::= +identification_variable_declaration | +derived_path_expression [AS] identification_variable {join}*| +derived_collection_member_declaration +derived_path_expression ::= +general_derived_path.single_valued_object_field | +general_derived_path.collection_valued_field +general_derived_path ::= +simple_derived_path | +treated_derived_path{.single_valued_object_field}* +simple_derived_path ::= superquery_identification_variable{.single_valued_object_field}* +treated_derived_path ::= TREAT(general_derived_path AS subtype) +derived_collection_member_declaration ::= +IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field +simple_select_clause ::= SELECT [DISTINCT] simple_select_expression +simple_select_expression::= +single_valued_path_expression | +scalar_expression | +aggregate_expression | +identification_variable +scalar_expression ::= +arithmetic_expression | +string_expression | +enum_expression | +datetime_expression | +boolean_expression | +case_expression | +entity_type_expression +conditional_expression ::= conditional_term | conditional_expression OR conditional_term +conditional_term ::= conditional_factor | conditional_term AND conditional_factor +conditional_factor ::= [ NOT ] conditional_primary +conditional_primary ::= simple_cond_expression | (conditional_expression) +simple_cond_expression ::= +comparison_expression | +between_expression | +in_expression | +like_expression | +null_comparison_expression | +empty_collection_comparison_expression | +collection_member_expression | +exists_expression +between_expression ::= +arithmetic_expression [NOT] BETWEEN +arithmetic_expression AND arithmetic_expression | +string_expression [NOT] BETWEEN string_expression AND string_expression | +datetime_expression [NOT] BETWEEN +datetime_expression AND datetime_expression +in_expression ::= +{state_valued_path_expression | type_discriminator} [NOT] IN +{ ( in_item {, in_item}* ) | (subquery) | collection_valued_input_parameter } +in_item ::= literal | single_valued_input_parameter +like_expression ::= +string_expression [NOT] LIKE pattern_value [ESCAPE escape_character] +null_comparison_expression ::= +{single_valued_path_expression | input_parameter} IS [NOT] NULL +empty_collection_comparison_expression ::= +collection_valued_path_expression IS [NOT] EMPTY +collection_member_expression ::= entity_or_value_expression +[NOT] MEMBER [OF] collection_valued_path_expression +entity_or_value_expression ::= +single_valued_object_path_expression | +state_field_path_expression | +simple_entity_or_value_expression +simple_entity_or_value_expression ::= +identification_variable | +input_parameter | +literal +exists_expression::= [NOT] EXISTS (subquery) +all_or_any_expression ::= { ALL | ANY | SOME} (subquery) +comparison_expression ::= +string_expression comparison_operator {string_expression | all_or_any_expression} | +boolean_expression { =|<>} {boolean_expression | all_or_any_expression} | +enum_expression { =|<>} {enum_expression | all_or_any_expression} | +datetime_expression comparison_operator +{datetime_expression | all_or_any_expression} | +entity_expression { = | <>} {entity_expression | all_or_any_expression} | +arithmetic_expression comparison_operator +{arithmetic_expression | all_or_any_expression} | +entity_type_expression { =|<>} entity_type_expression} +comparison_operator ::= = | > | >= | < | <= | <> +arithmetic_expression ::= +arithmetic_term | arithmetic_expression { + | - } arithmetic_term +arithmetic_term ::= arithmetic_factor | arithmetic_term { * | / } arithmetic_factor +arithmetic_factor ::= [{ + | - }] arithmetic_primary +arithmetic_primary ::= +state_valued_path_expression | +numeric_literal | +(arithmetic_expression) | +input_parameter | +functions_returning_numerics | +aggregate_expression | +case_expression | +function_invocation | +(subquery) +string_expression ::= +state_valued_path_expression | +string_literal | +input_parameter | +functions_returning_strings | +aggregate_expression | +case_expression | +function_invocation | +(subquery) +datetime_expression ::= +state_valued_path_expression | +input_parameter | +functions_returning_datetime | +aggregate_expression | +case_expression | +function_invocation | +date_time_timestamp_literal | +(subquery) +boolean_expression ::= +state_valued_path_expression | +boolean_literal | +input_parameter | +case_expression | +function_invocation | +(subquery) +enum_expression ::= +state_valued_path_expression | +enum_literal | +input_parameter | +case_expression | +(subquery) +entity_expression ::= +single_valued_object_path_expression | simple_entity_expression +simple_entity_expression ::= +identification_variable | +input_parameter +entity_type_expression ::= +type_discriminator | +entity_type_literal | +input_parameter +type_discriminator ::= +TYPE(general_identification_variable | +single_valued_object_path_expression | +input_parameter) +functions_returning_numerics::= +LENGTH(string_expression) | +LOCATE(string_expression, string_expression[, arithmetic_expression]) | +ABS(arithmetic_expression) | +SQRT(arithmetic_expression) | +MOD(arithmetic_expression, arithmetic_expression) | +SIZE(collection_valued_path_expression) | +INDEX(identification_variable) +functions_returning_datetime ::= +CURRENT_DATE | +CURRENT_TIME | +CURRENT_TIMESTAMP +functions_returning_strings ::= +CONCAT(string_expression, string_expression {, string_expression}*) | +SUBSTRING(string_expression, arithmetic_expression [, arithmetic_expression]) | +TRIM([[trim_specification] [trim_character] FROM] string_expression) | +LOWER(string_expression) | +UPPER(string_expression) +trim_specification ::= LEADING | TRAILING | BOTH +function_invocation::= FUNCTION(function_name {, function_arg}*) +function_arg ::= +literal | +state_valued_path_expression | +input_parameter | +scalar_expression +case_expression ::= +general_case_expression | +simple_case_expression | +coalesce_expression | +nullif_expression +general_case_expression::= +CASE when_clause {when_clause}* ELSE scalar_expression END +when_clause::= WHEN conditional_expression THEN scalar_expression +simple_case_expression::= +CASE case_operand simple_when_clause {simple_when_clause}* +ELSE scalar_expression +END +case_operand::= state_valued_path_expression | type_discriminator +simple_when_clause::= WHEN scalar_expression THEN scalar_expression +coalesce_expression::= COALESCE(scalar_expression {, scalar_expression}+) nullif_expression::= NULLIF(scalar_expression, scalar_expression) \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/Attribute.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/Attribute.java index 704e098e74..34966720a1 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/Attribute.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/Attribute.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.model; - -public interface Attribute extends Cloneable { - Class getSimpleType(); - - String getName(); - - boolean isEntityReferenceAttribute(); - - boolean isCollection(); - - String getReferencedEntityName(); - - String getUserFriendlyName(); - - boolean isEmbedded(); - - Object clone() throws CloneNotSupportedException; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.model; + +public interface Attribute extends Cloneable { + Class getSimpleType(); + + String getName(); + + boolean isEntityReferenceAttribute(); + + boolean isCollection(); + + String getReferencedEntityName(); + + String getUserFriendlyName(); + + boolean isEmbedded(); + + Object clone() throws CloneNotSupportedException; +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/AttributeImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/AttributeImpl.java index d9b3c8d5be..1426bb8f7f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/AttributeImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/AttributeImpl.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.model; - -public class AttributeImpl implements Attribute { - private final Class simpleType; - private final String name; - private final String referencedEntityName; - private boolean collection; - private String userFriendlyName; - private boolean isEmbedded; - - public AttributeImpl(Class simpleType, String name) { - this.simpleType = simpleType; - this.name = name; - referencedEntityName = null; - } - - public AttributeImpl(String referencedEntityName, String name, boolean isCollection) { - collection = isCollection; - this.simpleType = null; - this.name = name; - this.referencedEntityName = referencedEntityName; - } - - @Override - public Class getSimpleType() { - if (simpleType == null) - throw new IllegalStateException("Not a simpletype attribute"); - - return simpleType; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean isEntityReferenceAttribute() { - return referencedEntityName != null; - } - - @Override - public boolean isCollection() { - return collection; - } - - @Override - public String getReferencedEntityName() { - if (referencedEntityName == null) - throw new IllegalStateException("Not a referenced entity attribute"); - - return referencedEntityName; - } - - @Override - public String getUserFriendlyName() { - return userFriendlyName; - } - - public void setUserFriendlyName(String userFriendlyName) { - this.userFriendlyName = userFriendlyName; - } - - @Override - public boolean isEmbedded() { - return isEmbedded; - } - - public void setEmbedded(boolean embedded) { - isEmbedded = embedded; - } - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.model; + +public class AttributeImpl implements Attribute { + private final Class simpleType; + private final String name; + private final String referencedEntityName; + private boolean collection; + private String userFriendlyName; + private boolean isEmbedded; + + public AttributeImpl(Class simpleType, String name) { + this.simpleType = simpleType; + this.name = name; + referencedEntityName = null; + } + + public AttributeImpl(String referencedEntityName, String name, boolean isCollection) { + collection = isCollection; + this.simpleType = null; + this.name = name; + this.referencedEntityName = referencedEntityName; + } + + @Override + public Class getSimpleType() { + if (simpleType == null) + throw new IllegalStateException("Not a simpletype attribute"); + + return simpleType; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isEntityReferenceAttribute() { + return referencedEntityName != null; + } + + @Override + public boolean isCollection() { + return collection; + } + + @Override + public String getReferencedEntityName() { + if (referencedEntityName == null) + throw new IllegalStateException("Not a referenced entity attribute"); + + return referencedEntityName; + } + + @Override + public String getUserFriendlyName() { + return userFriendlyName; + } + + public void setUserFriendlyName(String userFriendlyName) { + this.userFriendlyName = userFriendlyName; + } + + @Override + public boolean isEmbedded() { + return isEmbedded; + } + + public void setEmbedded(boolean embedded) { + isEmbedded = embedded; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/EntityBuilder.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/EntityBuilder.java index 2dadf27d1b..570509092e 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/EntityBuilder.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/model/EntityBuilder.java @@ -1,81 +1,81 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.model; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MessageTools; - -public class EntityBuilder { - private JpqlEntityModelImpl result; - - public JpqlEntityModelImpl produceImmediately(String entityName) { - return new JpqlEntityModelImpl(entityName); - } - - public void startNewEntity(MetaClass metaClass) { - result = new JpqlEntityModelImpl(metaClass.getName()); - result.setUserFriendlyName(AppBeans.get(MessageTools.class).getEntityCaption(metaClass)); - } - - public JpqlEntityModel produceImmediately(String entityName, String... stringAttributeNames) { - JpqlEntityModelImpl result = new JpqlEntityModelImpl(entityName); - for (String stringAttributeName : stringAttributeNames) { - result.addSingleValueAttribute(String.class, stringAttributeName); - } - return result; - } - - public void startNewEntity(String name) { - result = new JpqlEntityModelImpl(name); - } - - public void addStringAttribute(String name) { - addSingleValueAttribute(String.class, name); - } - - public void addSingleValueAttribute(Class clazz, String name) { - result.addSingleValueAttribute(clazz, name); - } - - public void addSingleValueAttribute(Class clazz, String name, String userFriendlyName) { - result.addSingleValueAttribute(clazz, name, userFriendlyName); - } - - public void addReferenceAttribute(String name, String referencedEntityName) { - result.addReferenceAttribute(referencedEntityName, name); - } - - public void addReferenceAttribute(String name, String referencedEntityName, String userFriendlyName, boolean isEmbedded) { - result.addReferenceAttribute(referencedEntityName, name ,userFriendlyName, isEmbedded); - } - - public void addCollectionReferenceAttribute(String name, String referencedEntityName) { - result.addCollectionReferenceAttribute(referencedEntityName, name); - } - - public void addCollectionReferenceAttribute(String name, String referencedEntityName, String userFriendlyName) { - result.addCollectionReferenceAttribute(referencedEntityName, name, userFriendlyName); - } - - public JpqlEntityModel produce() { - JpqlEntityModelImpl returnedEntity = result; - result = null; - return returnedEntity; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.model; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MessageTools; + +public class EntityBuilder { + private JpqlEntityModelImpl result; + + public JpqlEntityModelImpl produceImmediately(String entityName) { + return new JpqlEntityModelImpl(entityName); + } + + public void startNewEntity(MetaClass metaClass) { + result = new JpqlEntityModelImpl(metaClass.getName()); + result.setUserFriendlyName(AppBeans.get(MessageTools.class).getEntityCaption(metaClass)); + } + + public JpqlEntityModel produceImmediately(String entityName, String... stringAttributeNames) { + JpqlEntityModelImpl result = new JpqlEntityModelImpl(entityName); + for (String stringAttributeName : stringAttributeNames) { + result.addSingleValueAttribute(String.class, stringAttributeName); + } + return result; + } + + public void startNewEntity(String name) { + result = new JpqlEntityModelImpl(name); + } + + public void addStringAttribute(String name) { + addSingleValueAttribute(String.class, name); + } + + public void addSingleValueAttribute(Class clazz, String name) { + result.addSingleValueAttribute(clazz, name); + } + + public void addSingleValueAttribute(Class clazz, String name, String userFriendlyName) { + result.addSingleValueAttribute(clazz, name, userFriendlyName); + } + + public void addReferenceAttribute(String name, String referencedEntityName) { + result.addReferenceAttribute(referencedEntityName, name); + } + + public void addReferenceAttribute(String name, String referencedEntityName, String userFriendlyName, boolean isEmbedded) { + result.addReferenceAttribute(referencedEntityName, name ,userFriendlyName, isEmbedded); + } + + public void addCollectionReferenceAttribute(String name, String referencedEntityName) { + result.addCollectionReferenceAttribute(referencedEntityName, name); + } + + public void addCollectionReferenceAttribute(String name, String referencedEntityName, String userFriendlyName) { + result.addCollectionReferenceAttribute(referencedEntityName, name, userFriendlyName); + } + + public JpqlEntityModel produce() { + JpqlEntityModelImpl returnedEntity = result; + result = null; + return returnedEntity; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/CollectionPointer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/CollectionPointer.java index 85e39d95c8..d112512b34 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/CollectionPointer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/CollectionPointer.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.pointer; - -import com.haulmont.bali.util.Preconditions; -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; - -public class CollectionPointer implements HasEntityPointer { - private JpqlEntityModel entity; - - public CollectionPointer(JpqlEntityModel entity) { - Preconditions.checkNotNullArgument(entity); - - this.entity = entity; - } - - public JpqlEntityModel getEntity() { - return entity; - } - - @Override - public Pointer next(DomainModel model, String field) { - return NoPointer.instance(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.pointer; + +import com.haulmont.bali.util.Preconditions; +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; + +public class CollectionPointer implements HasEntityPointer { + private JpqlEntityModel entity; + + public CollectionPointer(JpqlEntityModel entity) { + Preconditions.checkNotNullArgument(entity); + + this.entity = entity; + } + + public JpqlEntityModel getEntity() { + return entity; + } + + @Override + public Pointer next(DomainModel model, String field) { + return NoPointer.instance(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/EntityPointer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/EntityPointer.java index afd5afc35f..cef324bc04 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/EntityPointer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/EntityPointer.java @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.pointer; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.QueryVariableContext; -import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; -import com.haulmont.cuba.core.sys.jpql.model.Attribute; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; - -public class EntityPointer implements HasEntityPointer { - private JpqlEntityModel entity; - - private EntityPointer(JpqlEntityModel entity) { - if (entity == null) - throw new NullPointerException("No entity passed"); - - this.entity = entity; - } - - public static Pointer create(QueryVariableContext queryVC, String variableName) { - JpqlEntityModel entity = queryVC.getEntityByVariableName(variableName); - return entity == null ? NoPointer.instance() : new EntityPointer(entity); - } - - @Override - public Pointer next(DomainModel model, String field) { - Attribute attribute = entity.getAttributeByName(field); - if (attribute == null) { - return NoPointer.instance(); - } - if (!attribute.isEntityReferenceAttribute()) { - return new SimpleAttributePointer(entity, attribute); - } - - String targetEntityName = attribute.getReferencedEntityName(); - try { - JpqlEntityModel targetEntity = model.getEntityByName(targetEntityName); - return attribute.isCollection() ? - new CollectionPointer(targetEntity) : - new EntityPointer(targetEntity); - - } catch (UnknownEntityNameException e) { - return NoPointer.instance(); - } - } - - public JpqlEntityModel getEntity() { - return entity; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.pointer; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.QueryVariableContext; +import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; +import com.haulmont.cuba.core.sys.jpql.model.Attribute; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; + +public class EntityPointer implements HasEntityPointer { + private JpqlEntityModel entity; + + private EntityPointer(JpqlEntityModel entity) { + if (entity == null) + throw new NullPointerException("No entity passed"); + + this.entity = entity; + } + + public static Pointer create(QueryVariableContext queryVC, String variableName) { + JpqlEntityModel entity = queryVC.getEntityByVariableName(variableName); + return entity == null ? NoPointer.instance() : new EntityPointer(entity); + } + + @Override + public Pointer next(DomainModel model, String field) { + Attribute attribute = entity.getAttributeByName(field); + if (attribute == null) { + return NoPointer.instance(); + } + if (!attribute.isEntityReferenceAttribute()) { + return new SimpleAttributePointer(entity, attribute); + } + + String targetEntityName = attribute.getReferencedEntityName(); + try { + JpqlEntityModel targetEntity = model.getEntityByName(targetEntityName); + return attribute.isCollection() ? + new CollectionPointer(targetEntity) : + new EntityPointer(targetEntity); + + } catch (UnknownEntityNameException e) { + return NoPointer.instance(); + } + } + + public JpqlEntityModel getEntity() { + return entity; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/NoPointer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/NoPointer.java index 9a9dbefb46..5e136d2235 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/NoPointer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/NoPointer.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.pointer; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; - -public class NoPointer implements Pointer { - private static final NoPointer instance = new NoPointer(); - - private NoPointer() { - } - - public static Pointer instance() { - return instance; - } - - @Override - public Pointer next(DomainModel model, String field) { - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.pointer; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; + +public class NoPointer implements Pointer { + private static final NoPointer instance = new NoPointer(); + + private NoPointer() { + } + + public static Pointer instance() { + return instance; + } + + @Override + public Pointer next(DomainModel model, String field) { + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/Pointer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/Pointer.java index 8e2d4a4b3d..228b5af73f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/Pointer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/Pointer.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.pointer; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; - -public interface Pointer { - Pointer next(DomainModel model, String field); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.pointer; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; + +public interface Pointer { + Pointer next(DomainModel model, String field); +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/SimpleAttributePointer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/SimpleAttributePointer.java index 3f8a198374..c5d3dae8c7 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/SimpleAttributePointer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/pointer/SimpleAttributePointer.java @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.pointer; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.model.Attribute; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; - -public class SimpleAttributePointer implements Pointer { - private JpqlEntityModel entity; - private Attribute attribute; - - SimpleAttributePointer(JpqlEntityModel entity, Attribute attribute) { - this.entity = entity; - this.attribute = attribute; - } - - @Override - public Pointer next(DomainModel model, String field) { - return NoPointer.instance(); - } - - public Attribute getAttribute() { - return attribute; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.pointer; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.model.Attribute; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; + +public class SimpleAttributePointer implements Pointer { + private JpqlEntityModel entity; + private Attribute attribute; + + SimpleAttributePointer(JpqlEntityModel entity, Attribute attribute) { + this.entity = entity; + this.attribute = attribute; + } + + @Override + public Pointer next(DomainModel model, String field) { + return NoPointer.instance(); + } + + public Attribute getAttribute() { + return attribute; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityNameEntityReference.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityNameEntityReference.java index 6ac6e30ea0..8ac61b07e4 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityNameEntityReference.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityNameEntityReference.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import org.antlr.runtime.tree.Tree; - -public class EntityNameEntityReference implements EntityReference { - private String entityName; - - public EntityNameEntityReference(String entityName) { - this.entityName = entityName; - } - - @Override - public String replaceEntries(String queryPart, String replaceablePart) { - throw new UnsupportedOperationException(); - } - - @Override - public void renameVariableIn(PathNode node) { - throw new UnsupportedOperationException(); - } - - @Override - public Tree createNode() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isJoinableTo(IdentificationVariableNode node) { - return entityName.equals(node.getEffectiveEntityName()); - } - - @Override - public PathEntityReference addFieldPath(String fieldPath) { - throw new UnsupportedOperationException(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import org.antlr.runtime.tree.Tree; + +public class EntityNameEntityReference implements EntityReference { + private String entityName; + + public EntityNameEntityReference(String entityName) { + this.entityName = entityName; + } + + @Override + public String replaceEntries(String queryPart, String replaceablePart) { + throw new UnsupportedOperationException(); + } + + @Override + public void renameVariableIn(PathNode node) { + throw new UnsupportedOperationException(); + } + + @Override + public Tree createNode() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isJoinableTo(IdentificationVariableNode node) { + return entityName.equals(node.getEffectiveEntityName()); + } + + @Override + public PathEntityReference addFieldPath(String fieldPath) { + throw new UnsupportedOperationException(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReference.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReference.java index 86d3ede8c4..4dae1e8327 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReference.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReference.java @@ -1,34 +1,34 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import org.antlr.runtime.tree.Tree; - -public interface EntityReference { - String replaceEntries(String queryPart, String replaceablePart); - - void renameVariableIn(PathNode node); - - Tree createNode(); - - boolean isJoinableTo(IdentificationVariableNode node); - - PathEntityReference addFieldPath(String fieldPath); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import org.antlr.runtime.tree.Tree; + +public interface EntityReference { + String replaceEntries(String queryPart, String replaceablePart); + + void renameVariableIn(PathNode node); + + Tree createNode(); + + boolean isJoinableTo(IdentificationVariableNode node); + + PathEntityReference addFieldPath(String fieldPath); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReferenceInferer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReferenceInferer.java index acb752bb2e..cea5406c28 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReferenceInferer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/EntityReferenceInferer.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.model.VirtualJpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; - -public class EntityReferenceInferer { - private String entityName; - - public EntityReferenceInferer(String entityName) { - if (entityName == null) - throw new NullPointerException("No entity name passed"); - - this.entityName = entityName; - } - - public EntityReference infer(QueryTreeTransformer queryAnalyzer) { - String entityVariableNameInQuery = queryAnalyzer.getRootEntityVariableName(entityName); - if (entityVariableNameInQuery != null) { - return new VariableEntityReference(entityName, entityVariableNameInQuery); - } - PathNode path = queryAnalyzer.getSelectedPathNode(); - JpqlEntityModel entity = queryAnalyzer.getSelectedEntity(path); - if (!(entity instanceof VirtualJpqlEntityModel) && entity.getName().equals(entityName)) { - JpqlEntityModel pathStartingEntity = queryAnalyzer.getRootQueryVariableContext(). - getEntityByVariableName(path.getEntityVariableName()); - return new PathEntityReference(path, pathStartingEntity.getName()); - } - throw new RuntimeException(String.format("No variable or selected field of entity %s found in query", entityName)); - } - - public String getEntityName() { - return entityName; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.model.VirtualJpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; + +public class EntityReferenceInferer { + private String entityName; + + public EntityReferenceInferer(String entityName) { + if (entityName == null) + throw new NullPointerException("No entity name passed"); + + this.entityName = entityName; + } + + public EntityReference infer(QueryTreeTransformer queryAnalyzer) { + String entityVariableNameInQuery = queryAnalyzer.getRootEntityVariableName(entityName); + if (entityVariableNameInQuery != null) { + return new VariableEntityReference(entityName, entityVariableNameInQuery); + } + PathNode path = queryAnalyzer.getSelectedPathNode(); + JpqlEntityModel entity = queryAnalyzer.getSelectedEntity(path); + if (!(entity instanceof VirtualJpqlEntityModel) && entity.getName().equals(entityName)) { + JpqlEntityModel pathStartingEntity = queryAnalyzer.getRootQueryVariableContext(). + getEntityByVariableName(path.getEntityVariableName()); + return new PathEntityReference(path, pathStartingEntity.getName()); + } + throw new RuntimeException(String.format("No variable or selected field of entity %s found in query", entityName)); + } + + public String getEntityName() { + return entityName; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/ParameterCounter.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/ParameterCounter.java index ee40665d4c..d871624a56 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/ParameterCounter.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/ParameterCounter.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; -import org.antlr.runtime.tree.TreeVisitorAction; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class ParameterCounter implements TreeVisitorAction { - private boolean differentNamesOnly; - private int totalParameterCount = 0; - private Set names = new HashSet<>(); - - public ParameterCounter(boolean differentNamesOnly) { - this.differentNamesOnly = differentNamesOnly; - } - - @Override - public Object pre(Object o) { - if (o instanceof ParameterNode) { - ParameterNode node = (ParameterNode) o; - if (node.isNamed()) { - names.add(node.getParameterReference()); - } - totalParameterCount++; - } - return o; - } - - @Override - public Object post(Object o) { - return o; - } - - public int getParameterCount() { - return differentNamesOnly ? names.size() : totalParameterCount; - } - - public Set getParameterNames() { - return Collections.unmodifiableSet(names); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.tree.ParameterNode; +import org.antlr.runtime.tree.TreeVisitorAction; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class ParameterCounter implements TreeVisitorAction { + private boolean differentNamesOnly; + private int totalParameterCount = 0; + private Set names = new HashSet<>(); + + public ParameterCounter(boolean differentNamesOnly) { + this.differentNamesOnly = differentNamesOnly; + } + + @Override + public Object pre(Object o) { + if (o instanceof ParameterNode) { + ParameterNode node = (ParameterNode) o; + if (node.isNamed()) { + names.add(node.getParameterReference()); + } + totalParameterCount++; + } + return o; + } + + @Override + public Object post(Object o) { + return o; + } + + public int getParameterCount() { + return differentNamesOnly ? names.size() : totalParameterCount; + } + + public Set getParameterNames() { + return Collections.unmodifiableSet(names); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/PathEntityReference.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/PathEntityReference.java index a99cf6170f..912bc9ed54 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/PathEntityReference.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/PathEntityReference.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import org.antlr.runtime.tree.Tree; - -import java.util.ArrayList; -import java.util.List; - -public class PathEntityReference implements EntityReference { - private PathNode pathNode; - private String pathStartingEntityName; - - public PathEntityReference(PathNode pathNode, String pathStartingEntityName) { - this.pathStartingEntityName = pathStartingEntityName; - this.pathNode = pathNode.dupNode(); - } - - @Override - public String replaceEntries(String queryPart, String replaceablePart) { - return queryPart.replaceAll("\\{E\\}", pathNode.asPathString()); - } - - @Override - public void renameVariableIn(PathNode node) { - node.renameVariableTo(pathNode.getEntityVariableName()); - List newChildren = new ArrayList(pathNode.dupNode().getChildren()); - while (node.getChildCount() > 0) { - newChildren.add(node.deleteChild(0)); - } - node.addChildren(newChildren); - } - - @Override - public Tree createNode() { - return pathNode.dupNode(); - } - - @Override - public boolean isJoinableTo(IdentificationVariableNode node) { - return pathStartingEntityName.equals(node.getEffectiveEntityName()) && - pathNode.getEntityVariableName().equals(node.getVariableName()); - } - - @Override - public PathEntityReference addFieldPath(String fieldPath) { - PathNode newPathNode = pathNode.dupNode(); - newPathNode.addDefaultChildren(fieldPath); - return new PathEntityReference(newPathNode, pathStartingEntityName); - } - - public PathNode getPathNode() { - return pathNode.dupNode(); - } - - public String getPathStartingEntityName() { - return pathStartingEntityName; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import org.antlr.runtime.tree.Tree; + +import java.util.ArrayList; +import java.util.List; + +public class PathEntityReference implements EntityReference { + private PathNode pathNode; + private String pathStartingEntityName; + + public PathEntityReference(PathNode pathNode, String pathStartingEntityName) { + this.pathStartingEntityName = pathStartingEntityName; + this.pathNode = pathNode.dupNode(); + } + + @Override + public String replaceEntries(String queryPart, String replaceablePart) { + return queryPart.replaceAll("\\{E\\}", pathNode.asPathString()); + } + + @Override + public void renameVariableIn(PathNode node) { + node.renameVariableTo(pathNode.getEntityVariableName()); + List newChildren = new ArrayList(pathNode.dupNode().getChildren()); + while (node.getChildCount() > 0) { + newChildren.add(node.deleteChild(0)); + } + node.addChildren(newChildren); + } + + @Override + public Tree createNode() { + return pathNode.dupNode(); + } + + @Override + public boolean isJoinableTo(IdentificationVariableNode node) { + return pathStartingEntityName.equals(node.getEffectiveEntityName()) && + pathNode.getEntityVariableName().equals(node.getVariableName()); + } + + @Override + public PathEntityReference addFieldPath(String fieldPath) { + PathNode newPathNode = pathNode.dupNode(); + newPathNode.addDefaultChildren(fieldPath); + return new PathEntityReference(newPathNode, pathStartingEntityName); + } + + public PathNode getPathNode() { + return pathNode.dupNode(); + } + + public String getPathStartingEntityName() { + return pathStartingEntityName; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTransformerAstBased.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTransformerAstBased.java index 49911bb9bd..a9de56cc1e 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTransformerAstBased.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTransformerAstBased.java @@ -1,314 +1,314 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.global.QueryTransformer; -import com.haulmont.cuba.core.sys.PerformanceLog; -import com.haulmont.cuba.core.sys.jpql.*; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2RecognitionException; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; -import org.antlr.runtime.RecognitionException; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.TreeVisitor; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.*; - -import static java.lang.String.format; - -@Scope(BeanDefinition.SCOPE_PROTOTYPE) -@Component(QueryTransformer.NAME) -@PerformanceLog -public class QueryTransformerAstBased implements QueryTransformer { - private DomainModel model; - private String query; - private QueryTreeTransformer queryTreeTransformer; - private Set addedParams = new HashSet<>(); - private String returnedEntityName; - private String mainEntityName; - - public QueryTransformerAstBased(DomainModel model, String query) { - this.model = model; - this.query = query; - } - - private QueryTreeTransformer getQueryTransformer() { - if (queryTreeTransformer == null) { - queryTreeTransformer = new QueryTreeTransformer(); - try { - queryTreeTransformer.prepare(model, query); - } catch (RecognitionException e) { - throw new RuntimeException("Internal error while init queryTreeTransformer",e); - } catch (JPA2RecognitionException e) { - throw new JpqlSyntaxException(format("Errors found for input jpql:[%s]\n%s", StringUtils.strip(query), e.getMessage())); - } - List errors = new ArrayList<>(queryTreeTransformer.getInvalidIdVarNodes()); - if (!errors.isEmpty()) { - throw new JpqlSyntaxException(String.format("Errors found for input jpql:[%s]", StringUtils.strip(query)), errors); - } - } - return queryTreeTransformer; - } - - private String getReturnedEntityName() { - if (returnedEntityName == null) { - String returnedVariableName = getQueryTransformer().getFirstReturnedVariableName(); - JpqlEntityModel entity = getQueryTransformer().getRootQueryVariableContext().getEntityByVariableName(returnedVariableName); - if (entity != null) { - returnedEntityName = entity.getName(); - } - } - return returnedEntityName; - } - - private String getMainEntityName() { - if (mainEntityName == null) { - IdentificationVariableNode mainEntityIdentification = getQueryTransformer().getMainEntityIdentification(); - if (mainEntityIdentification != null) { - try { - JpqlEntityModel entityByName = model.getEntityByName(mainEntityIdentification.getEntityNameFromQuery()); - mainEntityName = entityByName.getName(); - } catch (UnknownEntityNameException e) { - throw new RuntimeException("Could not resolve entity for name " + mainEntityIdentification.getEntityNameFromQuery()); - } - } - } - return mainEntityName; - } - - @Override - public String getResult() { - CommonTree tree = getQueryTransformer().getTree(); - TreeVisitor visitor = new TreeVisitor(); - - TreeToQuery treeToQuery = new TreeToQuery(); - visitor.visit(tree, treeToQuery); - - return treeToQuery.getQueryString().trim(); - } - - @Override - public Set getAddedParams() { - return addedParams; - } - - @Override - public void handleCaseInsensitiveParam(String paramName) { - getQueryTransformer().handleCaseInsensitiveParam(paramName); - } - - /** - * @param where - "{E}" may be used as a replaceable entity placeholder. No such value - * should be used as a string constant - */ - @Override - public void addWhere(String where) { - EntityReferenceInferer inferrer = new EntityReferenceInferer(getMainEntityName()); - EntityReference ref = inferrer.infer(getQueryTransformer()); - if (where.contains("{E}")) { - where = ref.replaceEntries(where, "\\{E\\}"); - } - try { - CommonTree whereTree = Parser.parseWhereClause("where " + where); - addWhere(whereTree, ref, false); - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void addWhereAsIs(String where) { - try { - CommonTree whereTree = Parser.parseWhereClause("where " + where); - addWhere(whereTree, null, false); - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - /** - * copy from another statement - * - * @param statement from we copy where clause - */ - @Override - public void mergeWhere(String statement) { - EntityReferenceInferer inferer = new EntityReferenceInferer(getMainEntityName()); - EntityReference ref = inferer.infer(getQueryTransformer()); - try { - CommonTree statementTree = Parser.parse(statement, true); - CommonTree whereClause = (CommonTree) statementTree.getFirstChildWithType(JPA2Lexer.T_CONDITION); - addWhere(whereClause, ref, true); - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void addJoinAndWhere(String join, String where) { - EntityReferenceInferer inferer = new EntityReferenceInferer(getMainEntityName()); - EntityReference ref = inferer.infer(getQueryTransformer()); - if (where.contains("{E}")) { - where = ref.replaceEntries(where, "\\{E\\}"); - } - if (join.contains("{E}")) { - join = ref.replaceEntries(join, "\\{E\\}"); - } - String[] strings = join.split(","); - join = strings[0]; - try { - if (StringUtils.isNotBlank(join)) { - List joinVariableNodes = Parser.parseJoinClause(join); - boolean firstJoin = true; - for (JoinVariableNode joinVariableNode : joinVariableNodes) { - getQueryTransformer().mixinJoinIntoTree(joinVariableNode, ref, firstJoin); - firstJoin = false; - } - } - for (int i = 1; i < strings.length; i++) { - CommonTree selectionSource = Parser.parseSelectionSource(strings[i]); - getQueryTransformer().addSelectionSource(selectionSource); - } - CommonTree whereTree = Parser.parseWhereClause("where " + where); - addWhere(whereTree, ref, false); - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void addJoinAsIs(String join) { - String[] strings = join.split(","); - join = strings[0]; - try { - List joinVariableNodes = Parser.parseJoinClause(join); - for (JoinVariableNode joinVariableNode : joinVariableNodes) { - getQueryTransformer().mixinJoinIntoTree(joinVariableNode, new EntityNameEntityReference(getMainEntityName()), false); - } - for (int i = 1; i < strings.length; i++) { - CommonTree selectionSource = Parser.parseSelectionSource(strings[i]); - getQueryTransformer().addSelectionSource(selectionSource); - } - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void addFirstSelectionSource(String selection) { - try { - getQueryTransformer().addFirstSelectionSource(Parser.parseSelectionSource(selection)); - } catch (RecognitionException e) { - throw new RuntimeException(e); - } - } - - @Override - public void replaceWithCount() { - EntityReferenceInferer inferer = new EntityReferenceInferer(getReturnedEntityName()); - EntityReference ref = inferer.infer(getQueryTransformer()); - getQueryTransformer().replaceWithCount(ref); - } - - @Override - public void replaceWithSelectId() { - getQueryTransformer().replaceWithSelectId("id"); - } - - @Override - public void replaceWithSelectId(String pkName) { - getQueryTransformer().replaceWithSelectId(pkName); - } - - @Override - public void replaceWithSelectEntityVariable(String selectEntityVariable) { - getQueryTransformer().replaceWithSelectEntityVariable(selectEntityVariable); - } - - @Override - public boolean removeDistinct() { - return getQueryTransformer().removeDistinct(); - } - - @Override - public void addDistinct() { - getQueryTransformer().addDistinct(); - } - - @Override - public void replaceOrderBy(boolean desc, String... properties) { - EntityReferenceInferer inferer = new EntityReferenceInferer(getReturnedEntityName()); - EntityReference ref = inferer.infer(getQueryTransformer()); - PathEntityReference[] paths = Arrays.stream(properties) - .map(ref::addFieldPath).toArray(PathEntityReference[]::new); - getQueryTransformer().replaceOrderBy(desc, paths); - } - - @Override - public void addEntityInGroupBy(String entityAlias) { - getQueryTransformer().addEntityInGroupBy(entityAlias); - } - - @Override - public void removeOrderBy() { - getQueryTransformer().removeOrderBy(); - } - - @Override - public void replaceEntityName(String newName) { - getQueryTransformer().replaceEntityName(newName); - } - - @Override - public void reset() { - queryTreeTransformer = null; - addedParams.clear(); - } - - @Override - public void replaceInCondition(String paramName) { - getQueryTransformer().replaceInCondition(paramName); - } - - private void addWhere(CommonTree whereTree, EntityReference ref, boolean replaceVariableName) { - TreeVisitor visitor = new TreeVisitor(); - VariableManipulator variableManip = new VariableManipulator(); - visitor.visit(whereTree, variableManip); - if (replaceVariableName) { - Set variables = variableManip.getUsedVariableNames(); - if (variables.size() > 1) { - // we assume that adding where that use only one variable and does not add its own variables - throw new IllegalStateException("Multiple variables used in condition"); - } - String assumedEntityVariableInWhere = variableManip.getVariableNameInUse(0); - variableManip.renameVariable(assumedEntityVariableInWhere, ref); - } - - ParameterCounter parameterCounter = new ParameterCounter(true); - visitor.visit(whereTree, parameterCounter); - addedParams.addAll(parameterCounter.getParameterNames()); - - getQueryTransformer().mixinWhereConditionsIntoTree(whereTree); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.global.QueryTransformer; +import com.haulmont.cuba.core.sys.PerformanceLog; +import com.haulmont.cuba.core.sys.jpql.*; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2RecognitionException; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.JoinVariableNode; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeVisitor; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.*; + +import static java.lang.String.format; + +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +@Component(QueryTransformer.NAME) +@PerformanceLog +public class QueryTransformerAstBased implements QueryTransformer { + private DomainModel model; + private String query; + private QueryTreeTransformer queryTreeTransformer; + private Set addedParams = new HashSet<>(); + private String returnedEntityName; + private String mainEntityName; + + public QueryTransformerAstBased(DomainModel model, String query) { + this.model = model; + this.query = query; + } + + private QueryTreeTransformer getQueryTransformer() { + if (queryTreeTransformer == null) { + queryTreeTransformer = new QueryTreeTransformer(); + try { + queryTreeTransformer.prepare(model, query); + } catch (RecognitionException e) { + throw new RuntimeException("Internal error while init queryTreeTransformer",e); + } catch (JPA2RecognitionException e) { + throw new JpqlSyntaxException(format("Errors found for input jpql:[%s]\n%s", StringUtils.strip(query), e.getMessage())); + } + List errors = new ArrayList<>(queryTreeTransformer.getInvalidIdVarNodes()); + if (!errors.isEmpty()) { + throw new JpqlSyntaxException(String.format("Errors found for input jpql:[%s]", StringUtils.strip(query)), errors); + } + } + return queryTreeTransformer; + } + + private String getReturnedEntityName() { + if (returnedEntityName == null) { + String returnedVariableName = getQueryTransformer().getFirstReturnedVariableName(); + JpqlEntityModel entity = getQueryTransformer().getRootQueryVariableContext().getEntityByVariableName(returnedVariableName); + if (entity != null) { + returnedEntityName = entity.getName(); + } + } + return returnedEntityName; + } + + private String getMainEntityName() { + if (mainEntityName == null) { + IdentificationVariableNode mainEntityIdentification = getQueryTransformer().getMainEntityIdentification(); + if (mainEntityIdentification != null) { + try { + JpqlEntityModel entityByName = model.getEntityByName(mainEntityIdentification.getEntityNameFromQuery()); + mainEntityName = entityByName.getName(); + } catch (UnknownEntityNameException e) { + throw new RuntimeException("Could not resolve entity for name " + mainEntityIdentification.getEntityNameFromQuery()); + } + } + } + return mainEntityName; + } + + @Override + public String getResult() { + CommonTree tree = getQueryTransformer().getTree(); + TreeVisitor visitor = new TreeVisitor(); + + TreeToQuery treeToQuery = new TreeToQuery(); + visitor.visit(tree, treeToQuery); + + return treeToQuery.getQueryString().trim(); + } + + @Override + public Set getAddedParams() { + return addedParams; + } + + @Override + public void handleCaseInsensitiveParam(String paramName) { + getQueryTransformer().handleCaseInsensitiveParam(paramName); + } + + /** + * @param where - "{E}" may be used as a replaceable entity placeholder. No such value + * should be used as a string constant + */ + @Override + public void addWhere(String where) { + EntityReferenceInferer inferrer = new EntityReferenceInferer(getMainEntityName()); + EntityReference ref = inferrer.infer(getQueryTransformer()); + if (where.contains("{E}")) { + where = ref.replaceEntries(where, "\\{E\\}"); + } + try { + CommonTree whereTree = Parser.parseWhereClause("where " + where); + addWhere(whereTree, ref, false); + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + @Override + public void addWhereAsIs(String where) { + try { + CommonTree whereTree = Parser.parseWhereClause("where " + where); + addWhere(whereTree, null, false); + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + /** + * copy from another statement + * + * @param statement from we copy where clause + */ + @Override + public void mergeWhere(String statement) { + EntityReferenceInferer inferer = new EntityReferenceInferer(getMainEntityName()); + EntityReference ref = inferer.infer(getQueryTransformer()); + try { + CommonTree statementTree = Parser.parse(statement, true); + CommonTree whereClause = (CommonTree) statementTree.getFirstChildWithType(JPA2Lexer.T_CONDITION); + addWhere(whereClause, ref, true); + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + @Override + public void addJoinAndWhere(String join, String where) { + EntityReferenceInferer inferer = new EntityReferenceInferer(getMainEntityName()); + EntityReference ref = inferer.infer(getQueryTransformer()); + if (where.contains("{E}")) { + where = ref.replaceEntries(where, "\\{E\\}"); + } + if (join.contains("{E}")) { + join = ref.replaceEntries(join, "\\{E\\}"); + } + String[] strings = join.split(","); + join = strings[0]; + try { + if (StringUtils.isNotBlank(join)) { + List joinVariableNodes = Parser.parseJoinClause(join); + boolean firstJoin = true; + for (JoinVariableNode joinVariableNode : joinVariableNodes) { + getQueryTransformer().mixinJoinIntoTree(joinVariableNode, ref, firstJoin); + firstJoin = false; + } + } + for (int i = 1; i < strings.length; i++) { + CommonTree selectionSource = Parser.parseSelectionSource(strings[i]); + getQueryTransformer().addSelectionSource(selectionSource); + } + CommonTree whereTree = Parser.parseWhereClause("where " + where); + addWhere(whereTree, ref, false); + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + @Override + public void addJoinAsIs(String join) { + String[] strings = join.split(","); + join = strings[0]; + try { + List joinVariableNodes = Parser.parseJoinClause(join); + for (JoinVariableNode joinVariableNode : joinVariableNodes) { + getQueryTransformer().mixinJoinIntoTree(joinVariableNode, new EntityNameEntityReference(getMainEntityName()), false); + } + for (int i = 1; i < strings.length; i++) { + CommonTree selectionSource = Parser.parseSelectionSource(strings[i]); + getQueryTransformer().addSelectionSource(selectionSource); + } + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + @Override + public void addFirstSelectionSource(String selection) { + try { + getQueryTransformer().addFirstSelectionSource(Parser.parseSelectionSource(selection)); + } catch (RecognitionException e) { + throw new RuntimeException(e); + } + } + + @Override + public void replaceWithCount() { + EntityReferenceInferer inferer = new EntityReferenceInferer(getReturnedEntityName()); + EntityReference ref = inferer.infer(getQueryTransformer()); + getQueryTransformer().replaceWithCount(ref); + } + + @Override + public void replaceWithSelectId() { + getQueryTransformer().replaceWithSelectId("id"); + } + + @Override + public void replaceWithSelectId(String pkName) { + getQueryTransformer().replaceWithSelectId(pkName); + } + + @Override + public void replaceWithSelectEntityVariable(String selectEntityVariable) { + getQueryTransformer().replaceWithSelectEntityVariable(selectEntityVariable); + } + + @Override + public boolean removeDistinct() { + return getQueryTransformer().removeDistinct(); + } + + @Override + public void addDistinct() { + getQueryTransformer().addDistinct(); + } + + @Override + public void replaceOrderBy(boolean desc, String... properties) { + EntityReferenceInferer inferer = new EntityReferenceInferer(getReturnedEntityName()); + EntityReference ref = inferer.infer(getQueryTransformer()); + PathEntityReference[] paths = Arrays.stream(properties) + .map(ref::addFieldPath).toArray(PathEntityReference[]::new); + getQueryTransformer().replaceOrderBy(desc, paths); + } + + @Override + public void addEntityInGroupBy(String entityAlias) { + getQueryTransformer().addEntityInGroupBy(entityAlias); + } + + @Override + public void removeOrderBy() { + getQueryTransformer().removeOrderBy(); + } + + @Override + public void replaceEntityName(String newName) { + getQueryTransformer().replaceEntityName(newName); + } + + @Override + public void reset() { + queryTreeTransformer = null; + addedParams.clear(); + } + + @Override + public void replaceInCondition(String paramName) { + getQueryTransformer().replaceInCondition(paramName); + } + + private void addWhere(CommonTree whereTree, EntityReference ref, boolean replaceVariableName) { + TreeVisitor visitor = new TreeVisitor(); + VariableManipulator variableManip = new VariableManipulator(); + visitor.visit(whereTree, variableManip); + if (replaceVariableName) { + Set variables = variableManip.getUsedVariableNames(); + if (variables.size() > 1) { + // we assume that adding where that use only one variable and does not add its own variables + throw new IllegalStateException("Multiple variables used in condition"); + } + String assumedEntityVariableInWhere = variableManip.getVariableNameInUse(0); + variableManip.renameVariable(assumedEntityVariableInWhere, ref); + } + + ParameterCounter parameterCounter = new ParameterCounter(true); + visitor.visit(whereTree, parameterCounter); + addedParams.addAll(parameterCounter.getParameterNames()); + + getQueryTransformer().mixinWhereConditionsIntoTree(whereTree); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTreeTransformer.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTreeTransformer.java index ea49a37277..0a5ed1a27a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTreeTransformer.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/QueryTreeTransformer.java @@ -1,324 +1,324 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.QueryTreeAnalyzer; -import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.model.Attribute; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.tree.*; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class QueryTreeTransformer extends QueryTreeAnalyzer { - - public QueryTreeTransformer() { - } - - public void mixinWhereConditionsIntoTree(CommonTree whereTreeToMixIn) { - CommonTree whereTreeToMixWithin = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_CONDITION); - if (whereTreeToMixWithin == null) { - FromNode fromNode = (FromNode) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - List endingNodes = new ArrayList<>(); - int deletionCount = tree.getChildCount() - (fromNode.getChildIndex() + 1); - for (int i = 0; i < deletionCount; i++) { - endingNodes.add((Tree) tree.deleteChild(fromNode.getChildIndex() + 1)); - } - tree.addChild(whereTreeToMixIn); - for (Tree endingNode : endingNodes) { - tree.addChild(endingNode); - } - tree.freshenParentAndChildIndexes(); - } else { - List existingChildren = (List) whereTreeToMixWithin.getChildren(); - CommonTree existingChildrenWithBraces = new CommonTree(); - existingChildrenWithBraces.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); - existingChildrenWithBraces.addChildren(existingChildren); - existingChildrenWithBraces.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); - whereTreeToMixWithin.replaceChildren(0, whereTreeToMixWithin.getChildCount() - 1, existingChildrenWithBraces); - - CommonTree and = new CommonTree(new CommonToken(JPA2Lexer.AND, "and")); - whereTreeToMixWithin.addChild(and); - whereTreeToMixWithin.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); - for (Object o : whereTreeToMixIn.getChildren()) { - CommonTree t = (CommonTree) o; - whereTreeToMixWithin.addChild(t.dupNode()); - } - whereTreeToMixWithin.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); - whereTreeToMixWithin.freshenParentAndChildIndexes(); - } - } - - public void mixinJoinIntoTree(CommonTree joinClause, EntityReference entityRef, boolean renameVariable) { - CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - for (int i = 0; i < from.getChildCount(); i++) { - SelectionSourceNode sourceNode = (SelectionSourceNode) from.getChild(i); - if (sourceNode.getChild(0) instanceof IdentificationVariableNode) { - IdentificationVariableNode entityVariableNode = (IdentificationVariableNode) sourceNode.getChild(0); - if (entityRef.isJoinableTo(entityVariableNode)) { - String variableName = entityVariableNode.getVariableName(); - JoinVariableNode joinVariableNode = (JoinVariableNode) joinClause; - if (renameVariable) { - PathNode path = joinVariableNode.findPathNode(); - if (path != null) { - path.renameVariableTo(variableName); - } - } - sourceNode.addChild(joinClause); - from.freshenParentAndChildIndexes(); - return; - } - } - } - throw new RuntimeException("Join mixing failed. Cannot find selected entity with name " + entityRef); - } - - public void addSelectionSource(CommonTree selectionSource) { - CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - from.addChild(selectionSource); - from.freshenParentAndChildIndexes(); - } - - public void addFirstSelectionSource(CommonTree selectionSource) { - CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - from.insertChild(0, selectionSource); - from.freshenParentAndChildIndexes(); - } - - public void replaceWithCount(EntityReference entityRef) { - Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); - boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); - if (!(isDistinct && selectedItems.getChildCount() == 2 || - selectedItems.getChildCount() == 1)) - throw new IllegalStateException("Cannot replace with count if multiple fields selected"); - - SelectedItemNode selectedItemNode; - if (isDistinct) - selectedItems.deleteChild(0); - - selectedItemNode = (SelectedItemNode) selectedItems.getChild(0); - AggregateExpressionNode countNode = createCountNode(entityRef, isDistinct); - selectedItemNode.deleteChild(0); - selectedItemNode.addChild(countNode); - - Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY); - if (orderBy != null) { - tree.deleteChild(orderBy.getChildIndex()); - } - tree.freshenParentAndChildIndexes(); - } - - public void removeOrderBy() { - Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY); - if (orderBy != null) { - tree.deleteChild(orderBy.getChildIndex()); - } - tree.freshenParentAndChildIndexes(); - } - - public boolean removeDistinct() { - Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); - boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); - if (isDistinct) { - selectedItems.deleteChild(0); - } else { - return false; - } - tree.freshenParentAndChildIndexes(); - return true; - } - - public void addDistinct() { - CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); - boolean isDistinct = "distinct".equalsIgnoreCase(selectedItems.getChild(0).getText()); - if (!isDistinct) { - selectedItems.insertChild(0, new CommonTree(new CommonToken(JPA2Lexer.DISTINCT, "distinct"))); - selectedItems.freshenParentAndChildIndexes(); - } - } - - public void replaceEntityName(String newEntityName) { - IdentificationVariableNode identificationVariable = getMainEntityIdentification(); - if (identificationVariable != null) { - identificationVariable.deleteChild(0); - identificationVariable.addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, newEntityName))); - tree.freshenParentAndChildIndexes(); - } - } - - public void replaceOrderBy(boolean desc, PathEntityReference... orderingFieldRefs) { - removeOrderBy(); - CommonTree orderBy = new OrderByNode(JPA2Lexer.T_ORDER_BY); - tree.addChild(orderBy); - orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.ORDER, "order"))); - orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.BY, "by"))); - - Set addedJoinVariables = new HashSet<>(); - for (PathEntityReference orderingFieldRef : orderingFieldRefs) { - OrderByFieldNode orderByField = new OrderByFieldNode(JPA2Lexer.T_ORDER_BY_FIELD); - orderBy.addChild(orderByField); - - PathNode pathNode = orderingFieldRef.getPathNode(); - if (pathNode.getChildCount() > 1) { - List pathNodes = getPathNodesForOrderBy(orderingFieldRef); - if (pathNodes.size() > 1) { - orderByField.addChild(pathNodes.remove(pathNodes.size() - 1)); - for (PathNode joinPathNode : pathNodes) { - String joinPathNodeVariableName = joinPathNode.asPathString('_'); - if (!addedJoinVariables.contains(joinPathNodeVariableName)) { - JoinVariableNode joinNode = new JoinVariableNode(JPA2Lexer.T_JOIN_VAR, "left join", joinPathNodeVariableName); - joinNode.addChild(joinPathNode); - - CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); - from.getChild(0).addChild(joinNode); // assumption - addedJoinVariables.add(joinPathNodeVariableName); - } - } - } else { - orderByField.addChild(orderingFieldRef.createNode()); - } - } else { - orderByField.addChild(orderingFieldRef.createNode()); - } - - if (desc) { - orderByField.addChild(new CommonTree(new CommonToken(JPA2Lexer.DESC, "desc"))); - } - orderByField.freshenParentAndChildIndexes(); - } - } - - public void addEntityInGroupBy(String entityAlias) { - Tree groupBy = tree.getFirstChildWithType(JPA2Lexer.T_GROUP_BY); - if (groupBy != null) { - groupBy.addChild(new PathNode(JPA2Lexer.T_SELECTED_ENTITY, entityAlias)); - groupBy.freshenParentAndChildIndexes(); - } - } - - public void handleCaseInsensitiveParam(String paramName) { - List conditionNodesWithParameter = findConditionsForParameter(paramName); - - for (SimpleConditionNode simpleConditionNode : conditionNodesWithParameter) { - List toProcess = new ArrayList<>(); - for (int idx = 0; idx < simpleConditionNode.getChildCount(); idx++) { - Tree child = simpleConditionNode.getChild(idx); - if (child.getType() == JPA2Lexer.T_SELECTED_FIELD) { - toProcess.add((PathNode) child); - } - } - for (PathNode pathNode : toProcess) { - for (int idx = 0; idx < simpleConditionNode.getChildCount(); idx++) { - Tree child = simpleConditionNode.getChild(idx); - if (child == pathNode) { - CommonTree loweredPathNode = new CommonTree(); - loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.LOWER, "lower"))); - loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); - loweredPathNode.addChild(pathNode); - loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); - simpleConditionNode.replaceChildren(idx, idx, loweredPathNode); - break; - } - } - } - } - tree.freshenParentAndChildIndexes(); - } - - public void replaceInCondition(String paramName) { - List conditionNodesWithParameter = findConditionsForParameter(paramName); - for (SimpleConditionNode simpleConditionNode : conditionNodesWithParameter) { - Tree inToken = simpleConditionNode.getFirstChildWithType(JPA2Lexer.IN); - if (inToken != null) { - Tree notToken = simpleConditionNode.getFirstChildWithType(JPA2Lexer.NOT); - simpleConditionNode.getChildren().clear(); - simpleConditionNode.addChild( - new CommonTree(new CommonToken(JPA2Lexer.WORD, notToken == null ? "1=0" : "1=1"))); - } - } - tree.freshenParentAndChildIndexes(); - } - - public void replaceWithSelectId(String pkName) { - PathNode returnedPathNode = getFirstReturnedPathNode(); - if (returnedPathNode != null) { - returnedPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, pkName))); - } - } - - public void replaceWithSelectEntityVariable(String selectEntityVariable) { - PathNode returnedPathNode = getFirstReturnedPathNode(); - if (returnedPathNode != null) { - returnedPathNode.renameVariableTo(selectEntityVariable); - while (returnedPathNode.getChildCount() > 0) { - returnedPathNode.deleteChild(0); - } - } - } - - protected AggregateExpressionNode createCountNode(EntityReference ref, boolean distinct) { - AggregateExpressionNode result = new AggregateExpressionNode(JPA2Lexer.T_AGGREGATE_EXPR); - - result.addChild(new CommonTree(new CommonToken(JPA2Lexer.COUNT, "count"))); - result.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); - if (distinct) { - result.addChild(new CommonTree(new CommonToken(JPA2Lexer.DISTINCT, "distinct"))); - } - result.addChild(ref.createNode()); - result.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); - return result; - } - - protected List getPathNodesForOrderBy(PathEntityReference pathEntityReference) { - List pathNodes = new ArrayList<>(); - String entityName = pathEntityReference.getPathStartingEntityName(); - PathNode pathNode = pathEntityReference.getPathNode(); - try { - JpqlEntityModel entity = model.getEntityByName(entityName); - String currentVariableName = pathNode.getEntityVariableName(); - PathNode currentPathNode = new PathNode(pathNode.getToken(), currentVariableName); - for (int i = 0; i < pathNode.getChildCount(); i++) { - String fieldName = pathNode.getChild(i).toString(); - Attribute entityAttribute = entity.getAttributeByName(fieldName); - if (entityAttribute.isEntityReferenceAttribute() && !entityAttribute.isEmbedded()) { - currentPathNode.addDefaultChild(fieldName); - pathNodes.add(currentPathNode); - currentVariableName = currentPathNode.asPathString('_'); - currentPathNode = new PathNode(pathNode.getToken(), currentVariableName); - } else { - currentPathNode.addDefaultChild(fieldName); - } - if (entityAttribute.isEntityReferenceAttribute()) { - entityName = entityAttribute.getReferencedEntityName(); - entity = model.getEntityByName(entityName); - } - } - pathNodes.add(currentPathNode); - } catch (UnknownEntityNameException e) { - throw new RuntimeException(String.format("Could not find entity by name %s", entityName), e); - } - return pathNodes; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.QueryTreeAnalyzer; +import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.model.Attribute; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.tree.*; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class QueryTreeTransformer extends QueryTreeAnalyzer { + + public QueryTreeTransformer() { + } + + public void mixinWhereConditionsIntoTree(CommonTree whereTreeToMixIn) { + CommonTree whereTreeToMixWithin = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_CONDITION); + if (whereTreeToMixWithin == null) { + FromNode fromNode = (FromNode) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + List endingNodes = new ArrayList<>(); + int deletionCount = tree.getChildCount() - (fromNode.getChildIndex() + 1); + for (int i = 0; i < deletionCount; i++) { + endingNodes.add((Tree) tree.deleteChild(fromNode.getChildIndex() + 1)); + } + tree.addChild(whereTreeToMixIn); + for (Tree endingNode : endingNodes) { + tree.addChild(endingNode); + } + tree.freshenParentAndChildIndexes(); + } else { + List existingChildren = (List) whereTreeToMixWithin.getChildren(); + CommonTree existingChildrenWithBraces = new CommonTree(); + existingChildrenWithBraces.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); + existingChildrenWithBraces.addChildren(existingChildren); + existingChildrenWithBraces.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); + whereTreeToMixWithin.replaceChildren(0, whereTreeToMixWithin.getChildCount() - 1, existingChildrenWithBraces); + + CommonTree and = new CommonTree(new CommonToken(JPA2Lexer.AND, "and")); + whereTreeToMixWithin.addChild(and); + whereTreeToMixWithin.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); + for (Object o : whereTreeToMixIn.getChildren()) { + CommonTree t = (CommonTree) o; + whereTreeToMixWithin.addChild(t.dupNode()); + } + whereTreeToMixWithin.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); + whereTreeToMixWithin.freshenParentAndChildIndexes(); + } + } + + public void mixinJoinIntoTree(CommonTree joinClause, EntityReference entityRef, boolean renameVariable) { + CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + for (int i = 0; i < from.getChildCount(); i++) { + SelectionSourceNode sourceNode = (SelectionSourceNode) from.getChild(i); + if (sourceNode.getChild(0) instanceof IdentificationVariableNode) { + IdentificationVariableNode entityVariableNode = (IdentificationVariableNode) sourceNode.getChild(0); + if (entityRef.isJoinableTo(entityVariableNode)) { + String variableName = entityVariableNode.getVariableName(); + JoinVariableNode joinVariableNode = (JoinVariableNode) joinClause; + if (renameVariable) { + PathNode path = joinVariableNode.findPathNode(); + if (path != null) { + path.renameVariableTo(variableName); + } + } + sourceNode.addChild(joinClause); + from.freshenParentAndChildIndexes(); + return; + } + } + } + throw new RuntimeException("Join mixing failed. Cannot find selected entity with name " + entityRef); + } + + public void addSelectionSource(CommonTree selectionSource) { + CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + from.addChild(selectionSource); + from.freshenParentAndChildIndexes(); + } + + public void addFirstSelectionSource(CommonTree selectionSource) { + CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + from.insertChild(0, selectionSource); + from.freshenParentAndChildIndexes(); + } + + public void replaceWithCount(EntityReference entityRef) { + Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); + boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); + if (!(isDistinct && selectedItems.getChildCount() == 2 || + selectedItems.getChildCount() == 1)) + throw new IllegalStateException("Cannot replace with count if multiple fields selected"); + + SelectedItemNode selectedItemNode; + if (isDistinct) + selectedItems.deleteChild(0); + + selectedItemNode = (SelectedItemNode) selectedItems.getChild(0); + AggregateExpressionNode countNode = createCountNode(entityRef, isDistinct); + selectedItemNode.deleteChild(0); + selectedItemNode.addChild(countNode); + + Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY); + if (orderBy != null) { + tree.deleteChild(orderBy.getChildIndex()); + } + tree.freshenParentAndChildIndexes(); + } + + public void removeOrderBy() { + Tree orderBy = tree.getFirstChildWithType(JPA2Lexer.T_ORDER_BY); + if (orderBy != null) { + tree.deleteChild(orderBy.getChildIndex()); + } + tree.freshenParentAndChildIndexes(); + } + + public boolean removeDistinct() { + Tree selectedItems = tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); + boolean isDistinct = "DISTINCT".equalsIgnoreCase(selectedItems.getChild(0).getText()); + if (isDistinct) { + selectedItems.deleteChild(0); + } else { + return false; + } + tree.freshenParentAndChildIndexes(); + return true; + } + + public void addDistinct() { + CommonTree selectedItems = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SELECTED_ITEMS); + boolean isDistinct = "distinct".equalsIgnoreCase(selectedItems.getChild(0).getText()); + if (!isDistinct) { + selectedItems.insertChild(0, new CommonTree(new CommonToken(JPA2Lexer.DISTINCT, "distinct"))); + selectedItems.freshenParentAndChildIndexes(); + } + } + + public void replaceEntityName(String newEntityName) { + IdentificationVariableNode identificationVariable = getMainEntityIdentification(); + if (identificationVariable != null) { + identificationVariable.deleteChild(0); + identificationVariable.addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, newEntityName))); + tree.freshenParentAndChildIndexes(); + } + } + + public void replaceOrderBy(boolean desc, PathEntityReference... orderingFieldRefs) { + removeOrderBy(); + CommonTree orderBy = new OrderByNode(JPA2Lexer.T_ORDER_BY); + tree.addChild(orderBy); + orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.ORDER, "order"))); + orderBy.addChild(new CommonTree(new CommonToken(JPA2Lexer.BY, "by"))); + + Set addedJoinVariables = new HashSet<>(); + for (PathEntityReference orderingFieldRef : orderingFieldRefs) { + OrderByFieldNode orderByField = new OrderByFieldNode(JPA2Lexer.T_ORDER_BY_FIELD); + orderBy.addChild(orderByField); + + PathNode pathNode = orderingFieldRef.getPathNode(); + if (pathNode.getChildCount() > 1) { + List pathNodes = getPathNodesForOrderBy(orderingFieldRef); + if (pathNodes.size() > 1) { + orderByField.addChild(pathNodes.remove(pathNodes.size() - 1)); + for (PathNode joinPathNode : pathNodes) { + String joinPathNodeVariableName = joinPathNode.asPathString('_'); + if (!addedJoinVariables.contains(joinPathNodeVariableName)) { + JoinVariableNode joinNode = new JoinVariableNode(JPA2Lexer.T_JOIN_VAR, "left join", joinPathNodeVariableName); + joinNode.addChild(joinPathNode); + + CommonTree from = (CommonTree) tree.getFirstChildWithType(JPA2Lexer.T_SOURCES); + from.getChild(0).addChild(joinNode); // assumption + addedJoinVariables.add(joinPathNodeVariableName); + } + } + } else { + orderByField.addChild(orderingFieldRef.createNode()); + } + } else { + orderByField.addChild(orderingFieldRef.createNode()); + } + + if (desc) { + orderByField.addChild(new CommonTree(new CommonToken(JPA2Lexer.DESC, "desc"))); + } + orderByField.freshenParentAndChildIndexes(); + } + } + + public void addEntityInGroupBy(String entityAlias) { + Tree groupBy = tree.getFirstChildWithType(JPA2Lexer.T_GROUP_BY); + if (groupBy != null) { + groupBy.addChild(new PathNode(JPA2Lexer.T_SELECTED_ENTITY, entityAlias)); + groupBy.freshenParentAndChildIndexes(); + } + } + + public void handleCaseInsensitiveParam(String paramName) { + List conditionNodesWithParameter = findConditionsForParameter(paramName); + + for (SimpleConditionNode simpleConditionNode : conditionNodesWithParameter) { + List toProcess = new ArrayList<>(); + for (int idx = 0; idx < simpleConditionNode.getChildCount(); idx++) { + Tree child = simpleConditionNode.getChild(idx); + if (child.getType() == JPA2Lexer.T_SELECTED_FIELD) { + toProcess.add((PathNode) child); + } + } + for (PathNode pathNode : toProcess) { + for (int idx = 0; idx < simpleConditionNode.getChildCount(); idx++) { + Tree child = simpleConditionNode.getChild(idx); + if (child == pathNode) { + CommonTree loweredPathNode = new CommonTree(); + loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.LOWER, "lower"))); + loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); + loweredPathNode.addChild(pathNode); + loweredPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); + simpleConditionNode.replaceChildren(idx, idx, loweredPathNode); + break; + } + } + } + } + tree.freshenParentAndChildIndexes(); + } + + public void replaceInCondition(String paramName) { + List conditionNodesWithParameter = findConditionsForParameter(paramName); + for (SimpleConditionNode simpleConditionNode : conditionNodesWithParameter) { + Tree inToken = simpleConditionNode.getFirstChildWithType(JPA2Lexer.IN); + if (inToken != null) { + Tree notToken = simpleConditionNode.getFirstChildWithType(JPA2Lexer.NOT); + simpleConditionNode.getChildren().clear(); + simpleConditionNode.addChild( + new CommonTree(new CommonToken(JPA2Lexer.WORD, notToken == null ? "1=0" : "1=1"))); + } + } + tree.freshenParentAndChildIndexes(); + } + + public void replaceWithSelectId(String pkName) { + PathNode returnedPathNode = getFirstReturnedPathNode(); + if (returnedPathNode != null) { + returnedPathNode.addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, pkName))); + } + } + + public void replaceWithSelectEntityVariable(String selectEntityVariable) { + PathNode returnedPathNode = getFirstReturnedPathNode(); + if (returnedPathNode != null) { + returnedPathNode.renameVariableTo(selectEntityVariable); + while (returnedPathNode.getChildCount() > 0) { + returnedPathNode.deleteChild(0); + } + } + } + + protected AggregateExpressionNode createCountNode(EntityReference ref, boolean distinct) { + AggregateExpressionNode result = new AggregateExpressionNode(JPA2Lexer.T_AGGREGATE_EXPR); + + result.addChild(new CommonTree(new CommonToken(JPA2Lexer.COUNT, "count"))); + result.addChild(new CommonTree(new CommonToken(JPA2Lexer.LPAREN, "("))); + if (distinct) { + result.addChild(new CommonTree(new CommonToken(JPA2Lexer.DISTINCT, "distinct"))); + } + result.addChild(ref.createNode()); + result.addChild(new CommonTree(new CommonToken(JPA2Lexer.RPAREN, ")"))); + return result; + } + + protected List getPathNodesForOrderBy(PathEntityReference pathEntityReference) { + List pathNodes = new ArrayList<>(); + String entityName = pathEntityReference.getPathStartingEntityName(); + PathNode pathNode = pathEntityReference.getPathNode(); + try { + JpqlEntityModel entity = model.getEntityByName(entityName); + String currentVariableName = pathNode.getEntityVariableName(); + PathNode currentPathNode = new PathNode(pathNode.getToken(), currentVariableName); + for (int i = 0; i < pathNode.getChildCount(); i++) { + String fieldName = pathNode.getChild(i).toString(); + Attribute entityAttribute = entity.getAttributeByName(fieldName); + if (entityAttribute.isEntityReferenceAttribute() && !entityAttribute.isEmbedded()) { + currentPathNode.addDefaultChild(fieldName); + pathNodes.add(currentPathNode); + currentVariableName = currentPathNode.asPathString('_'); + currentPathNode = new PathNode(pathNode.getToken(), currentVariableName); + } else { + currentPathNode.addDefaultChild(fieldName); + } + if (entityAttribute.isEntityReferenceAttribute()) { + entityName = entityAttribute.getReferencedEntityName(); + entity = model.getEntityByName(entityName); + } + } + pathNodes.add(currentPathNode); + } catch (UnknownEntityNameException e) { + throw new RuntimeException(String.format("Could not find entity by name %s", entityName), e); + } + return pathNodes; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableEntityReference.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableEntityReference.java index ce9f539aeb..146b80fe6e 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableEntityReference.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableEntityReference.java @@ -1,63 +1,63 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -public class VariableEntityReference implements EntityReference { - private String entityName; - private String entityVariableName; - - public VariableEntityReference(String entityName, String entityVariableNameInQuery) { - this.entityName = entityName; - this.entityVariableName = entityVariableNameInQuery; - } - - @Override - public String replaceEntries(String queryPart, String replaceablePart) { - return queryPart.replaceAll("\\{E\\}", entityVariableName); - } - - @Override - public void renameVariableIn(PathNode node) { - node.renameVariableTo(entityVariableName); - } - - @Override - public Tree createNode() { - return new CommonTree(new CommonToken(JPA2Lexer.WORD, entityVariableName)); - } - - @Override - public boolean isJoinableTo(IdentificationVariableNode node) { - return entityName.equals(node.getEffectiveEntityName()); - } - - - @Override - public PathEntityReference addFieldPath(String fieldPath) { - PathNode pathNode = new PathNode(JPA2Lexer.T_SELECTED_FIELD, entityVariableName); - pathNode.addDefaultChildren(fieldPath); - return new PathEntityReference(pathNode, entityName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.tree.IdentificationVariableNode; +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +public class VariableEntityReference implements EntityReference { + private String entityName; + private String entityVariableName; + + public VariableEntityReference(String entityName, String entityVariableNameInQuery) { + this.entityName = entityName; + this.entityVariableName = entityVariableNameInQuery; + } + + @Override + public String replaceEntries(String queryPart, String replaceablePart) { + return queryPart.replaceAll("\\{E\\}", entityVariableName); + } + + @Override + public void renameVariableIn(PathNode node) { + node.renameVariableTo(entityVariableName); + } + + @Override + public Tree createNode() { + return new CommonTree(new CommonToken(JPA2Lexer.WORD, entityVariableName)); + } + + @Override + public boolean isJoinableTo(IdentificationVariableNode node) { + return entityName.equals(node.getEffectiveEntityName()); + } + + + @Override + public PathEntityReference addFieldPath(String fieldPath) { + PathNode pathNode = new PathNode(JPA2Lexer.T_SELECTED_FIELD, entityVariableName); + pathNode.addDefaultChildren(fieldPath); + return new PathEntityReference(pathNode, entityName); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableManipulator.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableManipulator.java index f6ce72736b..0fbd74f5a8 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableManipulator.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/transform/VariableManipulator.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.transform; - -import com.haulmont.cuba.core.sys.jpql.tree.PathNode; -import org.antlr.runtime.tree.TreeVisitorAction; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class VariableManipulator implements TreeVisitorAction { - private List variableUses = new ArrayList<>(); - - public VariableManipulator() { - } - - @Override - public Object pre(Object o) { - // todo unsafe, if we change a tree and it declares its own variables - if (o instanceof PathNode) { - PathNode pathNode = (PathNode) o; - variableUses.add(pathNode); - } - return o; - } - - @Override - public Object post(Object o) { - return o; - } - - public Set getUsedVariableNames() { - Set result = new HashSet<>(); - for (PathNode variableUse : variableUses) { - result.add(variableUse.getEntityVariableName()); - } - return result; - } - - public String getVariableNameInUse(int index) { - return variableUses.get(index).getEntityVariableName(); - } - - public void renameVariable(String origName, EntityReference newName) { - if (origName == null) - throw new NullPointerException("No original name passed"); - if (newName == null) - throw new NullPointerException("No new name passed"); - - for (PathNode variableUse : variableUses) { - if (origName.equals(variableUse.getEntityVariableName())) { - newName.renameVariableIn(variableUse); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.transform; + +import com.haulmont.cuba.core.sys.jpql.tree.PathNode; +import org.antlr.runtime.tree.TreeVisitorAction; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class VariableManipulator implements TreeVisitorAction { + private List variableUses = new ArrayList<>(); + + public VariableManipulator() { + } + + @Override + public Object pre(Object o) { + // todo unsafe, if we change a tree and it declares its own variables + if (o instanceof PathNode) { + PathNode pathNode = (PathNode) o; + variableUses.add(pathNode); + } + return o; + } + + @Override + public Object post(Object o) { + return o; + } + + public Set getUsedVariableNames() { + Set result = new HashSet<>(); + for (PathNode variableUse : variableUses) { + result.add(variableUse.getEntityVariableName()); + } + return result; + } + + public String getVariableNameInUse(int index) { + return variableUses.get(index).getEntityVariableName(); + } + + public void renameVariable(String origName, EntityReference newName) { + if (origName == null) + throw new NullPointerException("No original name passed"); + if (newName == null) + throw new NullPointerException("No new name passed"); + + for (PathNode variableUse : variableUses) { + if (origName.equals(variableUse.getEntityVariableName())) { + newName.renameVariableIn(variableUse); + } + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/AggregateExpressionNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/AggregateExpressionNode.java index 51bee48493..87e9f5461c 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/AggregateExpressionNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/AggregateExpressionNode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.Tree; - -public class AggregateExpressionNode extends BaseCustomNode { - private AggregateExpressionNode(Token token) { - super(token); - } - - public AggregateExpressionNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "AGGREGATE EXPR"; - } - - @Override - public Tree dupNode() { - AggregateExpressionNode result = new AggregateExpressionNode(token); - dupChildren(result); - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.Tree; + +public class AggregateExpressionNode extends BaseCustomNode { + private AggregateExpressionNode(Token token) { + super(token); + } + + public AggregateExpressionNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "AGGREGATE EXPR"; + } + + @Override + public Tree dupNode() { + AggregateExpressionNode result = new AggregateExpressionNode(token); + dupChildren(result); + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseCustomNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseCustomNode.java index 13001332c1..f10a7a5ec2 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseCustomNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseCustomNode.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class BaseCustomNode extends CommonTree implements TreeToQueryCapable { - public BaseCustomNode(Token t) { - super(t); - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - return this; - } - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - return this; - } - - protected CommonTree getNextNode() { - return getChildIndex() == (getParent().getChildCount() - 1) ? - null: - (CommonTree) getParent().getChild(getChildIndex() + 1); - } - - protected CommonTree getPrevNode() { - return getChildIndex() == 0 ? - null: - (CommonTree) getParent().getChild(getChildIndex() - 1); - } - - protected void dupChildren(CommonTree result) { - for (Object child : children) { - CommonTree t = (CommonTree) child; - Tree copy = t.dupNode(); - result.addChild(copy); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class BaseCustomNode extends CommonTree implements TreeToQueryCapable { + public BaseCustomNode(Token t) { + super(t); + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + return this; + } + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + return this; + } + + protected CommonTree getNextNode() { + return getChildIndex() == (getParent().getChildCount() - 1) ? + null: + (CommonTree) getParent().getChild(getChildIndex() + 1); + } + + protected CommonTree getPrevNode() { + return getChildIndex() == 0 ? + null: + (CommonTree) getParent().getChild(getChildIndex() - 1); + } + + protected void dupChildren(CommonTree result) { + for (Object child : children) { + CommonTree t = (CommonTree) child; + Tree copy = t.dupNode(); + result.addChild(copy); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseJoinNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseJoinNode.java index 0c6e90d0fb..bae3ca1185 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseJoinNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/BaseJoinNode.java @@ -1,102 +1,102 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryVariableContext; -import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; -import com.haulmont.cuba.core.sys.jpql.pointer.*; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.CommonTree; - -import java.util.Deque; -import java.util.List; - -public class BaseJoinNode extends BaseCustomNode { - protected String variableName; - - protected BaseJoinNode(Token token, String variableName) { - super(token); - this.variableName = variableName; - } - - public BaseJoinNode(int type, String variableName) { - this(new CommonToken(type, ""), variableName); - } - - public String getVariableName() { - return variableName; - } - - public void identifyVariableEntity(DomainModel model, - Deque stack, - List invalidNodes) { - String variableName = getVariableName(); - if (variableName == null) { - invalidNodes.add(new ErrorRec(this, "No variable name found")); - return; - } - - List children = getChildren(); - if (children == null || children.size() == 0) { - invalidNodes.add(new ErrorRec(this, "No children found")); - return; - } - - CommonTree child0 = (CommonTree) children.get(0); - if (child0 instanceof CommonErrorNode) { - invalidNodes.add(new ErrorRec(this, "Child 0 is an error node")); - return; - } - - QueryVariableContext queryVC = stack.peekLast(); - - if (child0 instanceof PathNode) { - PathNode pathNode = (PathNode) child0; - Pointer pointer = pathNode.resolvePointer(model, queryVC); - if (pointer instanceof NoPointer) { - invalidNodes.add(new ErrorRec(this, "Cannot resolve joined entity")); - } else if (pointer instanceof SimpleAttributePointer) { - invalidNodes.add(new ErrorRec(this, "Joined entity resolved to a non-entity attribute")); - } else if (pointer instanceof EntityPointer) { - queryVC.addEntityVariable(variableName, ((EntityPointer) pointer).getEntity()); - } else if (pointer instanceof CollectionPointer) { - queryVC.addEntityVariable(variableName, ((CollectionPointer) pointer).getEntity()); - } else { - invalidNodes.add(new ErrorRec(this, - "Unexpected pointer variable type: " + pointer.getClass()) - ); - } - } else {//this special case is for "join X on X.a = Y.b" query. Entity name would be just text in the child node - try { - queryVC.addEntityVariable(variableName, model.getEntityByName(child0.getText())); - } catch (UnknownEntityNameException e) { - invalidNodes.add(new ErrorRec(this, - "Could not find entity for name " + child0.getText()) - ); - } - } - } - - public void setVariableName(String newName) { - variableName = newName; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryVariableContext; +import com.haulmont.cuba.core.sys.jpql.UnknownEntityNameException; +import com.haulmont.cuba.core.sys.jpql.pointer.*; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; + +import java.util.Deque; +import java.util.List; + +public class BaseJoinNode extends BaseCustomNode { + protected String variableName; + + protected BaseJoinNode(Token token, String variableName) { + super(token); + this.variableName = variableName; + } + + public BaseJoinNode(int type, String variableName) { + this(new CommonToken(type, ""), variableName); + } + + public String getVariableName() { + return variableName; + } + + public void identifyVariableEntity(DomainModel model, + Deque stack, + List invalidNodes) { + String variableName = getVariableName(); + if (variableName == null) { + invalidNodes.add(new ErrorRec(this, "No variable name found")); + return; + } + + List children = getChildren(); + if (children == null || children.size() == 0) { + invalidNodes.add(new ErrorRec(this, "No children found")); + return; + } + + CommonTree child0 = (CommonTree) children.get(0); + if (child0 instanceof CommonErrorNode) { + invalidNodes.add(new ErrorRec(this, "Child 0 is an error node")); + return; + } + + QueryVariableContext queryVC = stack.peekLast(); + + if (child0 instanceof PathNode) { + PathNode pathNode = (PathNode) child0; + Pointer pointer = pathNode.resolvePointer(model, queryVC); + if (pointer instanceof NoPointer) { + invalidNodes.add(new ErrorRec(this, "Cannot resolve joined entity")); + } else if (pointer instanceof SimpleAttributePointer) { + invalidNodes.add(new ErrorRec(this, "Joined entity resolved to a non-entity attribute")); + } else if (pointer instanceof EntityPointer) { + queryVC.addEntityVariable(variableName, ((EntityPointer) pointer).getEntity()); + } else if (pointer instanceof CollectionPointer) { + queryVC.addEntityVariable(variableName, ((CollectionPointer) pointer).getEntity()); + } else { + invalidNodes.add(new ErrorRec(this, + "Unexpected pointer variable type: " + pointer.getClass()) + ); + } + } else {//this special case is for "join X on X.a = Y.b" query. Entity name would be just text in the child node + try { + queryVC.addEntityVariable(variableName, model.getEntityByName(child0.getText())); + } catch (UnknownEntityNameException e) { + invalidNodes.add(new ErrorRec(this, + "Could not find entity for name " + child0.getText()) + ); + } + } + } + + public void setVariableName(String newName) { + variableName = newName; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/CollectionMemberNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/CollectionMemberNode.java index 17d484e248..cea8e620b5 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/CollectionMemberNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/CollectionMemberNode.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class CollectionMemberNode extends BaseJoinNode { - - private CollectionMemberNode(Token token, String variableName) { - super(token, variableName); - } - - public CollectionMemberNode(int type, String variableName) { - this(new CommonToken(type, ""), variableName); - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + "Collection member decl: " + variableName; - } - - @Override - public Tree dupNode() { - CollectionMemberNode result = new CollectionMemberNode(token, variableName); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - sb.appendSpace(); - sb.appendString("in("); - return this; - } - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - sb.appendString(")"); - sb.appendSpace(); - sb.appendString(variableName); - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class CollectionMemberNode extends BaseJoinNode { + + private CollectionMemberNode(Token token, String variableName) { + super(token, variableName); + } + + public CollectionMemberNode(int type, String variableName) { + this(new CommonToken(type, ""), variableName); + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + "Collection member decl: " + variableName; + } + + @Override + public Tree dupNode() { + CollectionMemberNode result = new CollectionMemberNode(token, variableName); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + sb.appendSpace(); + sb.appendString("in("); + return this; + } + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + sb.appendString(")"); + sb.appendSpace(); + sb.appendString(variableName); + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/FromNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/FromNode.java index 2d878cdff2..bbe8b119a1 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/FromNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/FromNode.java @@ -1,59 +1,59 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class FromNode extends BaseCustomNode { - private Token fromT; - - private FromNode(Token token, Token fromT) { - super(token); - this.fromT = fromT; - } - - public FromNode(int type, Token fromT) { - this(new CommonToken(type, ""), fromT); - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + fromT; - } - - @Override - public Tree dupNode() { - FromNode result = new FromNode(token, fromT); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - sb.appendSpace(); - sb.appendString(fromT.getText()); - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class FromNode extends BaseCustomNode { + private Token fromT; + + private FromNode(Token token, Token fromT) { + super(token); + this.fromT = fromT; + } + + public FromNode(int type, Token fromT) { + this(new CommonToken(type, ""), fromT); + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + fromT; + } + + @Override + public Tree dupNode() { + FromNode result = new FromNode(token, fromT); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + sb.appendSpace(); + sb.appendString(fromT.getText()); + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/GroupByNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/GroupByNode.java index ebb1e96d3a..b3b68574a5 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/GroupByNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/GroupByNode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.Tree; - -public class GroupByNode extends BaseCustomNode { - private GroupByNode(Token token) { - super(token); - } - - public GroupByNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "GROUP BY"; - } - - @Override - public Tree dupNode() { - GroupByNode result = new GroupByNode(token); - dupChildren(result); - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.Tree; + +public class GroupByNode extends BaseCustomNode { + private GroupByNode(Token token) { + super(token); + } + + public GroupByNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "GROUP BY"; + } + + @Override + public Tree dupNode() { + GroupByNode result = new GroupByNode(token); + dupChildren(result); + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/IdentificationVariableNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/IdentificationVariableNode.java index ad07e0ff9a..8bcc705038 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/IdentificationVariableNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/IdentificationVariableNode.java @@ -1,162 +1,162 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.*; -import com.haulmont.cuba.core.sys.jpql.pointer.SimpleAttributePointer; -import com.haulmont.cuba.core.sys.jpql.pointer.NoPointer; -import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; -import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; -import com.haulmont.cuba.core.sys.jpql.model.*; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import javax.annotation.Nullable; -import java.util.Deque; -import java.util.List; - -public class IdentificationVariableNode extends BaseCustomNode { - private String variableName; - private String effectiveEntityName; - - private IdentificationVariableNode(Token token, String variableName) { - super(token); - this.variableName = variableName; - } - - public IdentificationVariableNode(int type, String variableName) { - this(new CommonToken(type, ""), variableName); - } - - public String getVariableName() { - return variableName; - } - - public void identifyVariableEntity( - DomainModel model, - Deque stack, - List invalidIdVarNodes) { - List children = getChildren(); - - if (variableName == null) { - invalidIdVarNodes.add(new ErrorRec(this, "No entity variable name")); - return; - } - - if (children == null) { - invalidIdVarNodes.add(new ErrorRec(this, "Null children")); - return; - } - - if (children.size() != 1) { - invalidIdVarNodes.add(new ErrorRec(this, "Number of children not equals 1")); - return; - } - - if (children.get(0) instanceof CommonErrorNode) { - invalidIdVarNodes.add(new ErrorRec(this, "Child 0 is an error node")); - return; - } - - CommonTree child0 = (CommonTree) children.get(0); - String variableName = getVariableName(); - - if (child0 instanceof QueryNode) { - QueryVariableContext queryVC; - do { - queryVC = stack.removeLast(); - } while (!queryVC.isPropagateVariablesUpstairs()); - deductFields(queryVC, child0, model); - stack.peekLast().addEntityVariable(variableName, queryVC.getEntity()); - } else { - if (variableName != null) { - try { - String entityName = child0.token.getText(); - JpqlEntityModel entity = model.getEntityByName(entityName); - effectiveEntityName = entity.getName(); - stack.peekLast().addEntityVariable(variableName, entity); - } catch (UnknownEntityNameException e) { - stack.peekLast().addEntityVariable(variableName, NoJpqlEntityModel.getInstance()); - } - } - } - } - - public void deductFields(QueryVariableContext queryVC, CommonTree node, DomainModel model) { - List children = node.getChildren(); - CommonTree T_SELECTED_ITEMS_NODE = (CommonTree) children.get(0); - for (Object o : T_SELECTED_ITEMS_NODE.getChildren()) { - o = ((SelectedItemNode) o).getChild(0); - if (!(o instanceof PathNode)) { - throw new RuntimeException("Not a path node"); - } - - PathNode pathNode = (PathNode) o; - Pointer pointer = pathNode.resolvePointer(model, queryVC); - - if (pointer instanceof NoPointer) { - queryVC.setEntity(NoJpqlEntityModel.getInstance()); - return; - } - - if (pointer instanceof SimpleAttributePointer) { - SimpleAttributePointer saPointer = (SimpleAttributePointer) pointer; - queryVC.getEntity().addAttributeCopy(saPointer.getAttribute()); - } else if (pointer instanceof EntityPointer) { - if (T_SELECTED_ITEMS_NODE.getChildren().size() != 1) { - //todo implement - throw new UnsupportedOperationException("Unimplemented variant with returned array"); - } else { - queryVC.setEntity(((EntityPointer) pointer).getEntity()); - } - } - } - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + "Variable: " + variableName; - } - - @Override - public Tree dupNode() { - IdentificationVariableNode result = new IdentificationVariableNode(token, variableName); - dupChildren(result); - return result; - } - - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - sb.appendSpace(); - sb.appendString(variableName); - return this; - } - - public String getEntityNameFromQuery() { - return getChild(0).getText(); - } - - @Nullable - public String getEffectiveEntityName() { - return effectiveEntityName; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.*; +import com.haulmont.cuba.core.sys.jpql.pointer.SimpleAttributePointer; +import com.haulmont.cuba.core.sys.jpql.pointer.NoPointer; +import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; +import com.haulmont.cuba.core.sys.jpql.pointer.EntityPointer; +import com.haulmont.cuba.core.sys.jpql.model.*; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import javax.annotation.Nullable; +import java.util.Deque; +import java.util.List; + +public class IdentificationVariableNode extends BaseCustomNode { + private String variableName; + private String effectiveEntityName; + + private IdentificationVariableNode(Token token, String variableName) { + super(token); + this.variableName = variableName; + } + + public IdentificationVariableNode(int type, String variableName) { + this(new CommonToken(type, ""), variableName); + } + + public String getVariableName() { + return variableName; + } + + public void identifyVariableEntity( + DomainModel model, + Deque stack, + List invalidIdVarNodes) { + List children = getChildren(); + + if (variableName == null) { + invalidIdVarNodes.add(new ErrorRec(this, "No entity variable name")); + return; + } + + if (children == null) { + invalidIdVarNodes.add(new ErrorRec(this, "Null children")); + return; + } + + if (children.size() != 1) { + invalidIdVarNodes.add(new ErrorRec(this, "Number of children not equals 1")); + return; + } + + if (children.get(0) instanceof CommonErrorNode) { + invalidIdVarNodes.add(new ErrorRec(this, "Child 0 is an error node")); + return; + } + + CommonTree child0 = (CommonTree) children.get(0); + String variableName = getVariableName(); + + if (child0 instanceof QueryNode) { + QueryVariableContext queryVC; + do { + queryVC = stack.removeLast(); + } while (!queryVC.isPropagateVariablesUpstairs()); + deductFields(queryVC, child0, model); + stack.peekLast().addEntityVariable(variableName, queryVC.getEntity()); + } else { + if (variableName != null) { + try { + String entityName = child0.token.getText(); + JpqlEntityModel entity = model.getEntityByName(entityName); + effectiveEntityName = entity.getName(); + stack.peekLast().addEntityVariable(variableName, entity); + } catch (UnknownEntityNameException e) { + stack.peekLast().addEntityVariable(variableName, NoJpqlEntityModel.getInstance()); + } + } + } + } + + public void deductFields(QueryVariableContext queryVC, CommonTree node, DomainModel model) { + List children = node.getChildren(); + CommonTree T_SELECTED_ITEMS_NODE = (CommonTree) children.get(0); + for (Object o : T_SELECTED_ITEMS_NODE.getChildren()) { + o = ((SelectedItemNode) o).getChild(0); + if (!(o instanceof PathNode)) { + throw new RuntimeException("Not a path node"); + } + + PathNode pathNode = (PathNode) o; + Pointer pointer = pathNode.resolvePointer(model, queryVC); + + if (pointer instanceof NoPointer) { + queryVC.setEntity(NoJpqlEntityModel.getInstance()); + return; + } + + if (pointer instanceof SimpleAttributePointer) { + SimpleAttributePointer saPointer = (SimpleAttributePointer) pointer; + queryVC.getEntity().addAttributeCopy(saPointer.getAttribute()); + } else if (pointer instanceof EntityPointer) { + if (T_SELECTED_ITEMS_NODE.getChildren().size() != 1) { + //todo implement + throw new UnsupportedOperationException("Unimplemented variant with returned array"); + } else { + queryVC.setEntity(((EntityPointer) pointer).getEntity()); + } + } + } + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + "Variable: " + variableName; + } + + @Override + public Tree dupNode() { + IdentificationVariableNode result = new IdentificationVariableNode(token, variableName); + dupChildren(result); + return result; + } + + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + sb.appendSpace(); + sb.appendString(variableName); + return this; + } + + public String getEntityNameFromQuery() { + return getChild(0).getText(); + } + + @Nullable + public String getEffectiveEntityName() { + return effectiveEntityName; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/JoinVariableNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/JoinVariableNode.java index a316727db2..0e2af75e07 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/JoinVariableNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/JoinVariableNode.java @@ -1,100 +1,100 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import com.haulmont.cuba.core.sys.jpql.TreeToQuery; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; -import org.antlr.runtime.tree.TreeVisitor; - -import javax.annotation.Nullable; -import java.util.List; - -public class JoinVariableNode extends BaseJoinNode { - private String joinSpec; - - public JoinVariableNode(Token token, String joinSpec, String variableName) { - super(token, variableName); - this.joinSpec = joinSpec; - } - - public JoinVariableNode(int type, String joinSpec, String variableName) { - this(new CommonToken(type, ""), joinSpec, variableName); - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + "Join variable: " + variableName; - } - - @Override - public Tree dupNode() { - JoinVariableNode result = new JoinVariableNode(token, joinSpec, variableName); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - int childCount = getChildCount(); - if (childCount == 0) { - invalidNodes.add(new ErrorRec(this, "No children found")); - return null; - } - sb.appendSpace(); - sb.appendString(joinSpec); - sb.appendSpace(); - sb.appendString(toQuery(getChild(0))); - sb.appendSpace(); - sb.appendString(variableName); - if (childCount > 1) { - sb.appendSpace(); - sb.appendString("on"); - for (int idx = 1; idx < childCount; idx++) { - sb.appendSpace(); - sb.appendString(toQuery(getChild(idx))); - } - } - return null; - } - - @Nullable - public PathNode findPathNode() { - for (Object child : getChildren()) { - if (child instanceof PathNode) { - return (PathNode) child; - } - } - return null; - } - - public String getJoinSpec() { - return joinSpec; - } - - protected String toQuery(Tree tree) { - TreeVisitor visitor = new TreeVisitor(); - TreeToQuery treeToQuery = new TreeToQuery(); - visitor.visit(tree, treeToQuery); - return treeToQuery.getQueryString().trim(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import com.haulmont.cuba.core.sys.jpql.TreeToQuery; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; +import org.antlr.runtime.tree.TreeVisitor; + +import javax.annotation.Nullable; +import java.util.List; + +public class JoinVariableNode extends BaseJoinNode { + private String joinSpec; + + public JoinVariableNode(Token token, String joinSpec, String variableName) { + super(token, variableName); + this.joinSpec = joinSpec; + } + + public JoinVariableNode(int type, String joinSpec, String variableName) { + this(new CommonToken(type, ""), joinSpec, variableName); + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + "Join variable: " + variableName; + } + + @Override + public Tree dupNode() { + JoinVariableNode result = new JoinVariableNode(token, joinSpec, variableName); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + int childCount = getChildCount(); + if (childCount == 0) { + invalidNodes.add(new ErrorRec(this, "No children found")); + return null; + } + sb.appendSpace(); + sb.appendString(joinSpec); + sb.appendSpace(); + sb.appendString(toQuery(getChild(0))); + sb.appendSpace(); + sb.appendString(variableName); + if (childCount > 1) { + sb.appendSpace(); + sb.appendString("on"); + for (int idx = 1; idx < childCount; idx++) { + sb.appendSpace(); + sb.appendString(toQuery(getChild(idx))); + } + } + return null; + } + + @Nullable + public PathNode findPathNode() { + for (Object child : getChildren()) { + if (child instanceof PathNode) { + return (PathNode) child; + } + } + return null; + } + + public String getJoinSpec() { + return joinSpec; + } + + protected String toQuery(Tree tree) { + TreeVisitor visitor = new TreeVisitor(); + TreeToQuery treeToQuery = new TreeToQuery(); + visitor.visit(tree, treeToQuery); + return treeToQuery.getQueryString().trim(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByFieldNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByFieldNode.java index 809d3822ec..5c8306d8fc 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByFieldNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByFieldNode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.Tree; - -public class OrderByFieldNode extends BaseCustomNode { - private OrderByFieldNode(Token token) { - super(token); - } - - public OrderByFieldNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "ORDER BY FIELD"; - } - - @Override - public Tree dupNode() { - OrderByFieldNode result = new OrderByFieldNode(token); - dupChildren(result); - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.Tree; + +public class OrderByFieldNode extends BaseCustomNode { + private OrderByFieldNode(Token token) { + super(token); + } + + public OrderByFieldNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "ORDER BY FIELD"; + } + + @Override + public Tree dupNode() { + OrderByFieldNode result = new OrderByFieldNode(token); + dupChildren(result); + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByNode.java index 709b1bd580..ed28f4ec34 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/OrderByNode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.Tree; - -public class OrderByNode extends BaseCustomNode { - private OrderByNode(Token token) { - super(token); - } - - public OrderByNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "ORDER BY"; - } - - @Override - public Tree dupNode() { - OrderByNode result = new OrderByNode(token); - dupChildren(result); - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.Tree; + +public class OrderByNode extends BaseCustomNode { + private OrderByNode(Token token) { + super(token); + } + + public OrderByNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "ORDER BY"; + } + + @Override + public Tree dupNode() { + OrderByNode result = new OrderByNode(token); + dupChildren(result); + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/ParameterNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/ParameterNode.java index bb13a1bc4e..6b37b245d0 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/ParameterNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/ParameterNode.java @@ -1,77 +1,77 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class ParameterNode extends BaseCustomNode { - - private ParameterNode(Token token) { - super(token); - } - - public ParameterNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return ""; - } - - @Override - public Tree dupNode() { - ParameterNode result = new ParameterNode(token); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - if (getChildren().size() == 2) { - String child0Text = getChild(0).getText(); - String child1Text = getChild(1).getText(); - if (":".equals(child0Text) || "?".equals(child0Text)) { - sb.appendString(child0Text); - sb.appendString(child1Text); - return null; - } - } - - return super.treeToQueryPre(sb, invalidNodes); - } - - public boolean isNamed() { - return getChild(0).getText().charAt(0) == ':'; - } - - public boolean isIndexed() { - return getChild(0).getText().equals("?"); - } - - public String getParameterReference() { - return isIndexed() ? getChild(1).getText() : getChild(0).getText().substring(1); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class ParameterNode extends BaseCustomNode { + + private ParameterNode(Token token) { + super(token); + } + + public ParameterNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return ""; + } + + @Override + public Tree dupNode() { + ParameterNode result = new ParameterNode(token); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + if (getChildren().size() == 2) { + String child0Text = getChild(0).getText(); + String child1Text = getChild(1).getText(); + if (":".equals(child0Text) || "?".equals(child0Text)) { + sb.appendString(child0Text); + sb.appendString(child1Text); + return null; + } + } + + return super.treeToQueryPre(sb, invalidNodes); + } + + public boolean isNamed() { + return getChild(0).getText().charAt(0) == ':'; + } + + public boolean isIndexed() { + return getChild(0).getText().equals("?"); + } + + public String getParameterReference() { + return isIndexed() ? getChild(1).getText() : getChild(0).getText().substring(1); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/PathNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/PathNode.java index 9c2b5ac48b..c77fd2e603 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/PathNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/PathNode.java @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.*; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; - -import java.util.Collections; -import java.util.List; - -public class PathNode extends BaseCustomNode { - private String entityVariableName; - - public PathNode(Token token, String entityVariableName) { - super(token); - this.entityVariableName = entityVariableName; - } - - public PathNode(int type, String entityVariableName) { - this(new CommonToken(type, ""), entityVariableName); - } - - public String getEntityVariableName() { - return entityVariableName; - } - - @Override - public PathNode dupNode() { - PathNode result = new PathNode(token, entityVariableName); - dupChildren(result); - return result; - } - - public Pointer resolvePointer(DomainModel model, QueryVariableContext queryVC) { - return createEntityPath().resolvePointer(model, queryVC); - } - - public List resolveTransitionalPointers(DomainModel model, QueryVariableContext queryVC) { - return createEntityPath().resolveTransitionalPointers(model, queryVC); - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + "Path entity variable: " + entityVariableName; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - sb.appendString(asPathString()); - return null; - } - - public String asPathString() { - return asPathString('.'); - } - - public String asPathString(char separator) { - String result = ""; - result += entityVariableName; - if (children != null) { - for (Object child : children) { - result += separator + child.toString(); - } - } - return result; - } - - public void renameVariableTo(String newVariableName) { - entityVariableName = newVariableName; - } - - public void addDefaultChildren(String fieldPath) { - String[] strings = fieldPath.split("\\."); - for (String string : strings) { - addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, string))); - } - } - - public void addDefaultChild(String field) { - addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, field))); - } - - protected EntityPath createEntityPath() { - List treeItems = getChildren(); - if (treeItems == null) { - treeItems = Collections.emptyList(); - } - String[] parts = new String[treeItems.size()]; - for (int i = 0; i < treeItems.size(); i++) { - CommonTree treeItem = (CommonTree) treeItems.get(i); - parts[i] = treeItem.getText(); - } - - EntityPath path = new EntityPath(); - path.topEntityVariableName = entityVariableName; - path.lastEntityFieldPattern = null; - path.traversedFields = parts; - return path; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.*; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.pointer.Pointer; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; + +import java.util.Collections; +import java.util.List; + +public class PathNode extends BaseCustomNode { + private String entityVariableName; + + public PathNode(Token token, String entityVariableName) { + super(token); + this.entityVariableName = entityVariableName; + } + + public PathNode(int type, String entityVariableName) { + this(new CommonToken(type, ""), entityVariableName); + } + + public String getEntityVariableName() { + return entityVariableName; + } + + @Override + public PathNode dupNode() { + PathNode result = new PathNode(token, entityVariableName); + dupChildren(result); + return result; + } + + public Pointer resolvePointer(DomainModel model, QueryVariableContext queryVC) { + return createEntityPath().resolvePointer(model, queryVC); + } + + public List resolveTransitionalPointers(DomainModel model, QueryVariableContext queryVC) { + return createEntityPath().resolveTransitionalPointers(model, queryVC); + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + "Path entity variable: " + entityVariableName; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + sb.appendString(asPathString()); + return null; + } + + public String asPathString() { + return asPathString('.'); + } + + public String asPathString(char separator) { + String result = ""; + result += entityVariableName; + if (children != null) { + for (Object child : children) { + result += separator + child.toString(); + } + } + return result; + } + + public void renameVariableTo(String newVariableName) { + entityVariableName = newVariableName; + } + + public void addDefaultChildren(String fieldPath) { + String[] strings = fieldPath.split("\\."); + for (String string : strings) { + addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, string))); + } + } + + public void addDefaultChild(String field) { + addChild(new CommonTree(new CommonToken(JPA2Lexer.WORD, field))); + } + + protected EntityPath createEntityPath() { + List treeItems = getChildren(); + if (treeItems == null) { + treeItems = Collections.emptyList(); + } + String[] parts = new String[treeItems.size()]; + for (int i = 0; i < treeItems.size(); i++) { + CommonTree treeItem = (CommonTree) treeItems.get(i); + parts[i] = treeItem.getText(); + } + + EntityPath path = new EntityPath(); + path.topEntityVariableName = entityVariableName; + path.lastEntityFieldPattern = null; + path.traversedFields = parts; + return path; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/QueryNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/QueryNode.java index 4b1fb5f630..49eb172d5d 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/QueryNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/QueryNode.java @@ -1,78 +1,78 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class QueryNode extends BaseCustomNode { - private Token lastToken; - - private QueryNode(Token token, Token lastToken) { - super(token); - this.lastToken = lastToken; - } - - public QueryNode(int type, Token token) { - this(token, null); - } - - public QueryNode(int type, Token token, Token lastToken) { - this(token, lastToken); - } - - public boolean contains(int caret) { - return lastToken == null || - caret >= token.getCharPositionInLine() && (caret - lastToken.getCharPositionInLine()) <= lastToken.getText().length(); - - - } - - @Override - public Tree dupNode() { - QueryNode result = new QueryNode(token, lastToken); - dupChildren(result); - return result; - } - - @Override - public String toStringTree() { - return super.toStringTree(); - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - sb.appendString(getText()); - return this; - } - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - if (parent != null) { - if (' ' == sb.getLast()) - sb.deleteLast(); - sb.appendString(") "); - } - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class QueryNode extends BaseCustomNode { + private Token lastToken; + + private QueryNode(Token token, Token lastToken) { + super(token); + this.lastToken = lastToken; + } + + public QueryNode(int type, Token token) { + this(token, null); + } + + public QueryNode(int type, Token token, Token lastToken) { + this(token, lastToken); + } + + public boolean contains(int caret) { + return lastToken == null || + caret >= token.getCharPositionInLine() && (caret - lastToken.getCharPositionInLine()) <= lastToken.getText().length(); + + + } + + @Override + public Tree dupNode() { + QueryNode result = new QueryNode(token, lastToken); + dupChildren(result); + return result; + } + + @Override + public String toStringTree() { + return super.toStringTree(); + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + sb.appendString(getText()); + return this; + } + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + if (parent != null) { + if (' ' == sb.getLast()) + sb.deleteLast(); + sb.appendString(") "); + } + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemNode.java index cc5ba0d8b2..d1f099e73a 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemNode.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class SelectedItemNode extends BaseCustomNode { - private SelectedItemNode(Token token) { - super(token); - } - - public SelectedItemNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "SELECTED_ITEM"; - } - - @Override - public Tree dupNode() { - SelectedItemNode result = new SelectedItemNode(token); - dupChildren(result); - return result; - } - - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - CommonTree prevNode = getPrevNode(); - if (prevNode != null && prevNode instanceof SelectedItemNode) { - sb.appendString(", "); - } else { - sb.appendSpace(); - } - return super.treeToQueryPre(sb, invalidNodes); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class SelectedItemNode extends BaseCustomNode { + private SelectedItemNode(Token token) { + super(token); + } + + public SelectedItemNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "SELECTED_ITEM"; + } + + @Override + public Tree dupNode() { + SelectedItemNode result = new SelectedItemNode(token); + dupChildren(result); + return result; + } + + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + CommonTree prevNode = getPrevNode(); + if (prevNode != null && prevNode instanceof SelectedItemNode) { + sb.appendString(", "); + } else { + sb.appendSpace(); + } + return super.treeToQueryPre(sb, invalidNodes); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemsNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemsNode.java index 9274a0bab3..c6a84e18d7 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemsNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectedItemsNode.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.Tree; - -public class SelectedItemsNode extends BaseCustomNode { - private SelectedItemsNode(Token token) { - super(token); - } - - public SelectedItemsNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "SELECTED_ITEMS"; - } - - @Override - public Tree dupNode() { - SelectedItemsNode result = new SelectedItemsNode(token); - dupChildren(result); - return result; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.Tree; + +public class SelectedItemsNode extends BaseCustomNode { + private SelectedItemsNode(Token token) { + super(token); + } + + public SelectedItemsNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "SELECTED_ITEMS"; + } + + @Override + public Tree dupNode() { + SelectedItemsNode result = new SelectedItemsNode(token); + dupChildren(result); + return result; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectionSourceNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectionSourceNode.java index f6aba3966f..e1c68e3edd 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectionSourceNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SelectionSourceNode.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class SelectionSourceNode extends BaseCustomNode { - private SelectionSourceNode(Token token) { - super(token); - } - - public SelectionSourceNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "SELECTION_SOURCE"; - } - - @Override - public Tree dupNode() { - SelectionSourceNode result = new SelectionSourceNode(token); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - CommonTree prevNode = getPrevNode(); - if (prevNode != null && prevNode instanceof SelectionSourceNode) { - sb.appendString(", "); - } else { - sb.appendSpace(); - } - return super.treeToQueryPre(sb, invalidNodes); - } - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class SelectionSourceNode extends BaseCustomNode { + private SelectionSourceNode(Token token) { + super(token); + } + + public SelectionSourceNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "SELECTION_SOURCE"; + } + + @Override + public Tree dupNode() { + SelectionSourceNode result = new SelectionSourceNode(token); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + CommonTree prevNode = getPrevNode(); + if (prevNode != null && prevNode instanceof SelectionSourceNode) { + sb.appendString(", "); + } else { + sb.appendSpace(); + } + return super.treeToQueryPre(sb, invalidNodes); + } + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SimpleConditionNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SimpleConditionNode.java index b222f18ff1..1755cbb26b 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SimpleConditionNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/SimpleConditionNode.java @@ -1,59 +1,59 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class SimpleConditionNode extends BaseCustomNode { - private SimpleConditionNode(Token token) { - super(token); - } - - public SimpleConditionNode(int type) { - this(new CommonToken(type, "")); - } - - @Override - public String toString() { - return "SIMPLE_CONDITION"; - } - - @Override - public Tree dupNode() { - SimpleConditionNode result = new SimpleConditionNode(token); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - return super.treeToQueryPre(sb, invalidNodes); - } - - @Override - public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class SimpleConditionNode extends BaseCustomNode { + private SimpleConditionNode(Token token) { + super(token); + } + + public SimpleConditionNode(int type) { + this(new CommonToken(type, "")); + } + + @Override + public String toString() { + return "SIMPLE_CONDITION"; + } + + @Override + public Tree dupNode() { + SimpleConditionNode result = new SimpleConditionNode(token); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + return super.treeToQueryPre(sb, invalidNodes); + } + + @Override + public CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes) { + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/TreeToQueryCapable.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/TreeToQueryCapable.java index c3ea4559f9..8b303f7df4 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/TreeToQueryCapable.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/TreeToQueryCapable.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.tree.CommonTree; - -import java.util.List; - -public interface TreeToQueryCapable { - - CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes); - - CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.tree.CommonTree; + +import java.util.List; + +public interface TreeToQueryCapable { + + CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes); + + CommonTree treeToQueryPost(QueryBuilder sb, List invalidNodes); +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/WhereNode.java b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/WhereNode.java index b50026810d..9612f24936 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/WhereNode.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/jpql/tree/WhereNode.java @@ -1,59 +1,59 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql.tree; - -import com.haulmont.cuba.core.sys.jpql.ErrorRec; -import com.haulmont.cuba.core.sys.jpql.QueryBuilder; -import org.antlr.runtime.CommonToken; -import org.antlr.runtime.Token; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.Tree; - -import java.util.List; - -public class WhereNode extends BaseCustomNode { - private Token whereT; - - private WhereNode(Token token, Token whereT) { - super(token); - this.whereT = whereT; - } - - public WhereNode(int type, Token whereT) { - this(new CommonToken(type, ""), whereT); - } - - @Override - public String toString() { - return (token != null ? token.getText() : "") + whereT; - } - - @Override - public Tree dupNode() { - WhereNode result = new WhereNode(token, whereT); - dupChildren(result); - return result; - } - - @Override - public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { - sb.appendSpace(); - sb.appendString(whereT.getText()); - return this; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql.tree; + +import com.haulmont.cuba.core.sys.jpql.ErrorRec; +import com.haulmont.cuba.core.sys.jpql.QueryBuilder; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import java.util.List; + +public class WhereNode extends BaseCustomNode { + private Token whereT; + + private WhereNode(Token token, Token whereT) { + super(token); + this.whereT = whereT; + } + + public WhereNode(int type, Token whereT) { + this(new CommonToken(type, ""), whereT); + } + + @Override + public String toString() { + return (token != null ? token.getText() : "") + whereT; + } + + @Override + public Tree dupNode() { + WhereNode result = new WhereNode(token, whereT); + dupChildren(result); + return result; + } + + @Override + public CommonTree treeToQueryPre(QueryBuilder sb, List invalidNodes) { + sb.appendSpace(); + sb.appendString(whereT.getText()); + return this; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/logging/LogMdc.java b/modules/global/src/com/haulmont/cuba/core/sys/logging/LogMdc.java index b60e2db6bc..4d6eff3a0c 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/logging/LogMdc.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/logging/LogMdc.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.logging; - -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.core.sys.UserSessionFinder; -import com.haulmont.cuba.security.global.UserSession; -import org.slf4j.MDC; -import org.springframework.context.ApplicationContext; - -public class LogMdc { - - public static final String USER = "cubaUser"; - public static final String APPLICATION = "cubaApp"; - - public static void setup(SecurityContext securityContext) { - String userProp = AppContext.getProperty("cuba.logUserName"); - if (userProp == null || Boolean.valueOf(userProp)) { - if (securityContext != null) { - String user = securityContext.getUser(); - if (user == null) { - UserSession session = securityContext.getSession(); - if (session != null) - user = session.getUser().getLogin(); - else if (securityContext.getSessionId() != null) { - ApplicationContext applicationContext = AppContext.getApplicationContext(); - if (applicationContext.containsBean("cuba_UserSessionManager")) { - UserSessionFinder sessionFinder = (UserSessionFinder) applicationContext.getBean("cuba_UserSessionManager"); - session = sessionFinder.findSession(securityContext.getSessionId()); - if (session != null) { - user = session.getUser().getLogin(); - } - } - } - } - if (user != null) { - MDC.put(USER, "/" + user); - } - } else { - MDC.remove(USER); - } - } - - String applicationProp = AppContext.getProperty("cuba.logAppName"); - if (applicationProp == null || Boolean.valueOf(applicationProp)) { - if (securityContext != null) { - MDC.put(APPLICATION, "/" + AppContext.getProperty("cuba.webContextName")); - } else { - MDC.remove(APPLICATION); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.logging; + +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.core.sys.UserSessionFinder; +import com.haulmont.cuba.security.global.UserSession; +import org.slf4j.MDC; +import org.springframework.context.ApplicationContext; + +public class LogMdc { + + public static final String USER = "cubaUser"; + public static final String APPLICATION = "cubaApp"; + + public static void setup(SecurityContext securityContext) { + String userProp = AppContext.getProperty("cuba.logUserName"); + if (userProp == null || Boolean.valueOf(userProp)) { + if (securityContext != null) { + String user = securityContext.getUser(); + if (user == null) { + UserSession session = securityContext.getSession(); + if (session != null) + user = session.getUser().getLogin(); + else if (securityContext.getSessionId() != null) { + ApplicationContext applicationContext = AppContext.getApplicationContext(); + if (applicationContext.containsBean("cuba_UserSessionManager")) { + UserSessionFinder sessionFinder = (UserSessionFinder) applicationContext.getBean("cuba_UserSessionManager"); + session = sessionFinder.findSession(securityContext.getSessionId()); + if (session != null) { + user = session.getUser().getLogin(); + } + } + } + } + if (user != null) { + MDC.put(USER, "/" + user); + } + } else { + MDC.remove(USER); + } + } + + String applicationProp = AppContext.getProperty("cuba.logAppName"); + if (applicationProp == null || Boolean.valueOf(applicationProp)) { + if (securityContext != null) { + MDC.put(APPLICATION, "/" + AppContext.getProperty("cuba.webContextName")); + } else { + MDC.remove(APPLICATION); + } + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/persistence/CubaIsNullExpressionOperator.java b/modules/global/src/com/haulmont/cuba/core/sys/persistence/CubaIsNullExpressionOperator.java index fcc89d007e..a61ae90357 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/persistence/CubaIsNullExpressionOperator.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/persistence/CubaIsNullExpressionOperator.java @@ -1,59 +1,59 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.persistence; - -import org.eclipse.persistence.expressions.ExpressionOperator; -import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter; -import org.eclipse.persistence.internal.expressions.QueryKeyExpression; -import org.eclipse.persistence.internal.helper.ClassConstants; -import org.eclipse.persistence.internal.helper.CubaUtil; - -import java.io.IOException; -import java.util.Vector; - -public class CubaIsNullExpressionOperator extends ExpressionOperator { - - public CubaIsNullExpressionOperator() { - setType(ExpressionOperator.ComparisonOperator); - setSelector(ExpressionOperator.IsNull); - Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); - v.add("("); - v.add(" IS NULL)"); - printsAs(v); - bePrefix(); - printsJavaAs(".isNull()"); - setNodeClass(ClassConstants.FunctionExpression_Class); - } - - @Override - public void printCollection(Vector items, ExpressionSQLPrinter printer) { - if (items.size() == 1 - && items.get(0) instanceof QueryKeyExpression - && "deleteTs".equals(((QueryKeyExpression) items.get(0)).getName())) { - if (!CubaUtil.isSoftDeletion()) { - try { - printer.getWriter().write("(0=0)"); - return; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - super.printCollection(items, printer); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.persistence; + +import org.eclipse.persistence.expressions.ExpressionOperator; +import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter; +import org.eclipse.persistence.internal.expressions.QueryKeyExpression; +import org.eclipse.persistence.internal.helper.ClassConstants; +import org.eclipse.persistence.internal.helper.CubaUtil; + +import java.io.IOException; +import java.util.Vector; + +public class CubaIsNullExpressionOperator extends ExpressionOperator { + + public CubaIsNullExpressionOperator() { + setType(ExpressionOperator.ComparisonOperator); + setSelector(ExpressionOperator.IsNull); + Vector v = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); + v.add("("); + v.add(" IS NULL)"); + printsAs(v); + bePrefix(); + printsJavaAs(".isNull()"); + setNodeClass(ClassConstants.FunctionExpression_Class); + } + + @Override + public void printCollection(Vector items, ExpressionSQLPrinter printer) { + if (items.size() == 1 + && items.get(0) instanceof QueryKeyExpression + && "deleteTs".equals(((QueryKeyExpression) items.get(0)).getName())) { + if (!CubaUtil.isSoftDeletion()) { + try { + printer.getWriter().write("(0=0)"); + return; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + super.printCollection(items, printer); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocation.java b/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocation.java index 908f304674..b575bbf76e 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocation.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocation.java @@ -1,79 +1,79 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.remoting; - -import org.aopalliance.intercept.MethodInvocation; -import org.springframework.remoting.support.RemoteInvocation; - -import java.util.TimeZone; -import java.util.UUID; - -/** - * Encapsulates a remote invocation of a middleware service. - * Additionally transfers the current user session identifier and request scope locale (for anonymous sessions). - */ -public class CubaRemoteInvocation extends RemoteInvocation { - - private static final long serialVersionUID = 5460262566597755733L; - - private UUID sessionId; - private String locale; - private TimeZone timeZone; - private String address; - private String clientInfo; - - public CubaRemoteInvocation(MethodInvocation methodInvocation, UUID sessionId) { - super(methodInvocation); - this.sessionId = sessionId; - } - - public UUID getSessionId() { - return sessionId; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public String getLocale() { - return locale; - } - - public TimeZone getTimeZone() { - return timeZone; - } - - public void setTimeZone(TimeZone timeZone) { - this.timeZone = timeZone; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getClientInfo() { - return clientInfo; - } - - public void setClientInfo(String clientInfo) { - this.clientInfo = clientInfo; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.remoting; + +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.remoting.support.RemoteInvocation; + +import java.util.TimeZone; +import java.util.UUID; + +/** + * Encapsulates a remote invocation of a middleware service. + * Additionally transfers the current user session identifier and request scope locale (for anonymous sessions). + */ +public class CubaRemoteInvocation extends RemoteInvocation { + + private static final long serialVersionUID = 5460262566597755733L; + + private UUID sessionId; + private String locale; + private TimeZone timeZone; + private String address; + private String clientInfo; + + public CubaRemoteInvocation(MethodInvocation methodInvocation, UUID sessionId) { + super(methodInvocation); + this.sessionId = sessionId; + } + + public UUID getSessionId() { + return sessionId; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getLocale() { + return locale; + } + + public TimeZone getTimeZone() { + return timeZone; + } + + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getClientInfo() { + return clientInfo; + } + + public void setClientInfo(String clientInfo) { + this.clientInfo = clientInfo; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationFactory.java b/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationFactory.java index a43e1cd491..466923cae8 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationFactory.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/remoting/CubaRemoteInvocationFactory.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.core.sys.SecurityContext; -import com.haulmont.cuba.security.global.ClientBasedSession; -import com.haulmont.cuba.security.global.UserSession; -import org.aopalliance.intercept.MethodInvocation; -import org.springframework.remoting.support.RemoteInvocation; -import org.springframework.remoting.support.RemoteInvocationFactory; - -public class CubaRemoteInvocationFactory implements RemoteInvocationFactory { - - @Override - public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { - SecurityContext securityContext = AppContext.getSecurityContext(); - - CubaRemoteInvocation remoteInvocation = new CubaRemoteInvocation(methodInvocation, - securityContext == null ? null : securityContext.getSessionId()); - - if (securityContext != null) { - UserSession session = securityContext.getSession(); - - if (session instanceof ClientBasedSession && ((ClientBasedSession) session).hasRequestScopedInfo()) { - remoteInvocation.setLocale(session.getLocale() != null ? session.getLocale().toLanguageTag() : null); - remoteInvocation.setTimeZone(session.getTimeZone()); - remoteInvocation.setAddress(session.getAddress()); - remoteInvocation.setClientInfo(session.getClientInfo()); - } - } - - return remoteInvocation; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.core.sys.SecurityContext; +import com.haulmont.cuba.security.global.ClientBasedSession; +import com.haulmont.cuba.security.global.UserSession; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.remoting.support.RemoteInvocation; +import org.springframework.remoting.support.RemoteInvocationFactory; + +public class CubaRemoteInvocationFactory implements RemoteInvocationFactory { + + @Override + public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { + SecurityContext securityContext = AppContext.getSecurityContext(); + + CubaRemoteInvocation remoteInvocation = new CubaRemoteInvocation(methodInvocation, + securityContext == null ? null : securityContext.getSessionId()); + + if (securityContext != null) { + UserSession session = securityContext.getSession(); + + if (session instanceof ClientBasedSession && ((ClientBasedSession) session).hasRequestScopedInfo()) { + remoteInvocation.setLocale(session.getLocale() != null ? session.getLocale().toLanguageTag() : null); + remoteInvocation.setTimeZone(session.getTimeZone()); + remoteInvocation.setAddress(session.getAddress()); + remoteInvocation.setClientInfo(session.getClientInfo()); + } + } + + return remoteInvocation; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/remoting/HttpServiceProxy.java b/modules/global/src/com/haulmont/cuba/core/sys/remoting/HttpServiceProxy.java index 0def1ef32d..a5e6b79569 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/remoting/HttpServiceProxy.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/remoting/HttpServiceProxy.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.global.RemoteException; -import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; -import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; -import org.springframework.remoting.support.RemoteInvocationResult; -import org.springframework.remoting.support.RemoteInvocationUtils; - -import java.lang.reflect.InvocationTargetException; - -public class HttpServiceProxy extends HttpInvokerProxyFactoryBean { - - public HttpServiceProxy(ServerSelector selector) { - setRemoteInvocationFactory(new CubaRemoteInvocationFactory()); - - ClusteredHttpInvokerRequestExecutor executor = new ClusteredHttpInvokerRequestExecutor(selector); - executor.setBeanClassLoader(getBeanClassLoader()); - setHttpInvokerRequestExecutor(executor); - } - - @Override - protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable { - Throwable throwable = result.getException(); - if (throwable != null) { - if (throwable instanceof InvocationTargetException) - throwable = ((InvocationTargetException) throwable).getTargetException(); - if (throwable instanceof RemoteException) { - Exception exception = ((RemoteException) throwable).getFirstCauseException(); - // This is a checked exception declared in a service method - // or runtime exception supported by client - if (exception != null) { - RemoteInvocationUtils.fillInClientStackTraceIfPossible(exception); - throw exception; - } - } - } - return super.recreateRemoteInvocationResult(result); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.global.RemoteException; +import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; +import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; +import org.springframework.remoting.support.RemoteInvocationResult; +import org.springframework.remoting.support.RemoteInvocationUtils; + +import java.lang.reflect.InvocationTargetException; + +public class HttpServiceProxy extends HttpInvokerProxyFactoryBean { + + public HttpServiceProxy(ServerSelector selector) { + setRemoteInvocationFactory(new CubaRemoteInvocationFactory()); + + ClusteredHttpInvokerRequestExecutor executor = new ClusteredHttpInvokerRequestExecutor(selector); + executor.setBeanClassLoader(getBeanClassLoader()); + setHttpInvokerRequestExecutor(executor); + } + + @Override + protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable { + Throwable throwable = result.getException(); + if (throwable != null) { + if (throwable instanceof InvocationTargetException) + throwable = ((InvocationTargetException) throwable).getTargetException(); + if (throwable instanceof RemoteException) { + Exception exception = ((RemoteException) throwable).getFirstCauseException(); + // This is a checked exception declared in a service method + // or runtime exception supported by client + if (exception != null) { + RemoteInvocationUtils.fillInClientStackTraceIfPossible(exception); + throw exception; + } + } + } + return super.recreateRemoteInvocationResult(result); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeService.java b/modules/global/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeService.java index 1032ddff1a..82e4d40232 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeService.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/remoting/LocalFileExchangeService.java @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.entity.FileDescriptor; -import com.haulmont.cuba.core.global.FileStorageException; - -import java.io.InputStream; - -/** - * The service might be used for work with file storage, when you use local service invocation - * (web and core are deployed to same JVM, or web and core are packaged to single WAR file) - */ -public interface LocalFileExchangeService { - String NAME = "cuba_LocalFileExchangeService"; - - void uploadFile(@BypassSerialization InputStream inputStream, FileDescriptor fileDescriptor) throws FileStorageException; - - @BypassSerialization - InputStream downloadFile(FileDescriptor fileDescriptor) throws FileStorageException; +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.entity.FileDescriptor; +import com.haulmont.cuba.core.global.FileStorageException; + +import java.io.InputStream; + +/** + * The service might be used for work with file storage, when you use local service invocation + * (web and core are deployed to same JVM, or web and core are packaged to single WAR file) + */ +public interface LocalFileExchangeService { + String NAME = "cuba_LocalFileExchangeService"; + + void uploadFile(@BypassSerialization InputStream inputStream, FileDescriptor fileDescriptor) throws FileStorageException; + + @BypassSerialization + InputStream downloadFile(FileDescriptor fileDescriptor) throws FileStorageException; } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/remoting/RemoteProxyBeanCreator.java b/modules/global/src/com/haulmont/cuba/core/sys/remoting/RemoteProxyBeanCreator.java index 882c727788..f74de375db 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/remoting/RemoteProxyBeanCreator.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/remoting/RemoteProxyBeanCreator.java @@ -1,103 +1,103 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.remoting; - -import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -import java.util.Map; - -public class RemoteProxyBeanCreator implements BeanFactoryPostProcessor, ApplicationContextAware { - - private Logger log = LoggerFactory.getLogger(RemoteProxyBeanCreator.class); - - protected Map services; - - protected Map substitutions; - - protected ServerSelector serverSelector; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - } - - public void setRemoteServices(Map services) { - this.services = services; - } - - public void setSubstitutions(Map substitutions) { - this.substitutions = substitutions; - } - - public void setServerSelector(ServerSelector serverSelector) { - this.serverSelector = serverSelector; - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - log.info("Configuring remote proxy beans: " + services.keySet()); - - BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; - - for (Map.Entry entry : services.entrySet()) { - String name = entry.getKey(); - - String serviceUrl = name; - String serviceInterface = entry.getValue(); - BeanDefinition definition = new RootBeanDefinition(HttpServiceProxy.class); - definition.getConstructorArgumentValues().addIndexedArgumentValue(0, serverSelector); - MutablePropertyValues propertyValues = definition.getPropertyValues(); - propertyValues.add("serviceUrl", serviceUrl); - propertyValues.add("serviceInterface", serviceInterface); - registry.registerBeanDefinition(name, definition); - - log.debug("Configured remote proxy bean " + name + " of type " + serviceInterface + ", bound to " + serviceUrl); - } - - processSubstitutions(beanFactory); - } - - protected void processSubstitutions(ConfigurableListableBeanFactory beanFactory) { - if (substitutions != null) { - BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; - - for (Map.Entry entry : substitutions.entrySet()) { - // replace bean with substitution bean - if (beanFactory.containsBean(entry.getKey())) { - String beanName = entry.getKey(); - String beanClass = entry.getValue(); - - BeanDefinition definition = new RootBeanDefinition(beanClass); - MutablePropertyValues propertyValues = definition.getPropertyValues(); - propertyValues.add("substitutedBean", beanFactory.getBean(beanName)); - registry.registerBeanDefinition(beanName, definition); - } - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.remoting; + +import com.haulmont.cuba.core.sys.remoting.discovery.ServerSelector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import java.util.Map; + +public class RemoteProxyBeanCreator implements BeanFactoryPostProcessor, ApplicationContextAware { + + private Logger log = LoggerFactory.getLogger(RemoteProxyBeanCreator.class); + + protected Map services; + + protected Map substitutions; + + protected ServerSelector serverSelector; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + } + + public void setRemoteServices(Map services) { + this.services = services; + } + + public void setSubstitutions(Map substitutions) { + this.substitutions = substitutions; + } + + public void setServerSelector(ServerSelector serverSelector) { + this.serverSelector = serverSelector; + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + log.info("Configuring remote proxy beans: " + services.keySet()); + + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + + for (Map.Entry entry : services.entrySet()) { + String name = entry.getKey(); + + String serviceUrl = name; + String serviceInterface = entry.getValue(); + BeanDefinition definition = new RootBeanDefinition(HttpServiceProxy.class); + definition.getConstructorArgumentValues().addIndexedArgumentValue(0, serverSelector); + MutablePropertyValues propertyValues = definition.getPropertyValues(); + propertyValues.add("serviceUrl", serviceUrl); + propertyValues.add("serviceInterface", serviceInterface); + registry.registerBeanDefinition(name, definition); + + log.debug("Configured remote proxy bean " + name + " of type " + serviceInterface + ", bound to " + serviceUrl); + } + + processSubstitutions(beanFactory); + } + + protected void processSubstitutions(ConfigurableListableBeanFactory beanFactory) { + if (substitutions != null) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + + for (Map.Entry entry : substitutions.entrySet()) { + // replace bean with substitution bean + if (beanFactory.containsBean(entry.getKey())) { + String beanName = entry.getKey(); + String beanClass = entry.getValue(); + + BeanDefinition definition = new RootBeanDefinition(beanClass); + MutablePropertyValues propertyValues = definition.getPropertyValues(); + propertyValues.add("substitutedBean", beanFactory.getBean(beanName)); + registry.registerBeanDefinition(beanName, definition); + } + } + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/serialization/KryoSerialization.java b/modules/global/src/com/haulmont/cuba/core/sys/serialization/KryoSerialization.java index e2a7b9320a..a0fb370faf 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/serialization/KryoSerialization.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/serialization/KryoSerialization.java @@ -1,376 +1,376 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.serialization; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.KryoException; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.CollectionSerializer; -import com.esotericsoftware.kryo.serializers.FieldSerializer; -import com.esotericsoftware.kryo.serializers.JavaSerializer; -import com.esotericsoftware.kryo.util.ObjectMap; -import com.esotericsoftware.kryo.util.Util; -import com.esotericsoftware.reflectasm.ConstructorAccess; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.HashMultimap; -import com.haulmont.chile.core.model.impl.MetaClassImpl; -import com.haulmont.chile.core.model.impl.MetaPropertyImpl; -import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import de.javakaffee.kryoserializers.*; -import de.javakaffee.kryoserializers.cglib.CGLibProxySerializer; -import de.javakaffee.kryoserializers.guava.ImmutableListSerializer; -import de.javakaffee.kryoserializers.guava.ImmutableMapSerializer; -import de.javakaffee.kryoserializers.guava.ImmutableMultimapSerializer; -import de.javakaffee.kryoserializers.guava.ImmutableSetSerializer; -import org.apache.commons.lang.ClassUtils; -import org.eclipse.persistence.indirection.IndirectCollection; -import org.eclipse.persistence.indirection.IndirectContainer; -import org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder; -import org.eclipse.persistence.internal.indirection.jdk8.IndirectList; -import org.eclipse.persistence.internal.indirection.jdk8.IndirectMap; -import org.eclipse.persistence.internal.indirection.jdk8.IndirectSet; -import org.objenesis.instantiator.ObjectInstantiator; -import org.objenesis.strategy.InstantiatorStrategy; -import org.objenesis.strategy.StdInstantiatorStrategy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.stream.Collectors; - -/** - * The serialization implementation using Kryo serialization - */ -public class KryoSerialization implements Serialization { - - protected static final Logger log = LoggerFactory.getLogger(KryoSerialization.class); - - protected static final List INCLUDED_VALUE_HOLDER_FIELDS = - Arrays.asList("value", "isInstantiated", "mapping", "sourceAttributeName", "relationshipSourceObject"); - - - protected boolean onlySerializable = true; - protected final ThreadLocal kryos = new ThreadLocal() { - @Override - protected Kryo initialValue() { - return newKryoInstance(); - } - }; - - public KryoSerialization() { - } - - public KryoSerialization(boolean onlySerializable) { - this.onlySerializable = onlySerializable; - } - - protected Kryo newKryoInstance() { - Kryo kryo = new Kryo(); - kryo.setInstantiatorStrategy(new CubaInstantiatorStrategy()); - if (onlySerializable) { - kryo.setDefaultSerializer(CubaFieldSerializer.class); - } - - //To work properly must itself be loaded by the application classloader (i.e. by classloader capable of loading - //all the other application classes). For web application it means placing this class inside webapp folder. - kryo.setClassLoader(KryoSerialization.class.getClassLoader()); - - kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer()); - kryo.register(Collections.EMPTY_LIST.getClass(), new CollectionsEmptyListSerializer()); - kryo.register(Collections.EMPTY_MAP.getClass(), new CollectionsEmptyMapSerializer()); - kryo.register(Collections.EMPTY_SET.getClass(), new CollectionsEmptySetSerializer()); - kryo.register(Collections.singletonList("").getClass(), new CollectionsSingletonListSerializer()); - kryo.register(Collections.singleton("").getClass(), new CollectionsSingletonSetSerializer()); - kryo.register(Collections.singletonMap("", "").getClass(), new CollectionsSingletonMapSerializer()); - kryo.register(BitSet.class, new BitSetSerializer()); - kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer()); - kryo.register(InvocationHandler.class, new JdkProxySerializer()); - UnmodifiableCollectionsSerializer.registerSerializers(kryo); - SynchronizedCollectionsSerializer.registerSerializers(kryo); - - kryo.register(CGLibProxySerializer.CGLibProxyMarker.class, new CGLibProxySerializer()); - ImmutableListSerializer.registerSerializers(kryo); - ImmutableSetSerializer.registerSerializers(kryo); - ImmutableMapSerializer.registerSerializers(kryo); - ImmutableMultimapSerializer.registerSerializers(kryo); - kryo.register(IndirectList.class, new IndirectContainerSerializer()); - kryo.register(IndirectMap.class, new IndirectContainerSerializer()); - kryo.register(IndirectSet.class, new IndirectContainerSerializer()); - - kryo.register(org.eclipse.persistence.indirection.IndirectList.class, new IndirectContainerSerializer()); - kryo.register(org.eclipse.persistence.indirection.IndirectMap.class, new IndirectContainerSerializer()); - kryo.register(org.eclipse.persistence.indirection.IndirectSet.class, new IndirectContainerSerializer()); - - //classes with custom serialization methods - kryo.register(HashMultimap.class, new CubaJavaSerializer()); - kryo.register(ArrayListMultimap.class, new CubaJavaSerializer()); - kryo.register(MetaClassImpl.class, new CubaJavaSerializer()); - kryo.register(MetaPropertyImpl.class, new CubaJavaSerializer()); - kryo.register(UnitOfWorkQueryValueHolder.class, new UnitOfWorkQueryValueHolderSerializer(kryo)); - - return kryo; - } - - @Override - @SuppressWarnings("finally") - public void serialize(Object object, OutputStream os) { - try (Output output = new CubaOutput(os)) { - if (object instanceof BaseGenericIdEntity - && BaseEntityInternalAccess.isManaged((BaseGenericIdEntity) object)) { - BaseEntityInternalAccess.setDetached((BaseGenericIdEntity) object, true); - } - kryos.get().writeClassAndObject(output, object); - } - } - - @Override - public Object deserialize(InputStream is) { - try (Input input = new Input(is)) { - return kryos.get().readClassAndObject(input); - } - } - - @Override - public byte[] serialize(Object object) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - serialize(object, bos); - return bos.toByteArray(); - } - - @Override - public Object deserialize(byte[] bytes) { - if (bytes == null) { - return null; - } - - return deserialize(new ByteArrayInputStream(bytes)); - } - - public Object copy(Object object) { - if (object == null) { - return null; - } - return kryos.get().copy(object); - } - - public static class IndirectContainerSerializer extends CollectionSerializer { - @Override - public void write(Kryo kryo, Output output, Collection collection) { - boolean isNotInstantiated = collection instanceof IndirectContainer - && !((IndirectContainer) collection).isInstantiated(); - output.writeBoolean(isNotInstantiated); - if (!isNotInstantiated) { - super.write(kryo, output, collection); - } - } - - @Override - public Collection read(Kryo kryo, Input input, Class type) { - boolean isNotInstantiated = input.readBoolean(); - if (!isNotInstantiated) { - return super.read(kryo, input, type); - } else { - IndirectCollection indirectCollection = (IndirectCollection) kryo.newInstance((Class) type); - indirectCollection.setValueHolder(new UnfetchedValueHolder()); - return (Collection) indirectCollection; - } - } - } - - public static class CubaJavaSerializer extends JavaSerializer { - @Override - public Object read(Kryo kryo, Input input, Class type) { - try { - ObjectMap graphContext = kryo.getGraphContext(); - ObjectInputStream objectStream = (ObjectInputStream) graphContext.get(this); - if (objectStream == null) { - objectStream = new ObjectInputStream(input) { - @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - return ClassUtils.getClass(KryoSerialization.class.getClassLoader(), desc.getName()); - } - }; - graphContext.put(this, objectStream); - } - return objectStream.readObject(); - } catch (Exception ex) { - throw new KryoException("Error during Java deserialization.", ex); - } - } - } - - public class UnitOfWorkQueryValueHolderSerializer extends KryoSerialization.CubaFieldSerializer { - - public UnitOfWorkQueryValueHolderSerializer(Kryo kryo) { - super(kryo, UnitOfWorkQueryValueHolder.class); - } - - @Override - protected void rebuildCachedFields(boolean minorRebuild) { - super.rebuildCachedFields(minorRebuild); - List excludedFields = Arrays.stream(getFields()) - .filter(cachedField -> !INCLUDED_VALUE_HOLDER_FIELDS.contains(cachedField.getField().getName())) - .collect(Collectors.toList()); - excludedFields.forEach(this::removeField); - } - - @Override - @SuppressWarnings("unchecked") - public void write(Kryo kryo, Output output, Object object) { - boolean isNotInstantiated = object instanceof UnitOfWorkQueryValueHolder - && !((UnitOfWorkQueryValueHolder) object).isInstantiated(); - output.writeBoolean(isNotInstantiated); - if (!isNotInstantiated) { - super.write(kryo, output, object); - } - } - - @Override - @SuppressWarnings("unchecked") - public Object read(Kryo kryo, Input input, Class type) { - boolean isNotInstantiated = input.readBoolean(); - if (!isNotInstantiated) { - return super.read(kryo, input, type); - } else { - return new UnfetchedWeavedAttributeValueHolder(); - } - } - } - - /** - * Strategy first tries to find and use a no-arg constructor and if it fails to do so, it should try to use - * {@link StdInstantiatorStrategy} as a fallback, because this one does not invoke any constructor at all. - * Strategy is a copy {@link Kryo.DefaultInstantiatorStrategy}, but if instantiation fails, use fallback to create object - */ - public static class CubaInstantiatorStrategy implements org.objenesis.strategy.InstantiatorStrategy { - private final InstantiatorStrategy fallbackStrategy = new StdInstantiatorStrategy(); - - @Override - public ObjectInstantiator newInstantiatorOf(Class type) { - // Use ReflectASM if the class is not a non-static member class. - Class enclosingType = type.getEnclosingClass(); - boolean isNonStaticMemberClass = enclosingType != null && type.isMemberClass() - && !Modifier.isStatic(type.getModifiers()); - if (!isNonStaticMemberClass) { - try { - final ConstructorAccess access = ConstructorAccess.get(type); - return () -> { - try { - return access.newInstance(); - } catch (Exception ex) { - if (log.isTraceEnabled()) { - log.trace("Unable instantiate class {}", Util.className(type), ex); - } - return fallbackStrategy.newInstantiatorOf(type).newInstance(); - } - }; - } catch (Exception ignored) { - } - } - // Reflection. - try { - Constructor ctor; - try { - ctor = type.getConstructor((Class[]) null); - } catch (Exception ex) { - ctor = type.getDeclaredConstructor((Class[]) null); - ctor.setAccessible(true); - } - final Constructor constructor = ctor; - return () -> { - try { - return constructor.newInstance(); - } catch (Exception ex) { - if (log.isTraceEnabled()) { - log.trace("Unable instantiate class {}", Util.className(type), ex); - } - return fallbackStrategy.newInstantiatorOf(type).newInstance(); - } - }; - } catch (Exception ignored) { - } - return fallbackStrategy.newInstantiatorOf(type); - } - } - - public static class CubaFieldSerializer extends FieldSerializer { - public CubaFieldSerializer(Kryo kryo, Class type) { - super(kryo, type); - } - - public CubaFieldSerializer(Kryo kryo, Class type, Class[] generics) { - super(kryo, type, generics); - } - - @Override - protected T create(Kryo kryo, Input input, Class type) { - checkIncorrectClass(type); - return super.create(kryo, input, type); - } - - @Override - public void write(Kryo kryo, Output output, T object) { - checkIncorrectObject(object); - super.write(kryo, output, object); - } - - @Override - public T read(Kryo kryo, Input input, Class type) { - checkIncorrectClass(type); - return super.read(kryo, input, type); - - } - - protected void checkIncorrectClass(Class type) { - if (type != null && !Serializable.class.isAssignableFrom(type)) { - throw new IllegalArgumentException(String.format("Class is not registered: %s\nNote: To register this class use: kryo.register(\"%s\".class);", - Util.className(type), Util.className(type))); - } - } - - protected void checkIncorrectObject(T object) { - if (object != null && !(object instanceof Serializable)) { - String className = Util.className(object.getClass()); - throw new IllegalArgumentException(String.format("Class is not registered: %s\nNote: To register this class use: kryo.register(\"%s\".class);", - className, className)); - } - } - } - - public static class CubaOutput extends Output { - - public CubaOutput(OutputStream outputStream) { - super(outputStream); - } - - @Override - public void close() { - //Prevent close stream. Stream closed only by: - //com.haulmont.cuba.core.sys.remoting.HttpServiceExporter, - //com.haulmont.cuba.core.sys.remoting.ClusteredHttpInvokerRequestExecutor() - //Only flush buffer to output stream - flush(); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.serialization; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.KryoException; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.kryo.serializers.CollectionSerializer; +import com.esotericsoftware.kryo.serializers.FieldSerializer; +import com.esotericsoftware.kryo.serializers.JavaSerializer; +import com.esotericsoftware.kryo.util.ObjectMap; +import com.esotericsoftware.kryo.util.Util; +import com.esotericsoftware.reflectasm.ConstructorAccess; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashMultimap; +import com.haulmont.chile.core.model.impl.MetaClassImpl; +import com.haulmont.chile.core.model.impl.MetaPropertyImpl; +import com.haulmont.cuba.core.entity.BaseEntityInternalAccess; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import de.javakaffee.kryoserializers.*; +import de.javakaffee.kryoserializers.cglib.CGLibProxySerializer; +import de.javakaffee.kryoserializers.guava.ImmutableListSerializer; +import de.javakaffee.kryoserializers.guava.ImmutableMapSerializer; +import de.javakaffee.kryoserializers.guava.ImmutableMultimapSerializer; +import de.javakaffee.kryoserializers.guava.ImmutableSetSerializer; +import org.apache.commons.lang.ClassUtils; +import org.eclipse.persistence.indirection.IndirectCollection; +import org.eclipse.persistence.indirection.IndirectContainer; +import org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder; +import org.eclipse.persistence.internal.indirection.jdk8.IndirectList; +import org.eclipse.persistence.internal.indirection.jdk8.IndirectMap; +import org.eclipse.persistence.internal.indirection.jdk8.IndirectSet; +import org.objenesis.instantiator.ObjectInstantiator; +import org.objenesis.strategy.InstantiatorStrategy; +import org.objenesis.strategy.StdInstantiatorStrategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.stream.Collectors; + +/** + * The serialization implementation using Kryo serialization + */ +public class KryoSerialization implements Serialization { + + protected static final Logger log = LoggerFactory.getLogger(KryoSerialization.class); + + protected static final List INCLUDED_VALUE_HOLDER_FIELDS = + Arrays.asList("value", "isInstantiated", "mapping", "sourceAttributeName", "relationshipSourceObject"); + + + protected boolean onlySerializable = true; + protected final ThreadLocal kryos = new ThreadLocal() { + @Override + protected Kryo initialValue() { + return newKryoInstance(); + } + }; + + public KryoSerialization() { + } + + public KryoSerialization(boolean onlySerializable) { + this.onlySerializable = onlySerializable; + } + + protected Kryo newKryoInstance() { + Kryo kryo = new Kryo(); + kryo.setInstantiatorStrategy(new CubaInstantiatorStrategy()); + if (onlySerializable) { + kryo.setDefaultSerializer(CubaFieldSerializer.class); + } + + //To work properly must itself be loaded by the application classloader (i.e. by classloader capable of loading + //all the other application classes). For web application it means placing this class inside webapp folder. + kryo.setClassLoader(KryoSerialization.class.getClassLoader()); + + kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer()); + kryo.register(Collections.EMPTY_LIST.getClass(), new CollectionsEmptyListSerializer()); + kryo.register(Collections.EMPTY_MAP.getClass(), new CollectionsEmptyMapSerializer()); + kryo.register(Collections.EMPTY_SET.getClass(), new CollectionsEmptySetSerializer()); + kryo.register(Collections.singletonList("").getClass(), new CollectionsSingletonListSerializer()); + kryo.register(Collections.singleton("").getClass(), new CollectionsSingletonSetSerializer()); + kryo.register(Collections.singletonMap("", "").getClass(), new CollectionsSingletonMapSerializer()); + kryo.register(BitSet.class, new BitSetSerializer()); + kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer()); + kryo.register(InvocationHandler.class, new JdkProxySerializer()); + UnmodifiableCollectionsSerializer.registerSerializers(kryo); + SynchronizedCollectionsSerializer.registerSerializers(kryo); + + kryo.register(CGLibProxySerializer.CGLibProxyMarker.class, new CGLibProxySerializer()); + ImmutableListSerializer.registerSerializers(kryo); + ImmutableSetSerializer.registerSerializers(kryo); + ImmutableMapSerializer.registerSerializers(kryo); + ImmutableMultimapSerializer.registerSerializers(kryo); + kryo.register(IndirectList.class, new IndirectContainerSerializer()); + kryo.register(IndirectMap.class, new IndirectContainerSerializer()); + kryo.register(IndirectSet.class, new IndirectContainerSerializer()); + + kryo.register(org.eclipse.persistence.indirection.IndirectList.class, new IndirectContainerSerializer()); + kryo.register(org.eclipse.persistence.indirection.IndirectMap.class, new IndirectContainerSerializer()); + kryo.register(org.eclipse.persistence.indirection.IndirectSet.class, new IndirectContainerSerializer()); + + //classes with custom serialization methods + kryo.register(HashMultimap.class, new CubaJavaSerializer()); + kryo.register(ArrayListMultimap.class, new CubaJavaSerializer()); + kryo.register(MetaClassImpl.class, new CubaJavaSerializer()); + kryo.register(MetaPropertyImpl.class, new CubaJavaSerializer()); + kryo.register(UnitOfWorkQueryValueHolder.class, new UnitOfWorkQueryValueHolderSerializer(kryo)); + + return kryo; + } + + @Override + @SuppressWarnings("finally") + public void serialize(Object object, OutputStream os) { + try (Output output = new CubaOutput(os)) { + if (object instanceof BaseGenericIdEntity + && BaseEntityInternalAccess.isManaged((BaseGenericIdEntity) object)) { + BaseEntityInternalAccess.setDetached((BaseGenericIdEntity) object, true); + } + kryos.get().writeClassAndObject(output, object); + } + } + + @Override + public Object deserialize(InputStream is) { + try (Input input = new Input(is)) { + return kryos.get().readClassAndObject(input); + } + } + + @Override + public byte[] serialize(Object object) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + serialize(object, bos); + return bos.toByteArray(); + } + + @Override + public Object deserialize(byte[] bytes) { + if (bytes == null) { + return null; + } + + return deserialize(new ByteArrayInputStream(bytes)); + } + + public Object copy(Object object) { + if (object == null) { + return null; + } + return kryos.get().copy(object); + } + + public static class IndirectContainerSerializer extends CollectionSerializer { + @Override + public void write(Kryo kryo, Output output, Collection collection) { + boolean isNotInstantiated = collection instanceof IndirectContainer + && !((IndirectContainer) collection).isInstantiated(); + output.writeBoolean(isNotInstantiated); + if (!isNotInstantiated) { + super.write(kryo, output, collection); + } + } + + @Override + public Collection read(Kryo kryo, Input input, Class type) { + boolean isNotInstantiated = input.readBoolean(); + if (!isNotInstantiated) { + return super.read(kryo, input, type); + } else { + IndirectCollection indirectCollection = (IndirectCollection) kryo.newInstance((Class) type); + indirectCollection.setValueHolder(new UnfetchedValueHolder()); + return (Collection) indirectCollection; + } + } + } + + public static class CubaJavaSerializer extends JavaSerializer { + @Override + public Object read(Kryo kryo, Input input, Class type) { + try { + ObjectMap graphContext = kryo.getGraphContext(); + ObjectInputStream objectStream = (ObjectInputStream) graphContext.get(this); + if (objectStream == null) { + objectStream = new ObjectInputStream(input) { + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + return ClassUtils.getClass(KryoSerialization.class.getClassLoader(), desc.getName()); + } + }; + graphContext.put(this, objectStream); + } + return objectStream.readObject(); + } catch (Exception ex) { + throw new KryoException("Error during Java deserialization.", ex); + } + } + } + + public class UnitOfWorkQueryValueHolderSerializer extends KryoSerialization.CubaFieldSerializer { + + public UnitOfWorkQueryValueHolderSerializer(Kryo kryo) { + super(kryo, UnitOfWorkQueryValueHolder.class); + } + + @Override + protected void rebuildCachedFields(boolean minorRebuild) { + super.rebuildCachedFields(minorRebuild); + List excludedFields = Arrays.stream(getFields()) + .filter(cachedField -> !INCLUDED_VALUE_HOLDER_FIELDS.contains(cachedField.getField().getName())) + .collect(Collectors.toList()); + excludedFields.forEach(this::removeField); + } + + @Override + @SuppressWarnings("unchecked") + public void write(Kryo kryo, Output output, Object object) { + boolean isNotInstantiated = object instanceof UnitOfWorkQueryValueHolder + && !((UnitOfWorkQueryValueHolder) object).isInstantiated(); + output.writeBoolean(isNotInstantiated); + if (!isNotInstantiated) { + super.write(kryo, output, object); + } + } + + @Override + @SuppressWarnings("unchecked") + public Object read(Kryo kryo, Input input, Class type) { + boolean isNotInstantiated = input.readBoolean(); + if (!isNotInstantiated) { + return super.read(kryo, input, type); + } else { + return new UnfetchedWeavedAttributeValueHolder(); + } + } + } + + /** + * Strategy first tries to find and use a no-arg constructor and if it fails to do so, it should try to use + * {@link StdInstantiatorStrategy} as a fallback, because this one does not invoke any constructor at all. + * Strategy is a copy {@link Kryo.DefaultInstantiatorStrategy}, but if instantiation fails, use fallback to create object + */ + public static class CubaInstantiatorStrategy implements org.objenesis.strategy.InstantiatorStrategy { + private final InstantiatorStrategy fallbackStrategy = new StdInstantiatorStrategy(); + + @Override + public ObjectInstantiator newInstantiatorOf(Class type) { + // Use ReflectASM if the class is not a non-static member class. + Class enclosingType = type.getEnclosingClass(); + boolean isNonStaticMemberClass = enclosingType != null && type.isMemberClass() + && !Modifier.isStatic(type.getModifiers()); + if (!isNonStaticMemberClass) { + try { + final ConstructorAccess access = ConstructorAccess.get(type); + return () -> { + try { + return access.newInstance(); + } catch (Exception ex) { + if (log.isTraceEnabled()) { + log.trace("Unable instantiate class {}", Util.className(type), ex); + } + return fallbackStrategy.newInstantiatorOf(type).newInstance(); + } + }; + } catch (Exception ignored) { + } + } + // Reflection. + try { + Constructor ctor; + try { + ctor = type.getConstructor((Class[]) null); + } catch (Exception ex) { + ctor = type.getDeclaredConstructor((Class[]) null); + ctor.setAccessible(true); + } + final Constructor constructor = ctor; + return () -> { + try { + return constructor.newInstance(); + } catch (Exception ex) { + if (log.isTraceEnabled()) { + log.trace("Unable instantiate class {}", Util.className(type), ex); + } + return fallbackStrategy.newInstantiatorOf(type).newInstance(); + } + }; + } catch (Exception ignored) { + } + return fallbackStrategy.newInstantiatorOf(type); + } + } + + public static class CubaFieldSerializer extends FieldSerializer { + public CubaFieldSerializer(Kryo kryo, Class type) { + super(kryo, type); + } + + public CubaFieldSerializer(Kryo kryo, Class type, Class[] generics) { + super(kryo, type, generics); + } + + @Override + protected T create(Kryo kryo, Input input, Class type) { + checkIncorrectClass(type); + return super.create(kryo, input, type); + } + + @Override + public void write(Kryo kryo, Output output, T object) { + checkIncorrectObject(object); + super.write(kryo, output, object); + } + + @Override + public T read(Kryo kryo, Input input, Class type) { + checkIncorrectClass(type); + return super.read(kryo, input, type); + + } + + protected void checkIncorrectClass(Class type) { + if (type != null && !Serializable.class.isAssignableFrom(type)) { + throw new IllegalArgumentException(String.format("Class is not registered: %s\nNote: To register this class use: kryo.register(\"%s\".class);", + Util.className(type), Util.className(type))); + } + } + + protected void checkIncorrectObject(T object) { + if (object != null && !(object instanceof Serializable)) { + String className = Util.className(object.getClass()); + throw new IllegalArgumentException(String.format("Class is not registered: %s\nNote: To register this class use: kryo.register(\"%s\".class);", + className, className)); + } + } + } + + public static class CubaOutput extends Output { + + public CubaOutput(OutputStream outputStream) { + super(outputStream); + } + + @Override + public void close() { + //Prevent close stream. Stream closed only by: + //com.haulmont.cuba.core.sys.remoting.HttpServiceExporter, + //com.haulmont.cuba.core.sys.remoting.ClusteredHttpInvokerRequestExecutor() + //Only flush buffer to output stream + flush(); + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/serialization/Serialization.java b/modules/global/src/com/haulmont/cuba/core/sys/serialization/Serialization.java index 08c9858454..40ea17286c 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/serialization/Serialization.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/serialization/Serialization.java @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.serialization; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * - * Defines the contract for platform serialization implementations. - */ -public interface Serialization { - /** - * Serialize object {@code object} to stream {@code os}. - * Stream isn't closed automatically after serialization. - * User code should be close stream correctly - * - * @param object object - * @param os output stream - */ - void serialize(Object object, OutputStream os); - - /** - * Deserialize object from stream - */ - Object deserialize(InputStream is); - - /** - * Serialize object to byte array - */ - byte[] serialize(Object object); - - /** - * Deserialize object from byte array - */ - Object deserialize(byte[] bytes); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.serialization; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * + * Defines the contract for platform serialization implementations. + */ +public interface Serialization { + /** + * Serialize object {@code object} to stream {@code os}. + * Stream isn't closed automatically after serialization. + * User code should be close stream correctly + * + * @param object object + * @param os output stream + */ + void serialize(Object object, OutputStream os); + + /** + * Deserialize object from stream + */ + Object deserialize(InputStream is); + + /** + * Serialize object to byte array + */ + byte[] serialize(Object object); + + /** + * Deserialize object from byte array + */ + Object deserialize(byte[] bytes); +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/serialization/SerializationSupport.java b/modules/global/src/com/haulmont/cuba/core/sys/serialization/SerializationSupport.java index 9d4fbaa9b7..8e91489a7f 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/serialization/SerializationSupport.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/serialization/SerializationSupport.java @@ -1,71 +1,71 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.serialization; - -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.cuba.core.sys.AppContext; -import org.apache.commons.lang.StringUtils; - -import java.io.InputStream; -import java.io.OutputStream; - -import static java.lang.String.format; - -/** - * - * Static holder for serialization object - */ -public class SerializationSupport { - private final static Serialization serialization; - private final static KryoSerialization kryoSerialization = new KryoSerialization(); - - static { - String serializationClassStr = AppContext.getProperty("cuba.serialization.impl"); - if (StringUtils.isNotBlank(serializationClassStr)) { - try { - Class aClass = ReflectionHelper.getClass(serializationClassStr); - serialization = ReflectionHelper.newInstance(aClass); - } catch (NoSuchMethodException e) { - throw new RuntimeException( - format("Could not create an instance of serialization class [%s]", serializationClassStr)); - } - } else { - serialization = new StandardSerialization(); - } - } - - public static void serialize(Object object, OutputStream os) { - serialization.serialize(object, os); - } - - public static Object deserialize(InputStream is) { - return serialization.deserialize(is); - } - - public static byte[] serialize(Object object) { - return serialization.serialize(object); - } - - public static Object deserialize(byte[] bytes) { - return serialization.deserialize(bytes); - } - - public static KryoSerialization getKryoSerialization() { - return kryoSerialization; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.serialization; + +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.cuba.core.sys.AppContext; +import org.apache.commons.lang.StringUtils; + +import java.io.InputStream; +import java.io.OutputStream; + +import static java.lang.String.format; + +/** + * + * Static holder for serialization object + */ +public class SerializationSupport { + private final static Serialization serialization; + private final static KryoSerialization kryoSerialization = new KryoSerialization(); + + static { + String serializationClassStr = AppContext.getProperty("cuba.serialization.impl"); + if (StringUtils.isNotBlank(serializationClassStr)) { + try { + Class aClass = ReflectionHelper.getClass(serializationClassStr); + serialization = ReflectionHelper.newInstance(aClass); + } catch (NoSuchMethodException e) { + throw new RuntimeException( + format("Could not create an instance of serialization class [%s]", serializationClassStr)); + } + } else { + serialization = new StandardSerialization(); + } + } + + public static void serialize(Object object, OutputStream os) { + serialization.serialize(object, os); + } + + public static Object deserialize(InputStream is) { + return serialization.deserialize(is); + } + + public static byte[] serialize(Object object) { + return serialization.serialize(object); + } + + public static Object deserialize(byte[] bytes) { + return serialization.deserialize(bytes); + } + + public static KryoSerialization getKryoSerialization() { + return kryoSerialization; + } +} diff --git a/modules/global/src/com/haulmont/cuba/core/sys/serialization/StandardSerialization.java b/modules/global/src/com/haulmont/cuba/core/sys/serialization/StandardSerialization.java index f03f864103..54beecaecb 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/serialization/StandardSerialization.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/serialization/StandardSerialization.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.serialization; - -import org.apache.commons.lang.ClassUtils; - -import java.io.*; - -/** - * The serialization implementation using standard Java serialization - */ -public class StandardSerialization implements Serialization { - @Override - public void serialize(Object object, OutputStream os) { - ObjectOutputStream out = null; - boolean isObjectStream = os instanceof ObjectOutputStream; - try { - out = isObjectStream ? (ObjectOutputStream)os : new ObjectOutputStream(os); - out.writeObject(object); - } catch (IOException ex) { - throw new IllegalStateException("Failed to serialize object", ex); - } finally { - //Prevent close stream. Stream closed only by: - //com.haulmont.cuba.core.sys.remoting.HttpServiceExporter, - //com.haulmont.cuba.core.sys.remoting.ClusteredHttpInvokerRequestExecutor() - //Only flush buffer to output stream - if (!isObjectStream && out != null) { - try { - out.flush(); - } catch (IOException ex) { - throw new IllegalStateException("Failed to serialize object", ex); - } - } - } - } - - //To work properly must itself be loaded by the application classloader (i.e. by classloader capable of loading - //all the other application classes). For web application it means placing this class inside webapp folder. - @Override - public Object deserialize(InputStream is) { - try { - ObjectInputStream ois; - boolean isObjectStream = is instanceof ObjectInputStream; - if (isObjectStream) { - ois = (ObjectInputStream)is; - } else { - ois = new ObjectInputStream(is) { - @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - return ClassUtils.getClass(StandardSerialization.class.getClassLoader(), desc.getName()); - } - }; - } - return ois.readObject(); - } catch (IOException ex) { - throw new IllegalArgumentException("Failed to deserialize object", ex); - } catch (ClassNotFoundException ex) { - throw new IllegalStateException("Failed to deserialize object type", ex); - } - } - - @Override - public byte[] serialize(Object object) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - serialize(object, bos); - return bos.toByteArray(); - } - - @Override - public Object deserialize(byte[] bytes) { - if (bytes == null) { - return null; - } - - return deserialize(new ByteArrayInputStream(bytes)); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.serialization; + +import org.apache.commons.lang.ClassUtils; + +import java.io.*; + +/** + * The serialization implementation using standard Java serialization + */ +public class StandardSerialization implements Serialization { + @Override + public void serialize(Object object, OutputStream os) { + ObjectOutputStream out = null; + boolean isObjectStream = os instanceof ObjectOutputStream; + try { + out = isObjectStream ? (ObjectOutputStream)os : new ObjectOutputStream(os); + out.writeObject(object); + } catch (IOException ex) { + throw new IllegalStateException("Failed to serialize object", ex); + } finally { + //Prevent close stream. Stream closed only by: + //com.haulmont.cuba.core.sys.remoting.HttpServiceExporter, + //com.haulmont.cuba.core.sys.remoting.ClusteredHttpInvokerRequestExecutor() + //Only flush buffer to output stream + if (!isObjectStream && out != null) { + try { + out.flush(); + } catch (IOException ex) { + throw new IllegalStateException("Failed to serialize object", ex); + } + } + } + } + + //To work properly must itself be loaded by the application classloader (i.e. by classloader capable of loading + //all the other application classes). For web application it means placing this class inside webapp folder. + @Override + public Object deserialize(InputStream is) { + try { + ObjectInputStream ois; + boolean isObjectStream = is instanceof ObjectInputStream; + if (isObjectStream) { + ois = (ObjectInputStream)is; + } else { + ois = new ObjectInputStream(is) { + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + return ClassUtils.getClass(StandardSerialization.class.getClassLoader(), desc.getName()); + } + }; + } + return ois.readObject(); + } catch (IOException ex) { + throw new IllegalArgumentException("Failed to deserialize object", ex); + } catch (ClassNotFoundException ex) { + throw new IllegalStateException("Failed to deserialize object type", ex); + } + } + + @Override + public byte[] serialize(Object object) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + serialize(object, bos); + return bos.toByteArray(); + } + + @Override + public Object deserialize(byte[] bytes) { + if (bytes == null) { + return null; + } + + return deserialize(new ByteArrayInputStream(bytes)); + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/app/LoginService.java b/modules/global/src/com/haulmont/cuba/security/app/LoginService.java index c176db284d..8b7e17c7d1 100644 --- a/modules/global/src/com/haulmont/cuba/security/app/LoginService.java +++ b/modules/global/src/com/haulmont/cuba/security/app/LoginService.java @@ -1,224 +1,224 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.security.auth.*; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.global.LoginException; -import com.haulmont.cuba.security.global.UserSession; - -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -/** - * Service interface defining methods to login users to the middleware. - * - * @deprecated Use {@link AuthenticationService} - */ -@Deprecated -public interface LoginService { - - String NAME = "cuba_LoginService"; - - /** - * Log out and destroy an active user session. - * - * @deprecated Use {@link AuthenticationService#logout()} - */ - @Deprecated - void logout(); - - /** - * Substitute a user, obtaining all its security related environment. - *
- * This method replaces an active UserSession with the new one, which is returned. - * - * @param substitutedUser a user to substitute. Must be in the current users' {@link User#substitutions} list. - * @return new UserSession instance that contains:
    - *
  • id - the previously active user session id
  • - *
  • user - the logged in user
  • - *
  • substitutedUser - the user passed to this method
  • - *
  • all security data - loaded for the substitutedUser
  • - *
- * @deprecated Use {@link AuthenticationService#substituteUser(User)} - */ - @Deprecated - UserSession substituteUser(User substitutedUser); - - /** - * Get a UserSession from the cache of currently active sessions. - * - * @param sessionId the session id - * @return a UserSession instance or null, if not found - * @deprecated use {@link TrustedClientService#findSession(String, UUID)} - */ - @Nullable - @Deprecated - UserSession getSession(UUID sessionId); - - /** - * Get system user session from a trusted client.
- * Do not call {@link #logout()} for obtained user session. It is cached on middleware for multiple clients.
- * Do not cache system session on clients since it is not replicated in cluster. - * - * @param trustedClientPassword trusted client password - * @return created user session - * @throws LoginException in case of unsuccessful login - * @deprecated use {@link TrustedClientService#getSystemSession(String)} - */ - @Deprecated - UserSession getSystemSession(String trustedClientPassword) throws LoginException; - - /** - * Log in using login and user's password. - * - * @param login login - * @param password user's encrypted password - * @param locale client locale - * @return created user session - * @throws LoginException in case of unsuccessful log in - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link LoginPasswordCredentials}. - */ - @Deprecated - UserSession login(String login, String password, Locale locale) throws LoginException; - - /** - * Login using user name and password - * - * @param login login name - * @param password encrypted password - * @param locale client locale - * @param params map of login parameters. Supported parameters are: - *
    - *
  • "com.haulmont.cuba.core.global.ClientType": "WEB" or "DESKTOP". It is used to check the - * "cuba.gui.loginToClient" specific permission.
  • - *
  • "cuba.syncNewUserSessionReplication": true or false. Indicates that a new user session - * created on login should be sent to the cluster synchronously. Overrides the application property - * with the same name.
  • - *
- * @return created user session - * @throws LoginException in case of unsuccessful login - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link LoginPasswordCredentials}. - */ - @Deprecated - UserSession login(String login, String password, Locale locale, Map params) throws LoginException; - - /** - * Log in from a trusted client. - * - * @param login login - * @param password client's encrypted trusted password - * @param locale client locale - * @return created user session - * @throws LoginException in case of unsuccessful log in - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link TrustedClientCredentials}. - */ - @Deprecated - UserSession loginTrusted(String login, String password, Locale locale) throws LoginException; - - /** - * Login using user name and trusted password - * - * @param login login name - * @param password client's encrypted trusted password - * @param locale client locale - * @param params login params - * @return created user session - * @throws LoginException in case of unsuccessful login - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link TrustedClientCredentials}. - */ - @Deprecated - UserSession loginTrusted(String login, String password, Locale locale, Map params) - throws LoginException; - - /** - * Login using user name and remember me token - * - * @param login login name - * @param rememberMeToken client's remember me token - * @param locale client locale - * @return created user session - * @throws LoginException in case of unsuccessful login - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link RememberMeCredentials}. - */ - @Deprecated - UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException; - - /** - * Login using user name and remember me token - * - * @param login login name - * @param rememberMeToken client's remember me token - * @param locale client locale - * @param params login params - * @return created user session - * @throws LoginException in case of unsuccessful login - * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link RememberMeCredentials}. - */ - @Deprecated - UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) throws LoginException; - - /** - * Check if remember me token exists in db. - * - * @param login user login - * @param rememberMeToken remember me token - * @return true if remember me token exists in db - * @deprecated Is not supported any more, returns false - */ - @Deprecated - boolean checkRememberMe(String login, String rememberMeToken); - - /** - * @return true if the brute-force protection is enabled - * @deprecated always returns false - */ - @Deprecated - boolean isBruteForceProtectionEnabled(); - - /** - * @return a time interval in seconds for which a user is blocked after a series of - * unsuccessful login attempts - * @deprecated is not supported any more - */ - @Deprecated - int getBruteForceBlockIntervalSec(); - - /** - * Returns a number of login attempts left for the specified pair of login and IP-address - * - * @param login user login - * @param ipAddress user IP-address - * @return number of login attempts left - * @deprecated is not supported any more - */ - @Deprecated - int loginAttemptsLeft(String login, String ipAddress); - - /** - * Registers unsuccessful login attempt - * - * @param login user login - * @param ipAddress user IP-address - * @return a number of login attempts left for the specified pair of login and IP-address - * @deprecated is not supported any more - */ - @Deprecated - int registerUnsuccessfulLogin(String login, String ipAddress); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.security.auth.*; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.global.LoginException; +import com.haulmont.cuba.security.global.UserSession; + +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +/** + * Service interface defining methods to login users to the middleware. + * + * @deprecated Use {@link AuthenticationService} + */ +@Deprecated +public interface LoginService { + + String NAME = "cuba_LoginService"; + + /** + * Log out and destroy an active user session. + * + * @deprecated Use {@link AuthenticationService#logout()} + */ + @Deprecated + void logout(); + + /** + * Substitute a user, obtaining all its security related environment. + *
+ * This method replaces an active UserSession with the new one, which is returned. + * + * @param substitutedUser a user to substitute. Must be in the current users' {@link User#substitutions} list. + * @return new UserSession instance that contains:
    + *
  • id - the previously active user session id
  • + *
  • user - the logged in user
  • + *
  • substitutedUser - the user passed to this method
  • + *
  • all security data - loaded for the substitutedUser
  • + *
+ * @deprecated Use {@link AuthenticationService#substituteUser(User)} + */ + @Deprecated + UserSession substituteUser(User substitutedUser); + + /** + * Get a UserSession from the cache of currently active sessions. + * + * @param sessionId the session id + * @return a UserSession instance or null, if not found + * @deprecated use {@link TrustedClientService#findSession(String, UUID)} + */ + @Nullable + @Deprecated + UserSession getSession(UUID sessionId); + + /** + * Get system user session from a trusted client.
+ * Do not call {@link #logout()} for obtained user session. It is cached on middleware for multiple clients.
+ * Do not cache system session on clients since it is not replicated in cluster. + * + * @param trustedClientPassword trusted client password + * @return created user session + * @throws LoginException in case of unsuccessful login + * @deprecated use {@link TrustedClientService#getSystemSession(String)} + */ + @Deprecated + UserSession getSystemSession(String trustedClientPassword) throws LoginException; + + /** + * Log in using login and user's password. + * + * @param login login + * @param password user's encrypted password + * @param locale client locale + * @return created user session + * @throws LoginException in case of unsuccessful log in + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link LoginPasswordCredentials}. + */ + @Deprecated + UserSession login(String login, String password, Locale locale) throws LoginException; + + /** + * Login using user name and password + * + * @param login login name + * @param password encrypted password + * @param locale client locale + * @param params map of login parameters. Supported parameters are: + *
    + *
  • "com.haulmont.cuba.core.global.ClientType": "WEB" or "DESKTOP". It is used to check the + * "cuba.gui.loginToClient" specific permission.
  • + *
  • "cuba.syncNewUserSessionReplication": true or false. Indicates that a new user session + * created on login should be sent to the cluster synchronously. Overrides the application property + * with the same name.
  • + *
+ * @return created user session + * @throws LoginException in case of unsuccessful login + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link LoginPasswordCredentials}. + */ + @Deprecated + UserSession login(String login, String password, Locale locale, Map params) throws LoginException; + + /** + * Log in from a trusted client. + * + * @param login login + * @param password client's encrypted trusted password + * @param locale client locale + * @return created user session + * @throws LoginException in case of unsuccessful log in + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link TrustedClientCredentials}. + */ + @Deprecated + UserSession loginTrusted(String login, String password, Locale locale) throws LoginException; + + /** + * Login using user name and trusted password + * + * @param login login name + * @param password client's encrypted trusted password + * @param locale client locale + * @param params login params + * @return created user session + * @throws LoginException in case of unsuccessful login + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link TrustedClientCredentials}. + */ + @Deprecated + UserSession loginTrusted(String login, String password, Locale locale, Map params) + throws LoginException; + + /** + * Login using user name and remember me token + * + * @param login login name + * @param rememberMeToken client's remember me token + * @param locale client locale + * @return created user session + * @throws LoginException in case of unsuccessful login + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link RememberMeCredentials}. + */ + @Deprecated + UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale) throws LoginException; + + /** + * Login using user name and remember me token + * + * @param login login name + * @param rememberMeToken client's remember me token + * @param locale client locale + * @param params login params + * @return created user session + * @throws LoginException in case of unsuccessful login + * @deprecated Use {@link AuthenticationService#login(Credentials)} with {@link RememberMeCredentials}. + */ + @Deprecated + UserSession loginByRememberMe(String login, String rememberMeToken, Locale locale, Map params) throws LoginException; + + /** + * Check if remember me token exists in db. + * + * @param login user login + * @param rememberMeToken remember me token + * @return true if remember me token exists in db + * @deprecated Is not supported any more, returns false + */ + @Deprecated + boolean checkRememberMe(String login, String rememberMeToken); + + /** + * @return true if the brute-force protection is enabled + * @deprecated always returns false + */ + @Deprecated + boolean isBruteForceProtectionEnabled(); + + /** + * @return a time interval in seconds for which a user is blocked after a series of + * unsuccessful login attempts + * @deprecated is not supported any more + */ + @Deprecated + int getBruteForceBlockIntervalSec(); + + /** + * Returns a number of login attempts left for the specified pair of login and IP-address + * + * @param login user login + * @param ipAddress user IP-address + * @return number of login attempts left + * @deprecated is not supported any more + */ + @Deprecated + int loginAttemptsLeft(String login, String ipAddress); + + /** + * Registers unsuccessful login attempt + * + * @param login user login + * @param ipAddress user IP-address + * @return a number of login attempts left for the specified pair of login and IP-address + * @deprecated is not supported any more + */ + @Deprecated + int registerUnsuccessfulLogin(String login, String ipAddress); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/app/UserManagementService.java b/modules/global/src/com/haulmont/cuba/security/app/UserManagementService.java index 24825f1db4..f98543aad0 100644 --- a/modules/global/src/com/haulmont/cuba/security/app/UserManagementService.java +++ b/modules/global/src/com/haulmont/cuba/security/app/UserManagementService.java @@ -1,150 +1,150 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.security.entity.Group; -import com.haulmont.cuba.security.entity.Role; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * Service providing maintenance operations on security entities. - * - */ -public interface UserManagementService { - - String NAME = "cuba_UserManagementService"; - - /** - * Copy access group with all its properties and subgroups. - * - * @param accessGroupId Source access group Id - * @return Cloned group - */ - Group copyAccessGroup(UUID accessGroupId); - - /** - * Copy user role with all its permissions. - * - * @param roleId Source access role Id - * @return Cloned role - */ - Role copyRole(UUID roleId); - - /** - * Move specified users to a new access group. - * - * @param userIds Ids for moved users - * @param targetAccessGroupId Id of target access group, may be null - * @return Number of users moved to target group - */ - Integer moveUsersToGroup(List userIds, @Nullable UUID targetAccessGroupId); - - /** - * Update passwords for specified users, send them emails with new generated passwords and make them change - * passwords at next logon. - * - * @param userIds User ids - * @return Count of users - */ - Integer changePasswordsAtLogonAndSendEmails(List userIds); - - /** - * Make specified users to change passwords at next logon. - * - * @param userIds User ids - * @param generatePassword Generate new passwords - * @return Map with userId and new password - */ - Map changePasswordsAtLogon(List userIds, boolean generatePassword); - - /** - * @param userId User id - * @param passwordHash Plain hash of new password - * @return True if the new and old passwords are equal - */ - boolean checkPassword(UUID userId, String passwordHash); - - /** - * Remove remember me tokens for users. The tokens reset is executed in the joined transaction - * if there is one at the moment, creates a new transaction otherwise. - * - * @param userIds User ids - */ - void resetRememberMeTokens(List userIds); - - /** - * Remove remember me tokens for all users. The tokens reset is always executed in a new transaction. - */ - void resetRememberMeTokens(); - - /** - * Generate and store to DB {@link com.haulmont.cuba.security.entity.RememberMeToken} - * - * @return token string - */ - String generateRememberMeToken(UUID userId); - - /** - * Get names of session attributes defined for the given group and all its parent groups. - * - * @param groupId Group identifier - * @return list of session attribute names - */ - List getSessionAttributeNames(UUID groupId); - - /** - * Load current user's time zone settings. - */ - UserTimeZone loadOwnTimeZone(); - - /** - * Save current user's time zone settings. - */ - void saveOwnTimeZone(UserTimeZone timeZone); - - /** - * Load current user's language. - */ - String loadOwnLocale(); - - /** - * Save current user's language settings. - */ - void saveOwnLocale(String locale); - - /** - * Change password for user - * - * @param userId user id - * @param newPasswordHash password hash - */ - void changeUserPassword(UUID userId, String newPasswordHash); - - /** - * Checks whether removing of users with the given logins is allowed - * - * @param userLogins user logins - * @return true if removing is allowed or false otherwise - */ - boolean isUsersRemovingAllowed(Collection userLogins); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.security.entity.Group; +import com.haulmont.cuba.security.entity.Role; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Service providing maintenance operations on security entities. + * + */ +public interface UserManagementService { + + String NAME = "cuba_UserManagementService"; + + /** + * Copy access group with all its properties and subgroups. + * + * @param accessGroupId Source access group Id + * @return Cloned group + */ + Group copyAccessGroup(UUID accessGroupId); + + /** + * Copy user role with all its permissions. + * + * @param roleId Source access role Id + * @return Cloned role + */ + Role copyRole(UUID roleId); + + /** + * Move specified users to a new access group. + * + * @param userIds Ids for moved users + * @param targetAccessGroupId Id of target access group, may be null + * @return Number of users moved to target group + */ + Integer moveUsersToGroup(List userIds, @Nullable UUID targetAccessGroupId); + + /** + * Update passwords for specified users, send them emails with new generated passwords and make them change + * passwords at next logon. + * + * @param userIds User ids + * @return Count of users + */ + Integer changePasswordsAtLogonAndSendEmails(List userIds); + + /** + * Make specified users to change passwords at next logon. + * + * @param userIds User ids + * @param generatePassword Generate new passwords + * @return Map with userId and new password + */ + Map changePasswordsAtLogon(List userIds, boolean generatePassword); + + /** + * @param userId User id + * @param passwordHash Plain hash of new password + * @return True if the new and old passwords are equal + */ + boolean checkPassword(UUID userId, String passwordHash); + + /** + * Remove remember me tokens for users. The tokens reset is executed in the joined transaction + * if there is one at the moment, creates a new transaction otherwise. + * + * @param userIds User ids + */ + void resetRememberMeTokens(List userIds); + + /** + * Remove remember me tokens for all users. The tokens reset is always executed in a new transaction. + */ + void resetRememberMeTokens(); + + /** + * Generate and store to DB {@link com.haulmont.cuba.security.entity.RememberMeToken} + * + * @return token string + */ + String generateRememberMeToken(UUID userId); + + /** + * Get names of session attributes defined for the given group and all its parent groups. + * + * @param groupId Group identifier + * @return list of session attribute names + */ + List getSessionAttributeNames(UUID groupId); + + /** + * Load current user's time zone settings. + */ + UserTimeZone loadOwnTimeZone(); + + /** + * Save current user's time zone settings. + */ + void saveOwnTimeZone(UserTimeZone timeZone); + + /** + * Load current user's language. + */ + String loadOwnLocale(); + + /** + * Save current user's language settings. + */ + void saveOwnLocale(String locale); + + /** + * Change password for user + * + * @param userId user id + * @param newPasswordHash password hash + */ + void changeUserPassword(UUID userId, String newPasswordHash); + + /** + * Checks whether removing of users with the given logins is allowed + * + * @param userLogins user logins + * @return true if removing is allowed or false otherwise + */ + boolean isUsersRemovingAllowed(Collection userLogins); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/app/UserSessionService.java b/modules/global/src/com/haulmont/cuba/security/app/UserSessionService.java index 679993b05c..5ff50c20d3 100644 --- a/modules/global/src/com/haulmont/cuba/security/app/UserSessionService.java +++ b/modules/global/src/com/haulmont/cuba/security/app/UserSessionService.java @@ -1,134 +1,134 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.security.entity.PermissionType; -import com.haulmont.cuba.security.entity.User; -import com.haulmont.cuba.security.entity.UserSessionEntity; -import com.haulmont.cuba.security.global.UserSession; - -import javax.annotation.Nullable; -import java.io.Serializable; -import java.util.*; - -/** - * Service interface to active {@link UserSession}s management. - * - */ -public interface UserSessionService { - - String NAME = "cuba_UserSessionService"; - - /** - * @param sessionId a session identifier - * @return an active user session instance if exists - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - UserSession getUserSession(UUID sessionId); - - /** - * Set a session attribute value, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param name attribute name - * @param value attribute value - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void setSessionAttribute(UUID sessionId, String name, Serializable value); - - /** - * Remove a session attribute, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param name attribute name - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void removeSessionAttribute(UUID sessionId, String name); - - /** - * Set user locale into the session, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param locale user locale - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void setSessionLocale(UUID sessionId, Locale locale); - - /** - * Set user time zone into the session, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param timeZone user time zone - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void setSessionTimeZone(UUID sessionId, TimeZone timeZone); - - /** - * Set client's address into the session, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param address client's address - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void setSessionAddress(UUID sessionId, String address); - - /** - * Set client's information into the session, propagating changes to the cluster. - * @param sessionId an active session identifier - * @param clientInfo client's info - * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID - * doesn't exist - */ - void setSessionClientInfo(UUID sessionId, String clientInfo); - - /** - * @return the list of active user sessions - */ - Collection getUserSessionInfo(); - - /** - * Disconnect a session. Returns silently if there is no active session with the specified ID. - * @param id an active session identifier - */ - void killSession(UUID id); - - /** - * Post a message to the list of active user sessions. If a session is not found, it is ignored. - * @param sessionIds list of session identifiers - * @param message the message text - */ - void postMessage(List sessionIds, String message); - - /** - * Poll for messages left for the current user session. Can also be used for session ping to prevent expiring on - * user idle time. - * @return all messages sent to the current session in one string separated by carriage returns - */ - @Nullable - String getMessages(); - - /** - * Get effective user permission. - * @param user user - * @param permissionType type of permission - * @param target permission target - * @return effective permission value - */ - Integer getPermissionValue(User user, PermissionType permissionType, String target); - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.security.entity.PermissionType; +import com.haulmont.cuba.security.entity.User; +import com.haulmont.cuba.security.entity.UserSessionEntity; +import com.haulmont.cuba.security.global.UserSession; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.*; + +/** + * Service interface to active {@link UserSession}s management. + * + */ +public interface UserSessionService { + + String NAME = "cuba_UserSessionService"; + + /** + * @param sessionId a session identifier + * @return an active user session instance if exists + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + UserSession getUserSession(UUID sessionId); + + /** + * Set a session attribute value, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param name attribute name + * @param value attribute value + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void setSessionAttribute(UUID sessionId, String name, Serializable value); + + /** + * Remove a session attribute, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param name attribute name + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void removeSessionAttribute(UUID sessionId, String name); + + /** + * Set user locale into the session, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param locale user locale + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void setSessionLocale(UUID sessionId, Locale locale); + + /** + * Set user time zone into the session, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param timeZone user time zone + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void setSessionTimeZone(UUID sessionId, TimeZone timeZone); + + /** + * Set client's address into the session, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param address client's address + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void setSessionAddress(UUID sessionId, String address); + + /** + * Set client's information into the session, propagating changes to the cluster. + * @param sessionId an active session identifier + * @param clientInfo client's info + * @throws com.haulmont.cuba.security.global.NoUserSessionException in case of a session with the specified ID + * doesn't exist + */ + void setSessionClientInfo(UUID sessionId, String clientInfo); + + /** + * @return the list of active user sessions + */ + Collection getUserSessionInfo(); + + /** + * Disconnect a session. Returns silently if there is no active session with the specified ID. + * @param id an active session identifier + */ + void killSession(UUID id); + + /** + * Post a message to the list of active user sessions. If a session is not found, it is ignored. + * @param sessionIds list of session identifiers + * @param message the message text + */ + void postMessage(List sessionIds, String message); + + /** + * Poll for messages left for the current user session. Can also be used for session ping to prevent expiring on + * user idle time. + * @return all messages sent to the current session in one string separated by carriage returns + */ + @Nullable + String getMessages(); + + /** + * Get effective user permission. + * @param user user + * @param permissionType type of permission + * @param target permission target + * @return effective permission value + */ + Integer getPermissionValue(User user, PermissionType permissionType, String target); + +} diff --git a/modules/global/src/com/haulmont/cuba/security/app/UserSettingService.java b/modules/global/src/com/haulmont/cuba/security/app/UserSettingService.java index a1a962828a..3c92822ef3 100644 --- a/modules/global/src/com/haulmont/cuba/security/app/UserSettingService.java +++ b/modules/global/src/com/haulmont/cuba/security/app/UserSettingService.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.app; - -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.security.entity.User; - -/** - * Service providing current user settings functionality: - * an application can save/load some "setting" (plain or XML string) for current user. - *
- * It is usually used by UI forms and components. - */ -public interface UserSettingService { - - String NAME = "cuba_UserSettingService"; - - /** Load settings for the current user and null client type. Returns null if no such setting found. */ - String loadSetting(String name); - - /** Load settings for the current user. Returns null if no such setting found. */ - String loadSetting(ClientType clientType, String name); - - /** Save settings for the current user and null client type */ - void saveSetting(String name, String value); - - /** Save settings for the current user */ - void saveSetting(ClientType clientType, String name, String value); - - /** Delete settings for the current user */ - void deleteSettings(ClientType clientType, String name); - - /** Copy user settings to another user */ - void copySettings(User fromUser, User toUser); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.app; + +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.security.entity.User; + +/** + * Service providing current user settings functionality: + * an application can save/load some "setting" (plain or XML string) for current user. + *
+ * It is usually used by UI forms and components. + */ +public interface UserSettingService { + + String NAME = "cuba_UserSettingService"; + + /** Load settings for the current user and null client type. Returns null if no such setting found. */ + String loadSetting(String name); + + /** Load settings for the current user. Returns null if no such setting found. */ + String loadSetting(ClientType clientType, String name); + + /** Save settings for the current user and null client type */ + void saveSetting(String name, String value); + + /** Save settings for the current user */ + void saveSetting(ClientType clientType, String name, String value); + + /** Delete settings for the current user */ + void deleteSettings(ClientType clientType, String name); + + /** Copy user settings to another user */ + void copySettings(User fromUser, User toUser); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/Constraint.java b/modules/global/src/com/haulmont/cuba/security/entity/Constraint.java index ba5e367d4d..ec2e3dc1de 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/Constraint.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/Constraint.java @@ -1,146 +1,146 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; - -/** - * Security constraint definition entity. - */ -@Entity(name = "sec$Constraint") -@Table(name = "SEC_CONSTRAINT") -@SystemLevel -public class Constraint extends StandardEntity { - - private static final long serialVersionUID = -8598548105315052474L; - - @Column(name = "CHECK_TYPE", length = 50, nullable = false) - protected String checkType = ConstraintCheckType.DATABASE.getId(); - - @Column(name = "OPERATION_TYPE", length = 50, nullable = false) - protected String operationType = ConstraintOperationType.READ.getId(); - - @Column(name = "CODE", length = 255) - protected String code; - - @Column(name = "ENTITY_NAME", length = 255, nullable = false) - protected String entityName; - - @Column(name = "JOIN_CLAUSE", length = 500) - protected String joinClause; - - @Column(name = "WHERE_CLAUSE", length = 1000) - protected String whereClause; - - @Lob - @Column(name = "GROOVY_SCRIPT") - protected String groovyScript; - - @Lob - @Column(name = "FILTER_XML") - protected String filterXml; - - @Column(name = "IS_ACTIVE") - protected Boolean isActive = true; - - @ManyToOne - @JoinColumn(name = "GROUP_ID") - protected Group group; - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - - public String getEntityName() { - return entityName; - } - - public void setEntityName(String entityName) { - this.entityName = entityName; - } - - public Group getGroup() { - return group; - } - - public void setGroup(Group group) { - this.group = group; - } - - public String getJoinClause() { - return joinClause; - } - - public void setJoinClause(String joinClause) { - this.joinClause = joinClause; - } - - public String getWhereClause() { - return whereClause; - } - - public void setWhereClause(String whereClause) { - this.whereClause = whereClause; - } - - public String getGroovyScript() { - return groovyScript; - } - - public void setGroovyScript(String groovyScript) { - this.groovyScript = groovyScript; - } - - public String getFilterXml() { - return filterXml; - } - - public void setFilterXml(String filterXml) { - this.filterXml = filterXml; - } - - public ConstraintCheckType getCheckType() { - return ConstraintCheckType.fromId(checkType); - } - - public void setCheckType(ConstraintCheckType checkType) { - this.checkType = checkType != null ? checkType.getId() : null; - } - - public ConstraintOperationType getOperationType() { - return ConstraintOperationType.fromId(operationType); - } - - public void setOperationType(ConstraintOperationType operationType) { - this.operationType = operationType != null ? operationType.getId() : null; - } - - public Boolean getIsActive() { - return isActive; - } - - public void setIsActive(Boolean isActive) { - this.isActive = isActive; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; + +/** + * Security constraint definition entity. + */ +@Entity(name = "sec$Constraint") +@Table(name = "SEC_CONSTRAINT") +@SystemLevel +public class Constraint extends StandardEntity { + + private static final long serialVersionUID = -8598548105315052474L; + + @Column(name = "CHECK_TYPE", length = 50, nullable = false) + protected String checkType = ConstraintCheckType.DATABASE.getId(); + + @Column(name = "OPERATION_TYPE", length = 50, nullable = false) + protected String operationType = ConstraintOperationType.READ.getId(); + + @Column(name = "CODE", length = 255) + protected String code; + + @Column(name = "ENTITY_NAME", length = 255, nullable = false) + protected String entityName; + + @Column(name = "JOIN_CLAUSE", length = 500) + protected String joinClause; + + @Column(name = "WHERE_CLAUSE", length = 1000) + protected String whereClause; + + @Lob + @Column(name = "GROOVY_SCRIPT") + protected String groovyScript; + + @Lob + @Column(name = "FILTER_XML") + protected String filterXml; + + @Column(name = "IS_ACTIVE") + protected Boolean isActive = true; + + @ManyToOne + @JoinColumn(name = "GROUP_ID") + protected Group group; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getEntityName() { + return entityName; + } + + public void setEntityName(String entityName) { + this.entityName = entityName; + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public String getJoinClause() { + return joinClause; + } + + public void setJoinClause(String joinClause) { + this.joinClause = joinClause; + } + + public String getWhereClause() { + return whereClause; + } + + public void setWhereClause(String whereClause) { + this.whereClause = whereClause; + } + + public String getGroovyScript() { + return groovyScript; + } + + public void setGroovyScript(String groovyScript) { + this.groovyScript = groovyScript; + } + + public String getFilterXml() { + return filterXml; + } + + public void setFilterXml(String filterXml) { + this.filterXml = filterXml; + } + + public ConstraintCheckType getCheckType() { + return ConstraintCheckType.fromId(checkType); + } + + public void setCheckType(ConstraintCheckType checkType) { + this.checkType = checkType != null ? checkType.getId() : null; + } + + public ConstraintOperationType getOperationType() { + return ConstraintOperationType.fromId(operationType); + } + + public void setOperationType(ConstraintOperationType operationType) { + this.operationType = operationType != null ? operationType.getId() : null; + } + + public Boolean getIsActive() { + return isActive; + } + + public void setIsActive(Boolean isActive) { + this.isActive = isActive; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/ConstraintCheckType.java b/modules/global/src/com/haulmont/cuba/security/entity/ConstraintCheckType.java index d442c99268..805c646d5b 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/ConstraintCheckType.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/ConstraintCheckType.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import org.apache.commons.lang.ObjectUtils; - -/** - * Type of constraint. - */ -public enum ConstraintCheckType implements EnumClass { - DATABASE_AND_MEMORY("db_and_memory", true, true), - DATABASE("db", true, false), - MEMORY("memory", false, true); - - private String id; - private boolean memory; - private boolean database; - - ConstraintCheckType(String id, boolean database, boolean memory) { - this.id = id; - this.database = database; - this.memory = memory; - } - - @Override - public String getId() { - return id; - } - - public static ConstraintCheckType fromId(String id) { - for (ConstraintCheckType type : ConstraintCheckType.values()) { - if (ObjectUtils.equals(id, type.getId())) - return type; - } - return null; // unknown id - } - - public boolean database(){ - return database; - } - - public boolean memory(){ - return memory; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import org.apache.commons.lang.ObjectUtils; + +/** + * Type of constraint. + */ +public enum ConstraintCheckType implements EnumClass { + DATABASE_AND_MEMORY("db_and_memory", true, true), + DATABASE("db", true, false), + MEMORY("memory", false, true); + + private String id; + private boolean memory; + private boolean database; + + ConstraintCheckType(String id, boolean database, boolean memory) { + this.id = id; + this.database = database; + this.memory = memory; + } + + @Override + public String getId() { + return id; + } + + public static ConstraintCheckType fromId(String id) { + for (ConstraintCheckType type : ConstraintCheckType.values()) { + if (ObjectUtils.equals(id, type.getId())) + return type; + } + return null; // unknown id + } + + public boolean database(){ + return database; + } + + public boolean memory(){ + return memory; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/ConstraintOperationType.java b/modules/global/src/com/haulmont/cuba/security/entity/ConstraintOperationType.java index b31410bd52..001268658b 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/ConstraintOperationType.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/ConstraintOperationType.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import org.apache.commons.lang.ObjectUtils; - -/** - * Area of constraint application. - */ -public enum ConstraintOperationType implements EnumClass { - - //todo degtyarjov probably need to join with EntityOp - - CREATE("create"), - READ("read"), - UPDATE("update"), - DELETE("delete"), - ALL("all"), - CUSTOM("custom"); - - private String id; - - ConstraintOperationType(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - public static ConstraintOperationType fromId(String id) { - for (ConstraintOperationType area : ConstraintOperationType.values()) { - if (ObjectUtils.equals(id, area.getId())) - return area; - } - return null; // unknown id - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import org.apache.commons.lang.ObjectUtils; + +/** + * Area of constraint application. + */ +public enum ConstraintOperationType implements EnumClass { + + //todo degtyarjov probably need to join with EntityOp + + CREATE("create"), + READ("read"), + UPDATE("update"), + DELETE("delete"), + ALL("all"), + CUSTOM("custom"); + + private String id; + + ConstraintOperationType(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + public static ConstraintOperationType fromId(String id) { + for (ConstraintOperationType area : ConstraintOperationType.values()) { + if (ObjectUtils.equals(id, area.getId())) + return area; + } + return null; // unknown id + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/EntityAttrAccess.java b/modules/global/src/com/haulmont/cuba/security/entity/EntityAttrAccess.java index 96bf283fb6..d9d1b2172e 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/EntityAttrAccess.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/EntityAttrAccess.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -/** - * Type of access to an entity attribute. - */ -public enum EntityAttrAccess { - DENY(0), - VIEW(1), - MODIFY(2); - - private int id; - - EntityAttrAccess(int id) { - this.id = id; - } - - public int getId() { - return id; - } - - public static EntityAttrAccess fromId(int id) { - switch (id) { - case 0: return DENY; - case 1: return VIEW; - case 2: return MODIFY; - default: return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +/** + * Type of access to an entity attribute. + */ +public enum EntityAttrAccess { + DENY(0), + VIEW(1), + MODIFY(2); + + private int id; + + EntityAttrAccess(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public static EntityAttrAccess fromId(int id) { + switch (id) { + case 0: return DENY; + case 1: return VIEW; + case 2: return MODIFY; + default: return null; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/EntityLogAttr.java b/modules/global/src/com/haulmont/cuba/security/entity/EntityLogAttr.java index 71aebec156..dc5ab4d412 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/EntityLogAttr.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/EntityLogAttr.java @@ -1,210 +1,210 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.google.common.base.Strings; -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.Metadata; -import org.apache.commons.lang.StringUtils; - -/** - * Record containing changed entity attribute. - */ -@MetaClass(name = "sec$EntityLogAttr") -@SystemLevel -public class EntityLogAttr extends BaseUuidEntity { - - private static final long serialVersionUID = 4258700403293876630L; - - public static final String VALUE_ID_SUFFIX = "-id"; - public static final String MP_SUFFIX = "-mp"; - public static final String OLD_VALUE_SUFFIX = "-oldVl"; - public static final String OLD_VALUE_ID_SUFFIX = "-oldVlId"; - - @MetaProperty - private EntityLogItem logItem; - - @MetaProperty - private String name; - - @MetaProperty - private String value; - - @MetaProperty - private String oldValue; - - @MetaProperty - private String valueId; - - @MetaProperty - private String oldValueId; - - @MetaProperty - private String messagesPack; - - public EntityLogItem getLogItem() { - return logItem; - } - - public void setLogItem(EntityLogItem logItem) { - this.logItem = logItem; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getOldValue() { - return oldValue; - } - - public void setOldValue(String oldValue) { - this.oldValue = oldValue; - } - - @MetaProperty - public String getDisplayValue() { - return getDisplayValue(getValue()); - } - - @MetaProperty - public String getDisplayOldValue() { - return getDisplayValue(getOldValue()); - } - - protected String getDisplayValue(String value) { - if (StringUtils.isEmpty(value)) { - return value; - } - final String entityName = getLogItem().getEntity(); - com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); - if (metaClass != null) { - com.haulmont.chile.core.model.MetaProperty property = metaClass.getProperty(getName()); - if (property != null) { - if (property.getRange().isDatatype()) { - return value; - } else if (property.getRange().isEnum()) { - String nameKey = property.getRange().asEnumeration().getJavaClass().getSimpleName() + "." + value; - String packageName = property.getRange().asEnumeration().getJavaClass().getPackage().getName(); - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMessage(packageName, nameKey); - } else { - return value; - } - } else { - return value; - } - } else { - return value; - } - } - - public String getValueId() { - return valueId; - } - - public void setValueId(String valueId) { - this.valueId = valueId; - } - - public String getOldValueId() { - return oldValueId; - } - - public void setOldValueId(String oldValueId) { - this.oldValueId = oldValueId; - } - - public String getMessagesPack() { - return messagesPack; - } - - public void setMessagesPack(String messagesPack) { - this.messagesPack = messagesPack; - } - - @MetaProperty - public String getDisplayName() { - String entityName = getLogItem().getEntity(); - String message; - com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); - if (metaClass != null) { - Messages messages = AppBeans.get(Messages.NAME); - message = messages.getTools().getPropertyCaption(metaClass, getName()); - } else { - return getName(); - } - return (message != null ? message : getName()); - } - - private com.haulmont.chile.core.model.MetaClass getClassFromEntityName(String entityName) { - Metadata metadata = AppBeans.get(Metadata.NAME); - com.haulmont.chile.core.model.MetaClass metaClass = metadata.getSession().getClass(entityName); - return metaClass == null ? null : metadata.getExtendedEntities().getEffectiveMetaClass(metaClass); - } - - @MetaProperty - public String getLocValue() { - return getLocValue(value); - } - - @MetaProperty - public String getLocOldValue() { - return getLocValue(oldValue); - } - - public String getLocValue(String value) { - if (Strings.isNullOrEmpty(value)) return value; - - String entityName = getLogItem().getEntity(); - com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); - if (metaClass != null) { - com.haulmont.chile.core.model.MetaProperty property = metaClass.getProperty(name); - if (property != null && property.getRange().isEnum()) { - try { - Enum caller = Enum.valueOf((Class) property.getJavaType(), value); - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMessage(caller); - } catch (IllegalArgumentException ignored) {} - } - } - - if (!StringUtils.isBlank(messagesPack)) { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMessage(messagesPack, value); - } else { - return value; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.google.common.base.Strings; +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.Metadata; +import org.apache.commons.lang.StringUtils; + +/** + * Record containing changed entity attribute. + */ +@MetaClass(name = "sec$EntityLogAttr") +@SystemLevel +public class EntityLogAttr extends BaseUuidEntity { + + private static final long serialVersionUID = 4258700403293876630L; + + public static final String VALUE_ID_SUFFIX = "-id"; + public static final String MP_SUFFIX = "-mp"; + public static final String OLD_VALUE_SUFFIX = "-oldVl"; + public static final String OLD_VALUE_ID_SUFFIX = "-oldVlId"; + + @MetaProperty + private EntityLogItem logItem; + + @MetaProperty + private String name; + + @MetaProperty + private String value; + + @MetaProperty + private String oldValue; + + @MetaProperty + private String valueId; + + @MetaProperty + private String oldValueId; + + @MetaProperty + private String messagesPack; + + public EntityLogItem getLogItem() { + return logItem; + } + + public void setLogItem(EntityLogItem logItem) { + this.logItem = logItem; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getOldValue() { + return oldValue; + } + + public void setOldValue(String oldValue) { + this.oldValue = oldValue; + } + + @MetaProperty + public String getDisplayValue() { + return getDisplayValue(getValue()); + } + + @MetaProperty + public String getDisplayOldValue() { + return getDisplayValue(getOldValue()); + } + + protected String getDisplayValue(String value) { + if (StringUtils.isEmpty(value)) { + return value; + } + final String entityName = getLogItem().getEntity(); + com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); + if (metaClass != null) { + com.haulmont.chile.core.model.MetaProperty property = metaClass.getProperty(getName()); + if (property != null) { + if (property.getRange().isDatatype()) { + return value; + } else if (property.getRange().isEnum()) { + String nameKey = property.getRange().asEnumeration().getJavaClass().getSimpleName() + "." + value; + String packageName = property.getRange().asEnumeration().getJavaClass().getPackage().getName(); + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMessage(packageName, nameKey); + } else { + return value; + } + } else { + return value; + } + } else { + return value; + } + } + + public String getValueId() { + return valueId; + } + + public void setValueId(String valueId) { + this.valueId = valueId; + } + + public String getOldValueId() { + return oldValueId; + } + + public void setOldValueId(String oldValueId) { + this.oldValueId = oldValueId; + } + + public String getMessagesPack() { + return messagesPack; + } + + public void setMessagesPack(String messagesPack) { + this.messagesPack = messagesPack; + } + + @MetaProperty + public String getDisplayName() { + String entityName = getLogItem().getEntity(); + String message; + com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); + if (metaClass != null) { + Messages messages = AppBeans.get(Messages.NAME); + message = messages.getTools().getPropertyCaption(metaClass, getName()); + } else { + return getName(); + } + return (message != null ? message : getName()); + } + + private com.haulmont.chile.core.model.MetaClass getClassFromEntityName(String entityName) { + Metadata metadata = AppBeans.get(Metadata.NAME); + com.haulmont.chile.core.model.MetaClass metaClass = metadata.getSession().getClass(entityName); + return metaClass == null ? null : metadata.getExtendedEntities().getEffectiveMetaClass(metaClass); + } + + @MetaProperty + public String getLocValue() { + return getLocValue(value); + } + + @MetaProperty + public String getLocOldValue() { + return getLocValue(oldValue); + } + + public String getLocValue(String value) { + if (Strings.isNullOrEmpty(value)) return value; + + String entityName = getLogItem().getEntity(); + com.haulmont.chile.core.model.MetaClass metaClass = getClassFromEntityName(entityName); + if (metaClass != null) { + com.haulmont.chile.core.model.MetaProperty property = metaClass.getProperty(name); + if (property != null && property.getRange().isEnum()) { + try { + Enum caller = Enum.valueOf((Class) property.getJavaType(), value); + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMessage(caller); + } catch (IllegalArgumentException ignored) {} + } + } + + if (!StringUtils.isBlank(messagesPack)) { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMessage(messagesPack, value); + } else { + return value; + } + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/EntityLogItem.java b/modules/global/src/com/haulmont/cuba/security/entity/EntityLogItem.java index c36f502843..60517c7d9f 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/EntityLogItem.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/EntityLogItem.java @@ -1,174 +1,174 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.ReferenceToEntity; -import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; -import com.haulmont.cuba.core.entity.annotation.Listeners; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; - -import javax.annotation.PostConstruct; -import javax.persistence.*; -import java.util.Date; -import java.util.Set; -import java.util.UUID; - -/** - * Record containing information about entity lifecycle event. - * Created by EntityLog bean. - */ -@Entity(name = "sec$EntityLog") -@Table(name = "SEC_ENTITY_LOG") -@Listeners("cuba_EntityLogItemDetachListener") -@SystemLevel -public class EntityLogItem extends BaseUuidEntity { - - private static final long serialVersionUID = 5859030306889056606L; - - public enum Type implements EnumClass { - CREATE("C"), - MODIFY("M"), - DELETE("D"), - RESTORE("R"); - - private String id; - - Type(String id) { - this.id = id; - } - - @Override - public String getId() { - return id; - } - - public static Type fromId(String value) { - if ("C".equals(value)) - return CREATE; - else if ("M".equals(value)) - return MODIFY; - else if ("D".equals(value)) - return DELETE; - else if ("R".equals(value)) - return RESTORE; - else - return null; - } - } - - @Column(name = "EVENT_TS") - private Date eventTs; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - private User user; - - @Column(name = "CHANGE_TYPE", length = 1) - private String type; - - @Column(name = "ENTITY", length = 100) - private String entity; - - @Embedded - @EmbeddedParameters(nullAllowed = false) - private ReferenceToEntity entityRef; - - @Transient - @MetaProperty - private Set attributes; - - @Column(name = "CHANGES") - private String changes; - - @PostConstruct - public void init() { - Metadata metadata = AppBeans.get(Metadata.NAME); - entityRef = metadata.create(ReferenceToEntity.class); - } - - public String getEntity() { - return entity; - } - - public void setEntity(String entity) { - this.entity = entity; - } - - public Date getEventTs() { - return eventTs; - } - - public void setEventTs(Date eventTs) { - this.eventTs = eventTs; - } - - public Type getType() { - return Type.fromId(type); - } - - public void setType(Type type) { - this.type = type.getId(); - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public Set getAttributes() { - return attributes; - } - - public void setAttributes(Set attributes) { - this.attributes = attributes; - } - - public String getChanges() { - return changes; - } - - public void setChanges(String changes) { - this.changes = changes; - } - - public ReferenceToEntity getEntityRef() { - return entityRef; - } - - public void setEntityRef(ReferenceToEntity entityRef) { - this.entityRef = entityRef; - } - - public void setObjectEntityId(Object entity) { - if (entityRef == null) { - entityRef = AppBeans.get(Metadata.class).create(ReferenceToEntity.class); - } - entityRef.setObjectEntityId(entity); - } - - public Object getObjectEntityId() { - return entityRef == null ? null : entityRef.getObjectEntityId(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.ReferenceToEntity; +import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters; +import com.haulmont.cuba.core.entity.annotation.Listeners; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; + +import javax.annotation.PostConstruct; +import javax.persistence.*; +import java.util.Date; +import java.util.Set; +import java.util.UUID; + +/** + * Record containing information about entity lifecycle event. + * Created by EntityLog bean. + */ +@Entity(name = "sec$EntityLog") +@Table(name = "SEC_ENTITY_LOG") +@Listeners("cuba_EntityLogItemDetachListener") +@SystemLevel +public class EntityLogItem extends BaseUuidEntity { + + private static final long serialVersionUID = 5859030306889056606L; + + public enum Type implements EnumClass { + CREATE("C"), + MODIFY("M"), + DELETE("D"), + RESTORE("R"); + + private String id; + + Type(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + public static Type fromId(String value) { + if ("C".equals(value)) + return CREATE; + else if ("M".equals(value)) + return MODIFY; + else if ("D".equals(value)) + return DELETE; + else if ("R".equals(value)) + return RESTORE; + else + return null; + } + } + + @Column(name = "EVENT_TS") + private Date eventTs; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + private User user; + + @Column(name = "CHANGE_TYPE", length = 1) + private String type; + + @Column(name = "ENTITY", length = 100) + private String entity; + + @Embedded + @EmbeddedParameters(nullAllowed = false) + private ReferenceToEntity entityRef; + + @Transient + @MetaProperty + private Set attributes; + + @Column(name = "CHANGES") + private String changes; + + @PostConstruct + public void init() { + Metadata metadata = AppBeans.get(Metadata.NAME); + entityRef = metadata.create(ReferenceToEntity.class); + } + + public String getEntity() { + return entity; + } + + public void setEntity(String entity) { + this.entity = entity; + } + + public Date getEventTs() { + return eventTs; + } + + public void setEventTs(Date eventTs) { + this.eventTs = eventTs; + } + + public Type getType() { + return Type.fromId(type); + } + + public void setType(Type type) { + this.type = type.getId(); + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Set getAttributes() { + return attributes; + } + + public void setAttributes(Set attributes) { + this.attributes = attributes; + } + + public String getChanges() { + return changes; + } + + public void setChanges(String changes) { + this.changes = changes; + } + + public ReferenceToEntity getEntityRef() { + return entityRef; + } + + public void setEntityRef(ReferenceToEntity entityRef) { + this.entityRef = entityRef; + } + + public void setObjectEntityId(Object entity) { + if (entityRef == null) { + entityRef = AppBeans.get(Metadata.class).create(ReferenceToEntity.class); + } + entityRef.setObjectEntityId(entity); + } + + public Object getObjectEntityId() { + return entityRef == null ? null : entityRef.getObjectEntityId(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/EntityOp.java b/modules/global/src/com/haulmont/cuba/security/entity/EntityOp.java index 2508b27897..e075cb6b5b 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/EntityOp.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/EntityOp.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -/** - * Type of operation on entity. - */ -public enum EntityOp { - READ("read"), - CREATE("create"), - UPDATE("update"), - DELETE("delete"); - - private String id; - - EntityOp(String id) { - this.id = id; - } - - public String getId() { - return id; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +/** + * Type of operation on entity. + */ +public enum EntityOp { + READ("read"), + CREATE("create"), + UPDATE("update"), + DELETE("delete"); + + private String id; + + EntityOp(String id) { + this.id = id; + } + + public String getId() { + return id; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/FilterEntity.java b/modules/global/src/com/haulmont/cuba/security/entity/FilterEntity.java index a419ddad64..0acdf7e814 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/FilterEntity.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/FilterEntity.java @@ -1,136 +1,136 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.AbstractSearchFolder; -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.EnableRestore; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; - -/** - * A filter component settings. - */ -@Entity(name = "sec$Filter") -@Table(name = "SEC_FILTER") -@NamePattern("%s|name") -@SystemLevel -public class FilterEntity extends StandardEntity { - - @Column(name = "COMPONENT") - protected String componentId; - - @Column(name = "NAME", length = 255) - protected String name; - - @Column(name = "CODE", length = 200) - protected String code; - - @Column(name = "XML") - @Lob - protected String xml; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - protected User user; - - @Transient - protected Boolean isDefault = false; - - @Transient - protected Boolean applyDefault = false; - - @Transient - protected AbstractSearchFolder folder; - - @Transient - protected Boolean isSet = false; - - public String getComponentId() { - return componentId; - } - - public void setComponentId(String componentId) { - this.componentId = componentId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getXml() { - return xml; - } - - public void setXml(String xml) { - this.xml = xml; - } - - public Boolean getIsDefault() { - return isDefault; - } - - public void setIsDefault(Boolean aDefault) { - isDefault = aDefault; - } - - public Boolean getApplyDefault(){ - return applyDefault; - } - - public void setApplyDefault(Boolean applyDefault){ - this.applyDefault=applyDefault; - } - - public AbstractSearchFolder getFolder() { - return folder; - } - - public void setFolder(AbstractSearchFolder folder) { - this.folder = folder; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - - public Boolean getIsSet(){ - return isSet; - } - - public void setIsSet(Boolean isSet){ - this.isSet=isSet; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.AbstractSearchFolder; +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.EnableRestore; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; + +/** + * A filter component settings. + */ +@Entity(name = "sec$Filter") +@Table(name = "SEC_FILTER") +@NamePattern("%s|name") +@SystemLevel +public class FilterEntity extends StandardEntity { + + @Column(name = "COMPONENT") + protected String componentId; + + @Column(name = "NAME", length = 255) + protected String name; + + @Column(name = "CODE", length = 200) + protected String code; + + @Column(name = "XML") + @Lob + protected String xml; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + protected User user; + + @Transient + protected Boolean isDefault = false; + + @Transient + protected Boolean applyDefault = false; + + @Transient + protected AbstractSearchFolder folder; + + @Transient + protected Boolean isSet = false; + + public String getComponentId() { + return componentId; + } + + public void setComponentId(String componentId) { + this.componentId = componentId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getXml() { + return xml; + } + + public void setXml(String xml) { + this.xml = xml; + } + + public Boolean getIsDefault() { + return isDefault; + } + + public void setIsDefault(Boolean aDefault) { + isDefault = aDefault; + } + + public Boolean getApplyDefault(){ + return applyDefault; + } + + public void setApplyDefault(Boolean applyDefault){ + this.applyDefault=applyDefault; + } + + public AbstractSearchFolder getFolder() { + return folder; + } + + public void setFolder(AbstractSearchFolder folder) { + this.folder = folder; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Boolean getIsSet(){ + return isSet; + } + + public void setIsSet(Boolean isSet){ + this.isSet=isSet; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/Group.java b/modules/global/src/com/haulmont/cuba/security/entity/Group.java index 21ec079ffb..f21e79589e 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/Group.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/Group.java @@ -1,103 +1,103 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.Composition; -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.Listeners; -import com.haulmont.cuba.core.entity.annotation.OnDelete; -import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; -import com.haulmont.cuba.core.global.DeletePolicy; -import com.haulmont.chile.core.annotations.NamePattern; - -import javax.persistence.*; -import java.util.List; -import java.util.Set; - -/** - * User access group. - */ -@Entity(name = "sec$Group") -@Table(name = "SEC_GROUP") -@Listeners("cuba_GroupEntityListener") -@NamePattern("%s|name") -@TrackEditScreenHistory -public class Group extends StandardEntity { - - private static final long serialVersionUID = -4581386806900761785L; - - @Column(name = "NAME", nullable = false, unique = true) - private String name; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "PARENT_ID") - private Group parent; - - @OneToMany(mappedBy = "group") - @OrderBy("level") - private List hierarchyList; - - @OneToMany(mappedBy = "group") - @Composition() - @OnDelete(DeletePolicy.CASCADE) - private Set constraints; - - @OneToMany(mappedBy = "group") - @Composition() - @OnDelete(DeletePolicy.CASCADE) - private Set sessionAttributes; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Group getParent() { - return parent; - } - - public void setParent(Group parent) { - this.parent = parent; - } - - public List getHierarchyList() { - return hierarchyList; - } - - public void setHierarchyList(List hierarchyList) { - this.hierarchyList = hierarchyList; - } - - public Set getConstraints() { - return constraints; - } - - public void setConstraints(Set constraints) { - this.constraints = constraints; - } - - public Set getSessionAttributes() { - return sessionAttributes; - } - - public void setSessionAttributes(Set sessionAttributes) { - this.sessionAttributes = sessionAttributes; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.Composition; +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.Listeners; +import com.haulmont.cuba.core.entity.annotation.OnDelete; +import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; +import com.haulmont.cuba.core.global.DeletePolicy; +import com.haulmont.chile.core.annotations.NamePattern; + +import javax.persistence.*; +import java.util.List; +import java.util.Set; + +/** + * User access group. + */ +@Entity(name = "sec$Group") +@Table(name = "SEC_GROUP") +@Listeners("cuba_GroupEntityListener") +@NamePattern("%s|name") +@TrackEditScreenHistory +public class Group extends StandardEntity { + + private static final long serialVersionUID = -4581386806900761785L; + + @Column(name = "NAME", nullable = false, unique = true) + private String name; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "PARENT_ID") + private Group parent; + + @OneToMany(mappedBy = "group") + @OrderBy("level") + private List hierarchyList; + + @OneToMany(mappedBy = "group") + @Composition() + @OnDelete(DeletePolicy.CASCADE) + private Set constraints; + + @OneToMany(mappedBy = "group") + @Composition() + @OnDelete(DeletePolicy.CASCADE) + private Set sessionAttributes; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Group getParent() { + return parent; + } + + public void setParent(Group parent) { + this.parent = parent; + } + + public List getHierarchyList() { + return hierarchyList; + } + + public void setHierarchyList(List hierarchyList) { + this.hierarchyList = hierarchyList; + } + + public Set getConstraints() { + return constraints; + } + + public void setConstraints(Set constraints) { + this.constraints = constraints; + } + + public Set getSessionAttributes() { + return sessionAttributes; + } + + public void setSessionAttributes(Set sessionAttributes) { + this.sessionAttributes = sessionAttributes; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/GroupHierarchy.java b/modules/global/src/com/haulmont/cuba/security/entity/GroupHierarchy.java index 626ba70103..d8a16ef222 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/GroupHierarchy.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/GroupHierarchy.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; - -/** - * User access groups hierarchy. - */ -@Entity(name = "sec$GroupHierarchy") -@Table(name = "SEC_GROUP_HIERARCHY") -@SystemLevel -public class GroupHierarchy extends BaseUuidEntity { - - private static final long serialVersionUID = 8106113488822530560L; - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "GROUP_ID") - private Group group; - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "PARENT_ID") - private Group parent; - - @Column(name = "HIERARCHY_LEVEL") - private Integer level; - - public Group getGroup() { - return group; - } - - public void setGroup(Group group) { - this.group = group; - } - - public Integer getLevel() { - return level; - } - - public void setLevel(Integer level) { - this.level = level; - } - - public Group getParent() { - return parent; - } - - public void setParent(Group parent) { - this.parent = parent; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; + +/** + * User access groups hierarchy. + */ +@Entity(name = "sec$GroupHierarchy") +@Table(name = "SEC_GROUP_HIERARCHY") +@SystemLevel +public class GroupHierarchy extends BaseUuidEntity { + + private static final long serialVersionUID = 8106113488822530560L; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "GROUP_ID") + private Group group; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "PARENT_ID") + private Group parent; + + @Column(name = "HIERARCHY_LEVEL") + private Integer level; + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public Integer getLevel() { + return level; + } + + public void setLevel(Integer level) { + this.level = level; + } + + public Group getParent() { + return parent; + } + + public void setParent(Group parent) { + this.parent = parent; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/LoggedAttribute.java b/modules/global/src/com/haulmont/cuba/security/entity/LoggedAttribute.java index f492c1feca..e666a5ab54 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/LoggedAttribute.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/LoggedAttribute.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; - -/** - * Configuration element of EntityLog bean. - */ -@Entity(name = "sec$LoggedAttribute") -@Table(name = "SEC_LOGGED_ATTR") -@SystemLevel -public class LoggedAttribute extends BaseUuidEntity { - - private static final long serialVersionUID = -615000337312303671L; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "ENTITY_ID") - private LoggedEntity entity; - - @Column(name = "NAME") - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public LoggedEntity getEntity() { - return entity; - } - - public void setEntity(LoggedEntity entity) { - this.entity = entity; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; + +/** + * Configuration element of EntityLog bean. + */ +@Entity(name = "sec$LoggedAttribute") +@Table(name = "SEC_LOGGED_ATTR") +@SystemLevel +public class LoggedAttribute extends BaseUuidEntity { + + private static final long serialVersionUID = -615000337312303671L; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "ENTITY_ID") + private LoggedEntity entity; + + @Column(name = "NAME") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LoggedEntity getEntity() { + return entity; + } + + public void setEntity(LoggedEntity entity) { + this.entity = entity; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/LoggedEntity.java b/modules/global/src/com/haulmont/cuba/security/entity/LoggedEntity.java index c551f48162..55b8f766b0 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/LoggedEntity.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/LoggedEntity.java @@ -1,78 +1,78 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import java.util.Set; - -/** - * Configuration element of EntityLog bean. - */ -@Entity(name = "sec$LoggedEntity") -@Table(name = "SEC_LOGGED_ENTITY") -@SystemLevel -public class LoggedEntity extends BaseUuidEntity { - - private static final long serialVersionUID = 2189206984294705835L; - - @Column(name = "NAME", length = 100) - private String name; - - @Column(name = "AUTO") - private Boolean auto; - - @Column(name = "MANUAL") - private Boolean manual; - - @OneToMany(mappedBy = "entity", cascade = CascadeType.ALL) - private Set attributes; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Boolean getAuto() { - return auto; - } - - public void setAuto(Boolean auto) { - this.auto = auto; - } - - public Boolean getManual() { - return manual; - } - - public void setManual(Boolean manual) { - this.manual = manual; - } - - public Set getAttributes() { - return attributes; - } - - public void setAttributes(Set attributes) { - this.attributes = attributes; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import java.util.Set; + +/** + * Configuration element of EntityLog bean. + */ +@Entity(name = "sec$LoggedEntity") +@Table(name = "SEC_LOGGED_ENTITY") +@SystemLevel +public class LoggedEntity extends BaseUuidEntity { + + private static final long serialVersionUID = 2189206984294705835L; + + @Column(name = "NAME", length = 100) + private String name; + + @Column(name = "AUTO") + private Boolean auto; + + @Column(name = "MANUAL") + private Boolean manual; + + @OneToMany(mappedBy = "entity", cascade = CascadeType.ALL) + private Set attributes; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean getAuto() { + return auto; + } + + public void setAuto(Boolean auto) { + this.auto = auto; + } + + public Boolean getManual() { + return manual; + } + + public void setManual(Boolean manual) { + this.manual = manual; + } + + public Set getAttributes() { + return attributes; + } + + public void setAttributes(Set attributes) { + this.attributes = attributes; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/Permission.java b/modules/global/src/com/haulmont/cuba/security/entity/Permission.java index 809e9a0df6..ee2578972d 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/Permission.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/Permission.java @@ -1,87 +1,87 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; - -/** - * Security permission record. - *
The {@link #value} may be 0,1,2 for {@link PermissionType#ENTITY_ATTR} and 0,1 for others. - */ -@Entity(name = "sec$Permission") -@Table(name = "SEC_PERMISSION") -@SystemLevel -public class Permission extends StandardEntity { - - private static final long serialVersionUID = 4188184934170706381L; - - public static final String TARGET_PATH_DELIMETER = ":"; - - /** @see com.haulmont.cuba.security.entity.PermissionType PermissionType.getId() */ - @Column(name = "PERMISSION_TYPE") - private Integer type; - - @Column(name = "TARGET", length = 100) - private String target; - - /** - * May be 0,1,2 for {@link PermissionType#ENTITY_ATTR} and 0,1 for others - */ - @Column(name = "VALUE") - private Integer value; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "ROLE_ID") - private Role role; - - public Role getRole() { - return role; - } - - public void setRole(Role role) { - this.role = role; - } - - public String getTarget() { - return target; - } - - public void setTarget(String target) { - this.target = target; - } - - public PermissionType getType() { - return type == null ? null : PermissionType.fromId(type); - } - - public void setType(PermissionType type) { - this.type = type == null ? null : type.getId(); - } - - /** See {@link #value} */ - public Integer getValue() { - return value; - } - - /** See {@link #value} */ - public void setValue(Integer value) { - this.value = value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; + +/** + * Security permission record. + *
The {@link #value} may be 0,1,2 for {@link PermissionType#ENTITY_ATTR} and 0,1 for others. + */ +@Entity(name = "sec$Permission") +@Table(name = "SEC_PERMISSION") +@SystemLevel +public class Permission extends StandardEntity { + + private static final long serialVersionUID = 4188184934170706381L; + + public static final String TARGET_PATH_DELIMETER = ":"; + + /** @see com.haulmont.cuba.security.entity.PermissionType PermissionType.getId() */ + @Column(name = "PERMISSION_TYPE") + private Integer type; + + @Column(name = "TARGET", length = 100) + private String target; + + /** + * May be 0,1,2 for {@link PermissionType#ENTITY_ATTR} and 0,1 for others + */ + @Column(name = "VALUE") + private Integer value; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "ROLE_ID") + private Role role; + + public Role getRole() { + return role; + } + + public void setRole(Role role) { + this.role = role; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public PermissionType getType() { + return type == null ? null : PermissionType.fromId(type); + } + + public void setType(PermissionType type) { + this.type = type == null ? null : type.getId(); + } + + /** See {@link #value} */ + public Integer getValue() { + return value; + } + + /** See {@link #value} */ + public void setValue(Integer value) { + this.value = value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/PermissionType.java b/modules/global/src/com/haulmont/cuba/security/entity/PermissionType.java index a14624d2e1..8977c1c55f 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/PermissionType.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/PermissionType.java @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import org.apache.commons.lang.ObjectUtils; - -/** - * Type of permission.
- * {@link #id} - corresponding value stored in the database - */ -public enum PermissionType implements EnumClass { - - /** Permission to screen */ - SCREEN(10), - - /** Permission to entity operation (see {@link EntityOp}) */ - ENTITY_OP(20), - - /** Permission to entity attribute (see {@link EntityAttrAccess}) */ - ENTITY_ATTR(30), - - /** Application-specific permission */ - SPECIFIC(40), - - /** Permissions for UI components in screens */ - UI(50); - - private int id; - - PermissionType(int id) { - this.id = id; - } - - /** Returns corresponding database value */ - @Override - public Integer getId() { - return id; - } - - /** Constructs type from corresponding database value */ - public static PermissionType fromId(Integer id) { - for (PermissionType type : PermissionType.values()) { - if (ObjectUtils.equals(type.getId(), id)) { - return type; - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import org.apache.commons.lang.ObjectUtils; + +/** + * Type of permission.
+ * {@link #id} - corresponding value stored in the database + */ +public enum PermissionType implements EnumClass { + + /** Permission to screen */ + SCREEN(10), + + /** Permission to entity operation (see {@link EntityOp}) */ + ENTITY_OP(20), + + /** Permission to entity attribute (see {@link EntityAttrAccess}) */ + ENTITY_ATTR(30), + + /** Application-specific permission */ + SPECIFIC(40), + + /** Permissions for UI components in screens */ + UI(50); + + private int id; + + PermissionType(int id) { + this.id = id; + } + + /** Returns corresponding database value */ + @Override + public Integer getId() { + return id; + } + + /** Constructs type from corresponding database value */ + public static PermissionType fromId(Integer id) { + for (PermissionType type : PermissionType.values()) { + if (ObjectUtils.equals(type.getId(), id)) { + return type; + } + } + return null; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/Presentation.java b/modules/global/src/com/haulmont/cuba/security/entity/Presentation.java index 598be231b1..0dc26bac65 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/Presentation.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/Presentation.java @@ -1,162 +1,162 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.Creatable; -import com.haulmont.cuba.core.entity.Updatable; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import javax.persistence.*; -import java.util.Date; - -/** - * A screen presentation settings. - */ -@Entity(name = "sec$Presentation") -@Table(name = "SEC_PRESENTATION") -@NamePattern("%s|name") -@SystemLevel -public class Presentation extends BaseUuidEntity implements Creatable, Updatable { - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @Column(name = "COMPONENT") - private String componentId; - - @Column(name = "NAME", length = 255) - private String name; - - @Column(name = "XML", length = 4000) - private String xml; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - private User user; - - @Column(name = "IS_AUTO_SAVE") - private Boolean autoSave; - - @Column(name = "UPDATE_TS") - protected Date updateTs; - - @Column(name = "UPDATED_BY", length = 50) - protected String updatedBy; - - @Transient - private Boolean isDefault; - - private static final long serialVersionUID = -3151934186797540532L; - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - public Boolean getAutoSave() { - return autoSave; - } - - public void setAutoSave(Boolean autoSave) { - this.autoSave = autoSave; - } - - public String getComponentId() { - return componentId; - } - - public void setComponentId(String componentId) { - this.componentId = componentId; - } - - public Boolean getDefault() { - return isDefault; - } - - public void setDefault(Boolean aDefault) { - isDefault = aDefault; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getXml() { - return xml; - } - - public void setXml(String xml) { - this.xml = xml; - } - - @Override - public String getUpdatedBy() { - return updatedBy; - } - - @Override - public Date getUpdateTs() { - return updateTs; - } - - @Override - public void setUpdateTs(Date updateTs) { - this.updateTs = updateTs; - } - - @Override - public void setUpdatedBy(String updatedBy) { - this.updatedBy = updatedBy; - } - - @Override - public String toString() { - return getName(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.Creatable; +import com.haulmont.cuba.core.entity.Updatable; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import javax.persistence.*; +import java.util.Date; + +/** + * A screen presentation settings. + */ +@Entity(name = "sec$Presentation") +@Table(name = "SEC_PRESENTATION") +@NamePattern("%s|name") +@SystemLevel +public class Presentation extends BaseUuidEntity implements Creatable, Updatable { + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @Column(name = "COMPONENT") + private String componentId; + + @Column(name = "NAME", length = 255) + private String name; + + @Column(name = "XML", length = 4000) + private String xml; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + private User user; + + @Column(name = "IS_AUTO_SAVE") + private Boolean autoSave; + + @Column(name = "UPDATE_TS") + protected Date updateTs; + + @Column(name = "UPDATED_BY", length = 50) + protected String updatedBy; + + @Transient + private Boolean isDefault; + + private static final long serialVersionUID = -3151934186797540532L; + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public Boolean getAutoSave() { + return autoSave; + } + + public void setAutoSave(Boolean autoSave) { + this.autoSave = autoSave; + } + + public String getComponentId() { + return componentId; + } + + public void setComponentId(String componentId) { + this.componentId = componentId; + } + + public Boolean getDefault() { + return isDefault; + } + + public void setDefault(Boolean aDefault) { + isDefault = aDefault; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getXml() { + return xml; + } + + public void setXml(String xml) { + this.xml = xml; + } + + @Override + public String getUpdatedBy() { + return updatedBy; + } + + @Override + public Date getUpdateTs() { + return updateTs; + } + + @Override + public void setUpdateTs(Date updateTs) { + this.updateTs = updateTs; + } + + @Override + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + @Override + public String toString() { + return getName(); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/Role.java b/modules/global/src/com/haulmont/cuba/security/entity/Role.java index bf001827b3..d554727d7f 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/Role.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/Role.java @@ -1,111 +1,111 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.Composition; -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.EnableRestore; -import com.haulmont.cuba.core.entity.annotation.OnDelete; -import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; -import com.haulmont.cuba.core.global.DeletePolicy; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import java.util.Set; - -/** - * User role. - */ -@Entity(name = "sec$Role") -@Table(name = "SEC_ROLE") -@NamePattern("%s [%s]|locName,name") -@TrackEditScreenHistory -public class Role extends StandardEntity { - - private static final long serialVersionUID = -4889116218059626402L; - - @Column(name = "NAME", nullable = false, unique = true) - private String name; - - @Column(name = "LOC_NAME") - private String locName; - - @Column(name = "DESCRIPTION", length = 1000) - private String description; - - @Column(name = "ROLE_TYPE") - private Integer type; - - @Column(name = "IS_DEFAULT_ROLE") - private Boolean defaultRole; - - @OneToMany(mappedBy = "role") - @OnDelete(DeletePolicy.CASCADE) - @Composition - private Set permissions; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public RoleType getType() { - return RoleType.fromId(type); - } - - public void setType(RoleType type) { - this.type = type == null ? null : type.getId(); - } - - public Set getPermissions() { - return permissions; - } - - public void setPermissions(Set permissions) { - this.permissions = permissions; - } - - public String getLocName() { - return locName; - } - - public void setLocName(String locName) { - this.locName = locName; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Boolean getDefaultRole() { - return defaultRole; - } - - public void setDefaultRole(Boolean defaultRole) { - this.defaultRole = defaultRole; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.Composition; +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.EnableRestore; +import com.haulmont.cuba.core.entity.annotation.OnDelete; +import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; +import com.haulmont.cuba.core.global.DeletePolicy; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import java.util.Set; + +/** + * User role. + */ +@Entity(name = "sec$Role") +@Table(name = "SEC_ROLE") +@NamePattern("%s [%s]|locName,name") +@TrackEditScreenHistory +public class Role extends StandardEntity { + + private static final long serialVersionUID = -4889116218059626402L; + + @Column(name = "NAME", nullable = false, unique = true) + private String name; + + @Column(name = "LOC_NAME") + private String locName; + + @Column(name = "DESCRIPTION", length = 1000) + private String description; + + @Column(name = "ROLE_TYPE") + private Integer type; + + @Column(name = "IS_DEFAULT_ROLE") + private Boolean defaultRole; + + @OneToMany(mappedBy = "role") + @OnDelete(DeletePolicy.CASCADE) + @Composition + private Set permissions; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public RoleType getType() { + return RoleType.fromId(type); + } + + public void setType(RoleType type) { + this.type = type == null ? null : type.getId(); + } + + public Set getPermissions() { + return permissions; + } + + public void setPermissions(Set permissions) { + this.permissions = permissions; + } + + public String getLocName() { + return locName; + } + + public void setLocName(String locName) { + this.locName = locName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getDefaultRole() { + return defaultRole; + } + + public void setDefaultRole(Boolean defaultRole) { + this.defaultRole = defaultRole; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/ScreenHistoryEntity.java b/modules/global/src/com/haulmont/cuba/security/entity/ScreenHistoryEntity.java index e2bd934b31..35a6072b85 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/ScreenHistoryEntity.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/ScreenHistoryEntity.java @@ -1,138 +1,138 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.Creatable; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.UserFormatTools; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.security.global.UserSession; - -import javax.annotation.PostConstruct; -import javax.persistence.*; -import java.util.Date; -import java.util.UUID; - -/** - * Screen history item. - */ -@Entity(name = "sec$ScreenHistory") -@Table(name = "SEC_SCREEN_HISTORY") -@SystemLevel -public class ScreenHistoryEntity extends BaseUuidEntity implements Creatable { - - private static final long serialVersionUID = 1L; - - @Column(name = "CREATE_TS") - protected Date createTs; - - @Column(name = "CREATED_BY", length = 50) - protected String createdBy; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - protected User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "SUBSTITUTED_USER_ID") - protected User substitutedUser; - - @Column(name = "CAPTION", length = 255) - protected String caption; - - @Column(name = "URL", length = 4000) - protected String url; - - @Column(name = "ENTITY_ID") - protected UUID entityId; - - @Override - public Date getCreateTs() { - return createTs; - } - - @Override - public void setCreateTs(Date createTs) { - this.createTs = createTs; - } - - @Override - public String getCreatedBy() { - return createdBy; - } - - @Override - public void setCreatedBy(String createdBy) { - this.createdBy = createdBy; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public UUID getEntityId() { - return entityId; - } - - public void setEntityId(UUID entityId) { - this.entityId = entityId; - } - - public User getSubstitutedUser() { - return substitutedUser; - } - - public void setSubstitutedUser(User substitutedUser) { - this.substitutedUser = substitutedUser; - } - - @MetaProperty - public String getDisplayUser() { - UserFormatTools formatTools = AppBeans.get(UserFormatTools.NAME); - return formatTools.formatUser(user, substitutedUser); - } - - @PostConstruct - protected void init() { - UserSession userSession = AppBeans.get(UserSessionSource.class).getUserSession(); - setUser(userSession.getUser()); - setSubstitutedUser(userSession.getSubstitutedUser()); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.Creatable; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.UserFormatTools; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.security.global.UserSession; + +import javax.annotation.PostConstruct; +import javax.persistence.*; +import java.util.Date; +import java.util.UUID; + +/** + * Screen history item. + */ +@Entity(name = "sec$ScreenHistory") +@Table(name = "SEC_SCREEN_HISTORY") +@SystemLevel +public class ScreenHistoryEntity extends BaseUuidEntity implements Creatable { + + private static final long serialVersionUID = 1L; + + @Column(name = "CREATE_TS") + protected Date createTs; + + @Column(name = "CREATED_BY", length = 50) + protected String createdBy; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + protected User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "SUBSTITUTED_USER_ID") + protected User substitutedUser; + + @Column(name = "CAPTION", length = 255) + protected String caption; + + @Column(name = "URL", length = 4000) + protected String url; + + @Column(name = "ENTITY_ID") + protected UUID entityId; + + @Override + public Date getCreateTs() { + return createTs; + } + + @Override + public void setCreateTs(Date createTs) { + this.createTs = createTs; + } + + @Override + public String getCreatedBy() { + return createdBy; + } + + @Override + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public UUID getEntityId() { + return entityId; + } + + public void setEntityId(UUID entityId) { + this.entityId = entityId; + } + + public User getSubstitutedUser() { + return substitutedUser; + } + + public void setSubstitutedUser(User substitutedUser) { + this.substitutedUser = substitutedUser; + } + + @MetaProperty + public String getDisplayUser() { + UserFormatTools formatTools = AppBeans.get(UserFormatTools.NAME); + return formatTools.formatUser(user, substitutedUser); + } + + @PostConstruct + protected void init() { + UserSession userSession = AppBeans.get(UserSessionSource.class).getUserSession(); + setUser(userSession.getUser()); + setSubstitutedUser(userSession.getSubstitutedUser()); + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/SearchFolder.java b/modules/global/src/com/haulmont/cuba/security/entity/SearchFolder.java index a4a7287608..d5d022f7c5 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/SearchFolder.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/SearchFolder.java @@ -1,104 +1,104 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.AbstractSearchFolder; -import com.haulmont.cuba.core.entity.annotation.EnableRestore; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.global.UserSessionSource; - -import javax.persistence.*; - -/** - * Search folder settings. - * - */ -@Entity(name = "sec$SearchFolder") -@Table(name = "SEC_SEARCH_FOLDER") -@PrimaryKeyJoinColumn(name = "FOLDER_ID", referencedColumnName = "ID") -@DiscriminatorValue("S") -@EnableRestore -public class SearchFolder extends AbstractSearchFolder { - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - protected User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "PRESENTATION_ID") - protected Presentation presentation; - - @Column(name="IS_SET") - protected Boolean isSet = false; - - @Column(name="ENTITY_TYPE") - protected String entityType; - - @Override - public void copyFrom(AbstractSearchFolder srcFolder) { - super.copyFrom(srcFolder); - - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - setUser(sessionSource.getUserSession().getUser()); - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public Presentation getPresentation() { - return presentation; - } - - public void setPresentation(Presentation presentation) { - this.presentation = presentation; - } - - @Override - public String toString() { - return getName(); - } - - @Override - public String getCaption() { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage(name); - } - - public Boolean getIsSet(){ - return isSet; - } - - public void setIsSet(Boolean isSet){ - this.isSet=isSet; - } - - public String getEntityType(){ - return entityType; - } - - public void setEntityType(String entityType){ - this.entityType=entityType; - } - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.AbstractSearchFolder; +import com.haulmont.cuba.core.entity.annotation.EnableRestore; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.global.UserSessionSource; + +import javax.persistence.*; + +/** + * Search folder settings. + * + */ +@Entity(name = "sec$SearchFolder") +@Table(name = "SEC_SEARCH_FOLDER") +@PrimaryKeyJoinColumn(name = "FOLDER_ID", referencedColumnName = "ID") +@DiscriminatorValue("S") +@EnableRestore +public class SearchFolder extends AbstractSearchFolder { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + protected User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "PRESENTATION_ID") + protected Presentation presentation; + + @Column(name="IS_SET") + protected Boolean isSet = false; + + @Column(name="ENTITY_TYPE") + protected String entityType; + + @Override + public void copyFrom(AbstractSearchFolder srcFolder) { + super.copyFrom(srcFolder); + + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + setUser(sessionSource.getUserSession().getUser()); + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Presentation getPresentation() { + return presentation; + } + + public void setPresentation(Presentation presentation) { + this.presentation = presentation; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public String getCaption() { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage(name); + } + + public Boolean getIsSet(){ + return isSet; + } + + public void setIsSet(Boolean isSet){ + this.isSet=isSet; + } + + public String getEntityType(){ + return entityType; + } + + public void setEntityType(String entityType){ + this.entityType=entityType; + } + +} diff --git a/modules/global/src/com/haulmont/cuba/security/entity/SessionAttribute.java b/modules/global/src/com/haulmont/cuba/security/entity/SessionAttribute.java index 0ea2d33e79..1d94bbeedb 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/SessionAttribute.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/SessionAttribute.java @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Messages; - -import javax.persistence.*; - -@Entity(name = "sec$SessionAttribute") -@Table(name = "SEC_SESSION_ATTR") -@SystemLevel -public class SessionAttribute extends StandardEntity { - - private static final long serialVersionUID = 4886168889020578592L; - - @Column(name = "NAME", length = 50) - private String name; - - @Column(name = "STR_VALUE", length = 1000) - private String stringValue; - - @Column(name = "DATATYPE", length = 20) - private String datatype; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "GROUP_ID") - private Group group; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - public Group getGroup() { - return group; - } - - public void setGroup(Group group) { - this.group = group; - } - - @MetaProperty - public String getDatatypeCaption() { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessage("Datatype." + datatype); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Messages; + +import javax.persistence.*; + +@Entity(name = "sec$SessionAttribute") +@Table(name = "SEC_SESSION_ATTR") +@SystemLevel +public class SessionAttribute extends StandardEntity { + + private static final long serialVersionUID = 4886168889020578592L; + + @Column(name = "NAME", length = 50) + private String name; + + @Column(name = "STR_VALUE", length = 1000) + private String stringValue; + + @Column(name = "DATATYPE", length = 20) + private String datatype; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "GROUP_ID") + private Group group; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + @MetaProperty + public String getDatatypeCaption() { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessage("Datatype." + datatype); + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/entity/User.java b/modules/global/src/com/haulmont/cuba/security/entity/User.java index f7f0229add..f993625fa2 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/User.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/User.java @@ -1,265 +1,265 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.Composition; -import com.haulmont.chile.core.annotations.NamePattern; -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.*; -import com.haulmont.cuba.core.global.DeletePolicy; -import com.haulmont.cuba.core.sys.AppContext; -import org.apache.commons.lang.StringUtils; - -import javax.persistence.*; -import java.text.MessageFormat; -import java.util.List; - -/** - * User - */ -@Entity(name = "sec$User") -@Table(name = "SEC_USER") -@Listeners("cuba_UserEntityListener") -@NamePattern("#getCaption|login,name") -@TrackEditScreenHistory -public class User extends StandardEntity { - - private static final long serialVersionUID = 5007187642916030394L; - - @Column(name = "LOGIN", length = 50, nullable = false) - protected String login; - - @SystemLevel - @Column(name = "LOGIN_LC", length = 50, nullable = false) - protected String loginLowerCase; - - @SystemLevel - @Column(name = "PASSWORD", length = 255) - protected String password; - - @Column(name = "NAME", length = 255) - protected String name; - - @Column(name = "FIRST_NAME", length = 255) - protected String firstName; - - @Column(name = "LAST_NAME", length = 255) - protected String lastName; - - @Column(name = "MIDDLE_NAME", length = 255) - protected String middleName; - - @Column(name = "POSITION_", length = 255) - protected String position; - - @Column(name = "EMAIL", length = 100) - protected String email; - - @Column(name = "LANGUAGE_", length = 20) - protected String language; - - @Column(name = "TIME_ZONE") - protected String timeZone; - - @Column(name = "TIME_ZONE_AUTO") - protected Boolean timeZoneAuto; - - @Column(name = "ACTIVE") - protected Boolean active = true; - - @Column(name = "CHANGE_PASSWORD_AT_LOGON") - protected Boolean changePasswordAtNextLogon = false; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "GROUP_ID") - @OnDeleteInverse(DeletePolicy.DENY) - protected Group group; - - @OneToMany(mappedBy = "user") - @OrderBy("createTs") - @Composition - protected List userRoles; - - @OneToMany(mappedBy = "user") - @OrderBy("createTs") - @Composition - protected List substitutions; - - @Column(name = "IP_MASK", length = 200) - protected String ipMask; - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public String getLoginLowerCase() { - return loginLowerCase; - } - - public void setLoginLowerCase(String loginLowerCase) { - this.loginLowerCase = loginLowerCase; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Group getGroup() { - return group; - } - - public void setGroup(Group group) { - this.group = group; - } - - public List getUserRoles() { - return userRoles; - } - - public void setUserRoles(List userRoles) { - this.userRoles = userRoles; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getTimeZone() { - return timeZone; - } - - public void setTimeZone(String timeZone) { - this.timeZone = timeZone; - } - - public Boolean getTimeZoneAuto() { - return timeZoneAuto; - } - - public void setTimeZoneAuto(Boolean timeZoneAuto) { - this.timeZoneAuto = timeZoneAuto; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getMiddleName() { - return middleName; - } - - public void setMiddleName(String middleName) { - this.middleName = middleName; - } - - public String getPosition() { - return position; - } - - public void setPosition(String position) { - this.position = position; - } - - public List getSubstitutions() { - return substitutions; - } - - public void setSubstitutions(List substitutions) { - this.substitutions = substitutions; - } - - public Boolean getActive() { - return active; - } - - public void setActive(Boolean active) { - this.active = active; - } - - public String getIpMask() { - return ipMask; - } - - public void setIpMask(String ipMask) { - this.ipMask = ipMask; - } - - public String getCaption() { - String pattern = AppContext.getProperty("cuba.user.namePattern"); - if (StringUtils.isBlank(pattern)) { - pattern = "{1} [{0}]"; - } - MessageFormat fmt = new MessageFormat(pattern); - return StringUtils.trimToEmpty(fmt.format(new Object[]{ - StringUtils.trimToEmpty(login), - StringUtils.trimToEmpty(name) - })); - } - - public Boolean getChangePasswordAtNextLogon() { - return changePasswordAtNextLogon; - } - - public void setChangePasswordAtNextLogon(Boolean changePasswordAtNextLogon) { - this.changePasswordAtNextLogon = changePasswordAtNextLogon; - } - - @Transient - public String getSalt() { - return id != null ? id.toString() : ""; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.Composition; +import com.haulmont.chile.core.annotations.NamePattern; +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.*; +import com.haulmont.cuba.core.global.DeletePolicy; +import com.haulmont.cuba.core.sys.AppContext; +import org.apache.commons.lang.StringUtils; + +import javax.persistence.*; +import java.text.MessageFormat; +import java.util.List; + +/** + * User + */ +@Entity(name = "sec$User") +@Table(name = "SEC_USER") +@Listeners("cuba_UserEntityListener") +@NamePattern("#getCaption|login,name") +@TrackEditScreenHistory +public class User extends StandardEntity { + + private static final long serialVersionUID = 5007187642916030394L; + + @Column(name = "LOGIN", length = 50, nullable = false) + protected String login; + + @SystemLevel + @Column(name = "LOGIN_LC", length = 50, nullable = false) + protected String loginLowerCase; + + @SystemLevel + @Column(name = "PASSWORD", length = 255) + protected String password; + + @Column(name = "NAME", length = 255) + protected String name; + + @Column(name = "FIRST_NAME", length = 255) + protected String firstName; + + @Column(name = "LAST_NAME", length = 255) + protected String lastName; + + @Column(name = "MIDDLE_NAME", length = 255) + protected String middleName; + + @Column(name = "POSITION_", length = 255) + protected String position; + + @Column(name = "EMAIL", length = 100) + protected String email; + + @Column(name = "LANGUAGE_", length = 20) + protected String language; + + @Column(name = "TIME_ZONE") + protected String timeZone; + + @Column(name = "TIME_ZONE_AUTO") + protected Boolean timeZoneAuto; + + @Column(name = "ACTIVE") + protected Boolean active = true; + + @Column(name = "CHANGE_PASSWORD_AT_LOGON") + protected Boolean changePasswordAtNextLogon = false; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "GROUP_ID") + @OnDeleteInverse(DeletePolicy.DENY) + protected Group group; + + @OneToMany(mappedBy = "user") + @OrderBy("createTs") + @Composition + protected List userRoles; + + @OneToMany(mappedBy = "user") + @OrderBy("createTs") + @Composition + protected List substitutions; + + @Column(name = "IP_MASK", length = 200) + protected String ipMask; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getLoginLowerCase() { + return loginLowerCase; + } + + public void setLoginLowerCase(String loginLowerCase) { + this.loginLowerCase = loginLowerCase; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public List getUserRoles() { + return userRoles; + } + + public void setUserRoles(List userRoles) { + this.userRoles = userRoles; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getTimeZone() { + return timeZone; + } + + public void setTimeZone(String timeZone) { + this.timeZone = timeZone; + } + + public Boolean getTimeZoneAuto() { + return timeZoneAuto; + } + + public void setTimeZoneAuto(Boolean timeZoneAuto) { + this.timeZoneAuto = timeZoneAuto; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public List getSubstitutions() { + return substitutions; + } + + public void setSubstitutions(List substitutions) { + this.substitutions = substitutions; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + public String getIpMask() { + return ipMask; + } + + public void setIpMask(String ipMask) { + this.ipMask = ipMask; + } + + public String getCaption() { + String pattern = AppContext.getProperty("cuba.user.namePattern"); + if (StringUtils.isBlank(pattern)) { + pattern = "{1} [{0}]"; + } + MessageFormat fmt = new MessageFormat(pattern); + return StringUtils.trimToEmpty(fmt.format(new Object[]{ + StringUtils.trimToEmpty(login), + StringUtils.trimToEmpty(name) + })); + } + + public Boolean getChangePasswordAtNextLogon() { + return changePasswordAtNextLogon; + } + + public void setChangePasswordAtNextLogon(Boolean changePasswordAtNextLogon) { + this.changePasswordAtNextLogon = changePasswordAtNextLogon; + } + + @Transient + public String getSalt() { + return id != null ? id.toString() : ""; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/UserRole.java b/modules/global/src/com/haulmont/cuba/security/entity/UserRole.java index 65a654aa77..f270015162 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/UserRole.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/UserRole.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.DeletePolicy; - -import javax.persistence.*; - -/** - * Link between users and roles. - * - */ -@Entity(name = "sec$UserRole") -@Table(name = "SEC_USER_ROLE") -@SystemLevel -public class UserRole extends StandardEntity { - - private static final long serialVersionUID = 8543853035155300992L; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID") - @OnDeleteInverse(DeletePolicy.CASCADE) - private User user; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "ROLE_ID") - @OnDeleteInverse(DeletePolicy.CASCADE) - private Role role; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public Role getRole() { - return role; - } - - public void setRole(Role role) { - this.role = role; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.DeletePolicy; + +import javax.persistence.*; + +/** + * Link between users and roles. + * + */ +@Entity(name = "sec$UserRole") +@Table(name = "SEC_USER_ROLE") +@SystemLevel +public class UserRole extends StandardEntity { + + private static final long serialVersionUID = 8543853035155300992L; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID") + @OnDeleteInverse(DeletePolicy.CASCADE) + private User user; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "ROLE_ID") + @OnDeleteInverse(DeletePolicy.CASCADE) + private Role role; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Role getRole() { + return role; + } + + public void setRole(Role role) { + this.role = role; + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/entity/UserSessionEntity.java b/modules/global/src/com/haulmont/cuba/security/entity/UserSessionEntity.java index c96c58b5f1..abdc6105d2 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/UserSessionEntity.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/UserSessionEntity.java @@ -1,112 +1,112 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.entity; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -import java.util.Date; - -/** - * Non-persistent entity to show user sessions list in UI. - * - */ -@MetaClass(name = "sec$UserSessionEntity") -@SystemLevel -public class UserSessionEntity extends BaseUuidEntity { - - private static final long serialVersionUID = 7730031482721158275L; - - @MetaProperty - private String login; - @MetaProperty - private String userName; - @MetaProperty - private String address; - @MetaProperty - private String clientInfo; - @MetaProperty - private Date since; - @MetaProperty - private Date lastUsedTs; - @MetaProperty - private Boolean system; - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public Date getSince() { - return since; - } - - public void setSince(Date since) { - this.since = since; - } - - public Date getLastUsedTs() { - return lastUsedTs; - } - - public void setLastUsedTs(Date lastUsedTs) { - this.lastUsedTs = lastUsedTs; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getClientInfo() { - return clientInfo; - } - - public void setClientInfo(String clientInfo) { - this.clientInfo = clientInfo; - } - - public Boolean getSystem() { - return system; - } - - public void setSystem(Boolean system) { - this.system = system; - } - - @Override - public String toString() { - return "id=" + getId() + ", login=" + login + ", user=" + userName + ", since=" + since + ", last=" + lastUsedTs; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.entity; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +import java.util.Date; + +/** + * Non-persistent entity to show user sessions list in UI. + * + */ +@MetaClass(name = "sec$UserSessionEntity") +@SystemLevel +public class UserSessionEntity extends BaseUuidEntity { + + private static final long serialVersionUID = 7730031482721158275L; + + @MetaProperty + private String login; + @MetaProperty + private String userName; + @MetaProperty + private String address; + @MetaProperty + private String clientInfo; + @MetaProperty + private Date since; + @MetaProperty + private Date lastUsedTs; + @MetaProperty + private Boolean system; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public Date getSince() { + return since; + } + + public void setSince(Date since) { + this.since = since; + } + + public Date getLastUsedTs() { + return lastUsedTs; + } + + public void setLastUsedTs(Date lastUsedTs) { + this.lastUsedTs = lastUsedTs; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getClientInfo() { + return clientInfo; + } + + public void setClientInfo(String clientInfo) { + this.clientInfo = clientInfo; + } + + public Boolean getSystem() { + return system; + } + + public void setSystem(Boolean system) { + this.system = system; + } + + @Override + public String toString() { + return "id=" + getId() + ", login=" + login + ", user=" + userName + ", since=" + since + ", last=" + lastUsedTs; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/UserSetting.java b/modules/global/src/com/haulmont/cuba/security/entity/UserSetting.java index 680a3504f2..907751e43e 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/UserSetting.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/UserSetting.java @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.ClientType; - -import javax.persistence.*; - -/** - * Record for user setting. - * Used by UserSettingServiceBean. - * - */ -@Entity(name = "sec$UserSetting") -@Table(name = "SEC_USER_SETTING") -@SystemLevel -public class UserSetting extends BaseUuidEntity { - - private static final long serialVersionUID = -4324101071593066529L; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "USER_ID") - private User user; - - @Column(name = "CLIENT_TYPE", length = 1) - private String clientType; - - @Column(name = "NAME", length = 255) - private String name; - - @Lob - @Column(name = "VALUE") - private String value; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public ClientType getClientType() { - return ClientType.fromId(clientType); - } - - public void setClientType(ClientType clientType) { - this.clientType = clientType == null ? null : clientType.getId(); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.ClientType; + +import javax.persistence.*; + +/** + * Record for user setting. + * Used by UserSettingServiceBean. + * + */ +@Entity(name = "sec$UserSetting") +@Table(name = "SEC_USER_SETTING") +@SystemLevel +public class UserSetting extends BaseUuidEntity { + + private static final long serialVersionUID = -4324101071593066529L; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USER_ID") + private User user; + + @Column(name = "CLIENT_TYPE", length = 1) + private String clientType; + + @Column(name = "NAME", length = 255) + private String name; + + @Lob + @Column(name = "VALUE") + private String value; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public ClientType getClientType() { + return ClientType.fromId(clientType); + } + + public void setClientType(ClientType clientType) { + this.clientType = clientType == null ? null : clientType.getId(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/UserSubstitution.java b/modules/global/src/com/haulmont/cuba/security/entity/UserSubstitution.java index 096c00c57d..6a7098ea75 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/UserSubstitution.java +++ b/modules/global/src/com/haulmont/cuba/security/entity/UserSubstitution.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.entity; - -import com.haulmont.cuba.core.entity.StandardEntity; -import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; -import com.haulmont.cuba.core.global.DeletePolicy; - -import javax.persistence.*; -import java.util.Date; - -/** - * User substitution definition. - * - */ -@Entity(name = "sec$UserSubstitution") -@Table(name = "SEC_USER_SUBSTITUTION") -@SystemLevel -public class UserSubstitution extends StandardEntity { - - private static final long serialVersionUID = -1260499554824220311L; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID") - protected User user; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "SUBSTITUTED_USER_ID") - @OnDeleteInverse(DeletePolicy.CASCADE) - protected User substitutedUser; - - @Column(name = "START_DATE") - @Temporal(TemporalType.DATE) - protected Date startDate; - - @Column(name = "END_DATE") - @Temporal(TemporalType.DATE) - protected Date endDate; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public User getSubstitutedUser() { - return substitutedUser; - } - - public void setSubstitutedUser(User substitutedUser) { - this.substitutedUser = substitutedUser; - } - - public Date getStartDate() { - return startDate; - } - - public void setStartDate(Date startDate) { - this.startDate = startDate; - } - - public Date getEndDate() { - return endDate; - } - - public void setEndDate(Date endDate) { - this.endDate = endDate; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.entity; + +import com.haulmont.cuba.core.entity.StandardEntity; +import com.haulmont.cuba.core.entity.annotation.OnDeleteInverse; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; +import com.haulmont.cuba.core.global.DeletePolicy; + +import javax.persistence.*; +import java.util.Date; + +/** + * User substitution definition. + * + */ +@Entity(name = "sec$UserSubstitution") +@Table(name = "SEC_USER_SUBSTITUTION") +@SystemLevel +public class UserSubstitution extends StandardEntity { + + private static final long serialVersionUID = -1260499554824220311L; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID") + protected User user; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "SUBSTITUTED_USER_ID") + @OnDeleteInverse(DeletePolicy.CASCADE) + protected User substitutedUser; + + @Column(name = "START_DATE") + @Temporal(TemporalType.DATE) + protected Date startDate; + + @Column(name = "END_DATE") + @Temporal(TemporalType.DATE) + protected Date endDate; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public User getSubstitutedUser() { + return substitutedUser; + } + + public void setSubstitutedUser(User substitutedUser) { + this.substitutedUser = substitutedUser; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/entity/messages.properties b/modules/global/src/com/haulmont/cuba/security/entity/messages.properties index 9eb1814de4..8712d40ed9 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/messages.properties +++ b/modules/global/src/com/haulmont/cuba/security/entity/messages.properties @@ -1,233 +1,233 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -Constraint=Constraint -Constraint.entityName=Entity Name -Constraint.joinClause=Join Clause -Constraint.whereClause=Where Clause -Constraint.group=Group -Constraint.groovyScript = Groovy Script -Constraint.filterXml = Filter XML -Constraint.code = Code -Constraint.checkType = Check Type -Constraint.operationType = Operation Type -Constraint.isActive = Is Active - -LocalizedConstraintMessage=Localized Constraint Message -LocalizedConstraintMessage.entityName=Entity Name -LocalizedConstraintMessage.operationType=Operation Type -LocalizedConstraintMessage.values=Localized Values - -SessionAttribute=Session Attribute -SessionAttribute.name=Name -SessionAttribute.stringValue=Value -SessionAttribute.datatype=Data Type -SessionAttribute.datatypeCaption=Data Type -SessionAttribute.group = Group - -Group=Group -Group.name=Name -Group.parent=Parent Group -Group.hierarchyList=Hierarchy List -Group.constraints=Constraints -Group.sessionAttributes = Session Attributes - -LoggedAttribute=Logged Attribute -LoggedAttribute.entity=Logged Entity -LoggedAttribute.name=Name - -LoggedEntity=Logged Entity -LoggedEntity.name=Name -LoggedEntity.auto=Auto -LoggedEntity.manual=Manual -LoggedEntity.attributes=Attributes - -Permission=Permission -Permission.type=Type -Permission.target=Target -Permission.value=Value -Permission.role=Role - -Role=Role -Role.name=Name -Role.type=Type -Role.permissions=Permissions -Role.description=Description -Role.defaultRole=Default Role -Role.locName=Localized Name - -RoleType=Role Type -RoleType.STANDARD=Standard -RoleType.SUPER=Super -RoleType.READONLY=Read-only -RoleType.DENYING=Denying - -User=User -User.login=Login -User.password=Password -User.name=Name -User.firstName=First Name -User.lastName=Last Name -User.middleName=Middle Name -User.position=Position -User.language=Language -User.timeZone=Time Zone -User.timeZoneAuto=Autodetect Time Zone -User.email=Email -User.group=Group -User.userRoles=User Roles -User.substitutions=Substitutions -User.ipMask=Permitted IP Mask -User.changePasswordAtNextLogon=Change Password at Next Logon -User.active=Active -User.loginLowerCase=Login - -UserRole=User role -UserRole.user=User -UserRole.role=Role - -UserSessionEntity=User Session Entity -UserSessionEntity.id=ID -UserSessionEntity.login=Login -UserSessionEntity.userName=User Name -UserSessionEntity.since=Active Since -UserSessionEntity.lastUsedTs=Last Used On -UserSessionEntity.address=Address -UserSessionEntity.clientInfo=Client Info -UserSessionEntity.system=System - -UserSetting=User Settings -UserSetting.user=User -UserSetting.clientType=Client Type -UserSetting.name=Name -UserSetting.value=Value - -UserSubstitution=User Substitution -UserSubstitution.user=User -UserSubstitution.substitutedUser=Substituted User -UserSubstitution.startDate=Start Date -UserSubstitution.endDate=End Date - -PermissionType.SCREEN=Screen -PermissionType.ENTITY_OP=Entity Operation -PermissionType.ENTITY_ATTR=Entity Attribute -PermissionType.SPECIFIC=Specific -PermissionType.UI=UI - -ScreenHistoryEntity=Screen History Entity -ScreenHistoryEntity.caption=Caption -ScreenHistoryEntity.user=User -ScreenHistoryEntity.entityId=Entity ID -ScreenHistoryEntity.createTs=Creation Time -ScreenHistoryEntity.url=URL -ScreenHistoryEntity.substitutedUser = Substituted User -ScreenHistoryEntity.displayUser = Display User - -EntityLogItem=Entity Log -EntityLogItem.eventTs=When -EntityLogItem.user=Who -EntityLogItem.type=Change Type -EntityLogItem.entity=Entity -EntityLogItem.entityId=Entity Id -EntityLogItem.changes = Changes -EntityLogItem.attributes = Attributes - -EntityLogItem$Type.MODIFY = Modify -EntityLogItem$Type.CREATE = Create -EntityLogItem$Type.DELETE = Delete -EntityLogItem$Type.RESTORE = Restore - -EntityLogAttr=Entity Log Attribute -EntityLogAttr.name=Attribute -EntityLogAttr.value=New Value -EntityLogAttr.oldValue=Old Value -EntityLogAttr.logItem=Log Item -EntityLogAttr.valueId=Value Id -EntityLogAttr.oldValueId=Old Value Id -EntityLogAttr.messagesPack=Messages Pack -EntityLogAttr.displayValue=Display Value -EntityLogAttr.displayName=Display Name -EntityLogAttr.locValue=Loc Value - -FilterEntity = Filter -FilterEntity.componentId=Component Id -FilterEntity.name=Name -FilterEntity.code=Code -FilterEntity.xml=XML -FilterEntity.user=User - -EntityAttrAccess.DENY=Deny -EntityAttrAccess.VIEW=View -EntityAttrAccess.MODIFY=Modify - -EntityOp.READ=Read -EntityOp.CREATE=Create -EntityOp.UPDATE=Update -EntityOp.DELETE=Delete - -GroupHierarchy=Group Hierarchy -GroupHierarchy.group=Group -GroupHierarchy.parent=Parent -GroupHierarchy.level=Level - -Presentation=Presentation -Presentation.componentId=Component Id -Presentation.name=Name -Presentation.xml=XML -Presentation.user=User -Presentation.autoSave=Auto Save -Presentation.updateTs=Updated -Presentation.updatedBy=Updated By - -SearchFolder=Search Folder -SearchFolder.user=User -SearchFolder.presentation=Presentation -SearchFolder.isSet=Is Set -SearchFolder.entityType=Entity Type - -RememberMeToken=Remember Me Token -RememberMeToken.user=User -RememberMeToken.token=Token - -ConstraintCheckType.DATABASE_AND_MEMORY = Check in database and in memory -ConstraintCheckType.DATABASE = Check in database -ConstraintCheckType.MEMORY = Check in memory - -ConstraintOperationType.CREATE = Create -ConstraintOperationType.READ = Read -ConstraintOperationType.UPDATE = Update -ConstraintOperationType.DELETE = Delete -ConstraintOperationType.ALL = All -ConstraintOperationType.CUSTOM = Custom - -SessionLogEntry=User Session Log -SessionLogEntry.sessionId=Session ID -SessionLogEntry.user=User -SessionLogEntry.substitutedUser=Substituted User -SessionLogEntry.address=Address -SessionLogEntry.clientInfo=Client Info -SessionLogEntry.clientType=Client Type -SessionLogEntry.startedTs=Started -SessionLogEntry.finishedTs=Finished -SessionLogEntry.server=Server -SessionLogEntry.lastAction=Last Action - -SessionAction.LOGIN=Login -SessionAction.LOGOUT=Logout -SessionAction.EXPIRATION=Expiration -SessionAction.TERMINATION=Termination -SessionAction.SUBSTITUTION=Substitution +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +Constraint=Constraint +Constraint.entityName=Entity Name +Constraint.joinClause=Join Clause +Constraint.whereClause=Where Clause +Constraint.group=Group +Constraint.groovyScript = Groovy Script +Constraint.filterXml = Filter XML +Constraint.code = Code +Constraint.checkType = Check Type +Constraint.operationType = Operation Type +Constraint.isActive = Is Active + +LocalizedConstraintMessage=Localized Constraint Message +LocalizedConstraintMessage.entityName=Entity Name +LocalizedConstraintMessage.operationType=Operation Type +LocalizedConstraintMessage.values=Localized Values + +SessionAttribute=Session Attribute +SessionAttribute.name=Name +SessionAttribute.stringValue=Value +SessionAttribute.datatype=Data Type +SessionAttribute.datatypeCaption=Data Type +SessionAttribute.group = Group + +Group=Group +Group.name=Name +Group.parent=Parent Group +Group.hierarchyList=Hierarchy List +Group.constraints=Constraints +Group.sessionAttributes = Session Attributes + +LoggedAttribute=Logged Attribute +LoggedAttribute.entity=Logged Entity +LoggedAttribute.name=Name + +LoggedEntity=Logged Entity +LoggedEntity.name=Name +LoggedEntity.auto=Auto +LoggedEntity.manual=Manual +LoggedEntity.attributes=Attributes + +Permission=Permission +Permission.type=Type +Permission.target=Target +Permission.value=Value +Permission.role=Role + +Role=Role +Role.name=Name +Role.type=Type +Role.permissions=Permissions +Role.description=Description +Role.defaultRole=Default Role +Role.locName=Localized Name + +RoleType=Role Type +RoleType.STANDARD=Standard +RoleType.SUPER=Super +RoleType.READONLY=Read-only +RoleType.DENYING=Denying + +User=User +User.login=Login +User.password=Password +User.name=Name +User.firstName=First Name +User.lastName=Last Name +User.middleName=Middle Name +User.position=Position +User.language=Language +User.timeZone=Time Zone +User.timeZoneAuto=Autodetect Time Zone +User.email=Email +User.group=Group +User.userRoles=User Roles +User.substitutions=Substitutions +User.ipMask=Permitted IP Mask +User.changePasswordAtNextLogon=Change Password at Next Logon +User.active=Active +User.loginLowerCase=Login + +UserRole=User role +UserRole.user=User +UserRole.role=Role + +UserSessionEntity=User Session Entity +UserSessionEntity.id=ID +UserSessionEntity.login=Login +UserSessionEntity.userName=User Name +UserSessionEntity.since=Active Since +UserSessionEntity.lastUsedTs=Last Used On +UserSessionEntity.address=Address +UserSessionEntity.clientInfo=Client Info +UserSessionEntity.system=System + +UserSetting=User Settings +UserSetting.user=User +UserSetting.clientType=Client Type +UserSetting.name=Name +UserSetting.value=Value + +UserSubstitution=User Substitution +UserSubstitution.user=User +UserSubstitution.substitutedUser=Substituted User +UserSubstitution.startDate=Start Date +UserSubstitution.endDate=End Date + +PermissionType.SCREEN=Screen +PermissionType.ENTITY_OP=Entity Operation +PermissionType.ENTITY_ATTR=Entity Attribute +PermissionType.SPECIFIC=Specific +PermissionType.UI=UI + +ScreenHistoryEntity=Screen History Entity +ScreenHistoryEntity.caption=Caption +ScreenHistoryEntity.user=User +ScreenHistoryEntity.entityId=Entity ID +ScreenHistoryEntity.createTs=Creation Time +ScreenHistoryEntity.url=URL +ScreenHistoryEntity.substitutedUser = Substituted User +ScreenHistoryEntity.displayUser = Display User + +EntityLogItem=Entity Log +EntityLogItem.eventTs=When +EntityLogItem.user=Who +EntityLogItem.type=Change Type +EntityLogItem.entity=Entity +EntityLogItem.entityId=Entity Id +EntityLogItem.changes = Changes +EntityLogItem.attributes = Attributes + +EntityLogItem$Type.MODIFY = Modify +EntityLogItem$Type.CREATE = Create +EntityLogItem$Type.DELETE = Delete +EntityLogItem$Type.RESTORE = Restore + +EntityLogAttr=Entity Log Attribute +EntityLogAttr.name=Attribute +EntityLogAttr.value=New Value +EntityLogAttr.oldValue=Old Value +EntityLogAttr.logItem=Log Item +EntityLogAttr.valueId=Value Id +EntityLogAttr.oldValueId=Old Value Id +EntityLogAttr.messagesPack=Messages Pack +EntityLogAttr.displayValue=Display Value +EntityLogAttr.displayName=Display Name +EntityLogAttr.locValue=Loc Value + +FilterEntity = Filter +FilterEntity.componentId=Component Id +FilterEntity.name=Name +FilterEntity.code=Code +FilterEntity.xml=XML +FilterEntity.user=User + +EntityAttrAccess.DENY=Deny +EntityAttrAccess.VIEW=View +EntityAttrAccess.MODIFY=Modify + +EntityOp.READ=Read +EntityOp.CREATE=Create +EntityOp.UPDATE=Update +EntityOp.DELETE=Delete + +GroupHierarchy=Group Hierarchy +GroupHierarchy.group=Group +GroupHierarchy.parent=Parent +GroupHierarchy.level=Level + +Presentation=Presentation +Presentation.componentId=Component Id +Presentation.name=Name +Presentation.xml=XML +Presentation.user=User +Presentation.autoSave=Auto Save +Presentation.updateTs=Updated +Presentation.updatedBy=Updated By + +SearchFolder=Search Folder +SearchFolder.user=User +SearchFolder.presentation=Presentation +SearchFolder.isSet=Is Set +SearchFolder.entityType=Entity Type + +RememberMeToken=Remember Me Token +RememberMeToken.user=User +RememberMeToken.token=Token + +ConstraintCheckType.DATABASE_AND_MEMORY = Check in database and in memory +ConstraintCheckType.DATABASE = Check in database +ConstraintCheckType.MEMORY = Check in memory + +ConstraintOperationType.CREATE = Create +ConstraintOperationType.READ = Read +ConstraintOperationType.UPDATE = Update +ConstraintOperationType.DELETE = Delete +ConstraintOperationType.ALL = All +ConstraintOperationType.CUSTOM = Custom + +SessionLogEntry=User Session Log +SessionLogEntry.sessionId=Session ID +SessionLogEntry.user=User +SessionLogEntry.substitutedUser=Substituted User +SessionLogEntry.address=Address +SessionLogEntry.clientInfo=Client Info +SessionLogEntry.clientType=Client Type +SessionLogEntry.startedTs=Started +SessionLogEntry.finishedTs=Finished +SessionLogEntry.server=Server +SessionLogEntry.lastAction=Last Action + +SessionAction.LOGIN=Login +SessionAction.LOGOUT=Logout +SessionAction.EXPIRATION=Expiration +SessionAction.TERMINATION=Termination +SessionAction.SUBSTITUTION=Substitution diff --git a/modules/global/src/com/haulmont/cuba/security/entity/messages_ru.properties b/modules/global/src/com/haulmont/cuba/security/entity/messages_ru.properties index 4d6da056a3..b80f6493e8 100644 --- a/modules/global/src/com/haulmont/cuba/security/entity/messages_ru.properties +++ b/modules/global/src/com/haulmont/cuba/security/entity/messages_ru.properties @@ -1,233 +1,233 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# - -Constraint=Ограничение -Constraint.entityName=Имя сущности -Constraint.joinClause=Предложение Join -Constraint.whereClause=Предложение Where -Constraint.group=Группа -Constraint.groovyScript = Groovy скрипт -Constraint.filterXml = Фильтр -Constraint.code = Код -Constraint.checkType = Тип проверки -Constraint.operationType = Тип операции -Constraint.isActive = Активно - -LocalizedConstraintMessage=Локализованные сообщения для ограничения -LocalizedConstraintMessage.entityName=Имя сущности -LocalizedConstraintMessage.operationType=Тип операции -LocalizedConstraintMessage.values=Локализованные сообщения - -SessionAttribute=Атрибут сессии -SessionAttribute.name=Имя -SessionAttribute.stringValue=Значение -SessionAttribute.datatype=Тип данных -SessionAttribute.datatypeCaption=Тип данных -SessionAttribute.group = Group - -Group=Группа -Group.name=Наименование -Group.parent=Родительская группа -Group.hierarchyList=Иерархия -Group.constraints=Ограничения -Group.sessionAttributes = Session Attributes - -LoggedAttribute=Журналируемый атрибут -LoggedAttribute.entity=Журналируемая сущность -LoggedAttribute.name=Наименование - -LoggedEntity=Журналируемая сущность -LoggedEntity.name=Наименование -LoggedEntity.auto=Авто -LoggedEntity.manual=Вручную -LoggedEntity.attributes=Атрибуты - -Permission=Разрешение -Permission.type=Тип -Permission.target=Цель -Permission.value=Значение -Permission.role=Роль - -Role=Роль -Role.name=Наименование -Role.type=Тип -Role.permissions=Права -Role.description=Описание -Role.defaultRole=Роль по умолчанию -Role.locName=Наименование (лок.) - -RoleType=Тип роли -RoleType.STANDARD=Стандартная -RoleType.SUPER=Супер -RoleType.READONLY=Только чтение -RoleType.DENYING=Запрещающая - -User=Пользователь -User.login=Логин -User.password=Пароль -User.name=Полное имя -User.firstName=Имя -User.lastName=Фамилия -User.middleName=Отчество -User.position=Должность -User.language=Язык -User.timeZone=Часовой пояс -User.timeZoneAuto=Автоопределение часового пояса -User.email=Email -User.group=Группа -User.userRoles=Роли пользователя -User.substitutions=Замещения -User.ipMask=Маска разрешенных IP -User.changePasswordAtNextLogon=Сменить пароль при следующем входе -User.active=Активен -User.loginLowerCase=Логин - -UserRole=Роль пользователя -UserRole.user=Пользователь -UserRole.role=Роль - -UserSessionEntity=Пользовательская сессия -UserSessionEntity.id=ID -UserSessionEntity.login=Логин -UserSessionEntity.userName=Имя пользователя -UserSessionEntity.since=Активен с -UserSessionEntity.lastUsedTs=Последняя активность -UserSessionEntity.address=Адрес -UserSessionEntity.clientInfo=Информация о клиенте -UserSessionEntity.system=Система - -UserSetting=Пользовательские настройки -UserSetting.user=Пользователь -UserSetting.clientType=Тип клиента -UserSetting.name=Наименование -UserSetting.value=Значение - -UserSubstitution=Замещение пользователя -UserSubstitution.user=Пользователь -UserSubstitution.substitutedUser=Замещаемый пользователь -UserSubstitution.startDate=Действует с -UserSubstitution.endDate=Действует до - -PermissionType.SCREEN=Экран -PermissionType.ENTITY_OP=Операция с сущностью -PermissionType.ENTITY_ATTR=Атрибут сущности -PermissionType.SPECIFIC=Специфическое -PermissionType.UI=Интерфейс - -ScreenHistoryEntity=Сущность экрана истории -ScreenHistoryEntity.caption=Заголовок -ScreenHistoryEntity.user=Пользователь -ScreenHistoryEntity.entityId=ID cущности -ScreenHistoryEntity.createTs=Время создания -ScreenHistoryEntity.url=URL -ScreenHistoryEntity.substitutedUser = Substituted User -ScreenHistoryEntity.displayUser = Display User - -EntityLogItem=Журнал изменений сущностей -EntityLogItem.eventTs=Когда -EntityLogItem.user=Кто -EntityLogItem.type=Тип изменения -EntityLogItem.entity=Сущность -EntityLogItem.entityId=ID cущности -EntityLogItem.changes = Changes -EntityLogItem.attributes = Attributes - -EntityLogItem$Type.MODIFY = Изменение -EntityLogItem$Type.CREATE = Создание -EntityLogItem$Type.DELETE = Удаление -EntityLogItem$Type.RESTORE = Восстановление - -EntityLogAttr=Атрибут журнала изменений сущностей -EntityLogAttr.name=Атрибут -EntityLogAttr.value=Новое значение -EntityLogAttr.oldValue=Старое значение -EntityLogAttr.logItem=Элемент журнала изменений -EntityLogAttr.valueId=Id значения -EntityLogAttr.oldValueId=Старое Id значения -EntityLogAttr.messagesPack=Пакет сообщений -EntityLogAttr.displayValue=Отображаемое значение -EntityLogAttr.displayName=Отображаемое имя -EntityLogAttr.locValue=Значение (лок.) - -FilterEntity = Фильтр -FilterEntity.componentId=Id компонента -FilterEntity.name=Наименование -FilterEntity.code=Код -FilterEntity.xml=XML -FilterEntity.user=Пользователь - -EntityAttrAccess.DENY=Запрещено -EntityAttrAccess.VIEW=Просмотр -EntityAttrAccess.MODIFY=Изменение - -EntityOp.READ=Чтение -EntityOp.CREATE=Создание -EntityOp.UPDATE=Изменение -EntityOp.DELETE=Удаление - -GroupHierarchy=Иерархия групп -GroupHierarchy.group=Группа -GroupHierarchy.parent=Родительская группа -GroupHierarchy.level=Уровень - -Presentation=Представление -Presentation.componentId=Id компонента -Presentation.name=Наименование -Presentation.xml=XML -Presentation.user=Пользователь -Presentation.autoSave=Автоматическое сохранение -Presentation.updateTs=Дата изменения -Presentation.updatedBy=Изменена кем - -SearchFolder=Папка поиска -SearchFolder.user=Пользователь -SearchFolder.presentation=Представление -SearchFolder.isSet=Набор -SearchFolder.entityType=Тип сущности - -RememberMeToken=Признак 'Запомнить меня' -RememberMeToken.user=Пользователь -RememberMeToken.token=Опознавательный знак - -ConstraintCheckType.DATABASE_AND_MEMORY = Проверка в базе данных и памяти -ConstraintCheckType.DATABASE = Проверка в базе данных -ConstraintCheckType.MEMORY = Проверка в памяти - -ConstraintOperationType.CREATE = Создание -ConstraintOperationType.READ = Чтение -ConstraintOperationType.UPDATE = Модификация -ConstraintOperationType.DELETE = Удаление -ConstraintOperationType.ALL = Все -ConstraintOperationType.CUSTOM = Специальная операция - -SessionLogEntry=Лог пользовательских сессий -SessionLogEntry.sessionId=ID сессии -SessionLogEntry.user=Пользователь -SessionLogEntry.substitutedUser=От имени пользователя -SessionLogEntry.address=IP Адрес -SessionLogEntry.clientInfo=Информация о клиенте -SessionLogEntry.clientType=Тип клиента -SessionLogEntry.startedTs=Начата -SessionLogEntry.finishedTs=Завершена -SessionLogEntry.server=Сервер -SessionLogEntry.lastAction=Последнее действие - -SessionAction.LOGIN=Логин -SessionAction.LOGOUT=Выход -SessionAction.EXPIRATION=Истечение срока -SessionAction.TERMINATION=Прервана +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# + +Constraint=Ограничение +Constraint.entityName=Имя сущности +Constraint.joinClause=Предложение Join +Constraint.whereClause=Предложение Where +Constraint.group=Группа +Constraint.groovyScript = Groovy скрипт +Constraint.filterXml = Фильтр +Constraint.code = Код +Constraint.checkType = Тип проверки +Constraint.operationType = Тип операции +Constraint.isActive = Активно + +LocalizedConstraintMessage=Локализованные сообщения для ограничения +LocalizedConstraintMessage.entityName=Имя сущности +LocalizedConstraintMessage.operationType=Тип операции +LocalizedConstraintMessage.values=Локализованные сообщения + +SessionAttribute=Атрибут сессии +SessionAttribute.name=Имя +SessionAttribute.stringValue=Значение +SessionAttribute.datatype=Тип данных +SessionAttribute.datatypeCaption=Тип данных +SessionAttribute.group = Group + +Group=Группа +Group.name=Наименование +Group.parent=Родительская группа +Group.hierarchyList=Иерархия +Group.constraints=Ограничения +Group.sessionAttributes = Session Attributes + +LoggedAttribute=Журналируемый атрибут +LoggedAttribute.entity=Журналируемая сущность +LoggedAttribute.name=Наименование + +LoggedEntity=Журналируемая сущность +LoggedEntity.name=Наименование +LoggedEntity.auto=Авто +LoggedEntity.manual=Вручную +LoggedEntity.attributes=Атрибуты + +Permission=Разрешение +Permission.type=Тип +Permission.target=Цель +Permission.value=Значение +Permission.role=Роль + +Role=Роль +Role.name=Наименование +Role.type=Тип +Role.permissions=Права +Role.description=Описание +Role.defaultRole=Роль по умолчанию +Role.locName=Наименование (лок.) + +RoleType=Тип роли +RoleType.STANDARD=Стандартная +RoleType.SUPER=Супер +RoleType.READONLY=Только чтение +RoleType.DENYING=Запрещающая + +User=Пользователь +User.login=Логин +User.password=Пароль +User.name=Полное имя +User.firstName=Имя +User.lastName=Фамилия +User.middleName=Отчество +User.position=Должность +User.language=Язык +User.timeZone=Часовой пояс +User.timeZoneAuto=Автоопределение часового пояса +User.email=Email +User.group=Группа +User.userRoles=Роли пользователя +User.substitutions=Замещения +User.ipMask=Маска разрешенных IP +User.changePasswordAtNextLogon=Сменить пароль при следующем входе +User.active=Активен +User.loginLowerCase=Логин + +UserRole=Роль пользователя +UserRole.user=Пользователь +UserRole.role=Роль + +UserSessionEntity=Пользовательская сессия +UserSessionEntity.id=ID +UserSessionEntity.login=Логин +UserSessionEntity.userName=Имя пользователя +UserSessionEntity.since=Активен с +UserSessionEntity.lastUsedTs=Последняя активность +UserSessionEntity.address=Адрес +UserSessionEntity.clientInfo=Информация о клиенте +UserSessionEntity.system=Система + +UserSetting=Пользовательские настройки +UserSetting.user=Пользователь +UserSetting.clientType=Тип клиента +UserSetting.name=Наименование +UserSetting.value=Значение + +UserSubstitution=Замещение пользователя +UserSubstitution.user=Пользователь +UserSubstitution.substitutedUser=Замещаемый пользователь +UserSubstitution.startDate=Действует с +UserSubstitution.endDate=Действует до + +PermissionType.SCREEN=Экран +PermissionType.ENTITY_OP=Операция с сущностью +PermissionType.ENTITY_ATTR=Атрибут сущности +PermissionType.SPECIFIC=Специфическое +PermissionType.UI=Интерфейс + +ScreenHistoryEntity=Сущность экрана истории +ScreenHistoryEntity.caption=Заголовок +ScreenHistoryEntity.user=Пользователь +ScreenHistoryEntity.entityId=ID cущности +ScreenHistoryEntity.createTs=Время создания +ScreenHistoryEntity.url=URL +ScreenHistoryEntity.substitutedUser = Substituted User +ScreenHistoryEntity.displayUser = Display User + +EntityLogItem=Журнал изменений сущностей +EntityLogItem.eventTs=Когда +EntityLogItem.user=Кто +EntityLogItem.type=Тип изменения +EntityLogItem.entity=Сущность +EntityLogItem.entityId=ID cущности +EntityLogItem.changes = Changes +EntityLogItem.attributes = Attributes + +EntityLogItem$Type.MODIFY = Изменение +EntityLogItem$Type.CREATE = Создание +EntityLogItem$Type.DELETE = Удаление +EntityLogItem$Type.RESTORE = Восстановление + +EntityLogAttr=Атрибут журнала изменений сущностей +EntityLogAttr.name=Атрибут +EntityLogAttr.value=Новое значение +EntityLogAttr.oldValue=Старое значение +EntityLogAttr.logItem=Элемент журнала изменений +EntityLogAttr.valueId=Id значения +EntityLogAttr.oldValueId=Старое Id значения +EntityLogAttr.messagesPack=Пакет сообщений +EntityLogAttr.displayValue=Отображаемое значение +EntityLogAttr.displayName=Отображаемое имя +EntityLogAttr.locValue=Значение (лок.) + +FilterEntity = Фильтр +FilterEntity.componentId=Id компонента +FilterEntity.name=Наименование +FilterEntity.code=Код +FilterEntity.xml=XML +FilterEntity.user=Пользователь + +EntityAttrAccess.DENY=Запрещено +EntityAttrAccess.VIEW=Просмотр +EntityAttrAccess.MODIFY=Изменение + +EntityOp.READ=Чтение +EntityOp.CREATE=Создание +EntityOp.UPDATE=Изменение +EntityOp.DELETE=Удаление + +GroupHierarchy=Иерархия групп +GroupHierarchy.group=Группа +GroupHierarchy.parent=Родительская группа +GroupHierarchy.level=Уровень + +Presentation=Представление +Presentation.componentId=Id компонента +Presentation.name=Наименование +Presentation.xml=XML +Presentation.user=Пользователь +Presentation.autoSave=Автоматическое сохранение +Presentation.updateTs=Дата изменения +Presentation.updatedBy=Изменена кем + +SearchFolder=Папка поиска +SearchFolder.user=Пользователь +SearchFolder.presentation=Представление +SearchFolder.isSet=Набор +SearchFolder.entityType=Тип сущности + +RememberMeToken=Признак 'Запомнить меня' +RememberMeToken.user=Пользователь +RememberMeToken.token=Опознавательный знак + +ConstraintCheckType.DATABASE_AND_MEMORY = Проверка в базе данных и памяти +ConstraintCheckType.DATABASE = Проверка в базе данных +ConstraintCheckType.MEMORY = Проверка в памяти + +ConstraintOperationType.CREATE = Создание +ConstraintOperationType.READ = Чтение +ConstraintOperationType.UPDATE = Модификация +ConstraintOperationType.DELETE = Удаление +ConstraintOperationType.ALL = Все +ConstraintOperationType.CUSTOM = Специальная операция + +SessionLogEntry=Лог пользовательских сессий +SessionLogEntry.sessionId=ID сессии +SessionLogEntry.user=Пользователь +SessionLogEntry.substitutedUser=От имени пользователя +SessionLogEntry.address=IP Адрес +SessionLogEntry.clientInfo=Информация о клиенте +SessionLogEntry.clientType=Тип клиента +SessionLogEntry.startedTs=Начата +SessionLogEntry.finishedTs=Завершена +SessionLogEntry.server=Сервер +SessionLogEntry.lastAction=Последнее действие + +SessionAction.LOGIN=Логин +SessionAction.LOGOUT=Выход +SessionAction.EXPIRATION=Истечение срока +SessionAction.TERMINATION=Прервана SessionAction.SUBSTITUTION=Подмена пользователя \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/global/ConstraintData.java b/modules/global/src/com/haulmont/cuba/security/global/ConstraintData.java index a72444e385..dfdc34e98f 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/ConstraintData.java +++ b/modules/global/src/com/haulmont/cuba/security/global/ConstraintData.java @@ -1,73 +1,73 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.global; - -import com.haulmont.cuba.security.entity.Constraint; -import com.haulmont.cuba.security.entity.ConstraintOperationType; -import com.haulmont.cuba.security.entity.ConstraintCheckType; - -import java.io.Serializable; -import java.util.UUID; - -public class ConstraintData implements Serializable { - protected final UUID id; - protected final String code; - protected final ConstraintOperationType operationType; - protected final ConstraintCheckType checkType; - protected final String join; - protected final String whereClause; - protected final String groovyScript; - - public ConstraintData(Constraint constraint) { - this.id = constraint.getId(); - this.code = constraint.getCode(); - this.join = constraint.getJoinClause(); - this.whereClause = constraint.getWhereClause(); - this.groovyScript = constraint.getGroovyScript(); - this.operationType = constraint.getOperationType(); - this.checkType = constraint.getCheckType(); - } - - public String getCode() { - return code; - } - - public String getJoin() { - return join; - } - - public String getWhereClause() { - return whereClause; - } - - public String getGroovyScript() { - return groovyScript; - } - - public ConstraintOperationType getOperationType() { - return operationType; - } - - public ConstraintCheckType getCheckType() { - return checkType; - } - - public UUID getId() { - return id; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.global; + +import com.haulmont.cuba.security.entity.Constraint; +import com.haulmont.cuba.security.entity.ConstraintOperationType; +import com.haulmont.cuba.security.entity.ConstraintCheckType; + +import java.io.Serializable; +import java.util.UUID; + +public class ConstraintData implements Serializable { + protected final UUID id; + protected final String code; + protected final ConstraintOperationType operationType; + protected final ConstraintCheckType checkType; + protected final String join; + protected final String whereClause; + protected final String groovyScript; + + public ConstraintData(Constraint constraint) { + this.id = constraint.getId(); + this.code = constraint.getCode(); + this.join = constraint.getJoinClause(); + this.whereClause = constraint.getWhereClause(); + this.groovyScript = constraint.getGroovyScript(); + this.operationType = constraint.getOperationType(); + this.checkType = constraint.getCheckType(); + } + + public String getCode() { + return code; + } + + public String getJoin() { + return join; + } + + public String getWhereClause() { + return whereClause; + } + + public String getGroovyScript() { + return groovyScript; + } + + public ConstraintOperationType getOperationType() { + return operationType; + } + + public ConstraintCheckType getCheckType() { + return checkType; + } + + public UUID getId() { + return id; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/global/IpMatcher.java b/modules/global/src/com/haulmont/cuba/security/global/IpMatcher.java index 94a08c77c2..2d3d387447 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/IpMatcher.java +++ b/modules/global/src/com/haulmont/cuba/security/global/IpMatcher.java @@ -1,103 +1,103 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.global; - -import com.google.common.collect.ImmutableSet; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -public class IpMatcher { - - private static final Set whiteListedIPs = ImmutableSet.of("127.0.0.1", "0:0:0:0:0:0:0:1"); - private List masks = new ArrayList<>(); - - private final Logger log = LoggerFactory.getLogger(IpMatcher.class); - - public IpMatcher(String source) { - String[] parts = source.split("[,;]"); - for (String part : parts) { - String m = part.trim(); - String[] mask = ipv4(m); - if (mask == null) { - mask = ipv6(m); - if (mask == null) { - log.warn("Invalid IP mask: '{}'", m); - continue; - } - } - masks.add(mask); - } - } - - public boolean match(String ip) { - if (StringUtils.isBlank(ip) || whiteListedIPs.contains(ip)) { - return true; - } - if (masks.isEmpty()) { - return true; - } - - String[] ipv = ipv4(ip); - if (ipv == null) { - ipv = ipv6(ip); - if (ipv == null) { - log.warn("IP format not supported: '{}'", ip); - return true; - } - } - - for (String[] mask : masks) { - if (match(mask, ipv)) - return true; - } - return false; - } - - private boolean match(String[] mask, String[] ip) { - if (mask.length != ip.length) { - return false; - } - for (int j = 0; j < mask.length; j++) { - String mp = mask[j]; - if (!mp.equals("*") && !ip[j].equals(mp)) { - return false; - } - } - return true; - } - - private static String[] ipv4(String ip) { - String[] ipp = ip.split("\\."); - if (ipp.length != 4) { - return null; - } - return ipp; - } - - private static String[] ipv6(String ip) { - String[] ipp = ip.split(":"); - if (ipp.length != 8) { - return null; - } - return ipp; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.global; + +import com.google.common.collect.ImmutableSet; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class IpMatcher { + + private static final Set whiteListedIPs = ImmutableSet.of("127.0.0.1", "0:0:0:0:0:0:0:1"); + private List masks = new ArrayList<>(); + + private final Logger log = LoggerFactory.getLogger(IpMatcher.class); + + public IpMatcher(String source) { + String[] parts = source.split("[,;]"); + for (String part : parts) { + String m = part.trim(); + String[] mask = ipv4(m); + if (mask == null) { + mask = ipv6(m); + if (mask == null) { + log.warn("Invalid IP mask: '{}'", m); + continue; + } + } + masks.add(mask); + } + } + + public boolean match(String ip) { + if (StringUtils.isBlank(ip) || whiteListedIPs.contains(ip)) { + return true; + } + if (masks.isEmpty()) { + return true; + } + + String[] ipv = ipv4(ip); + if (ipv == null) { + ipv = ipv6(ip); + if (ipv == null) { + log.warn("IP format not supported: '{}'", ip); + return true; + } + } + + for (String[] mask : masks) { + if (match(mask, ipv)) + return true; + } + return false; + } + + private boolean match(String[] mask, String[] ip) { + if (mask.length != ip.length) { + return false; + } + for (int j = 0; j < mask.length; j++) { + String mp = mask[j]; + if (!mp.equals("*") && !ip[j].equals(mp)) { + return false; + } + } + return true; + } + + private static String[] ipv4(String ip) { + String[] ipp = ip.split("\\."); + if (ipp.length != 4) { + return null; + } + return ipp; + } + + private static String[] ipv6(String ip) { + String[] ipp = ip.split(":"); + if (ipp.length != 8) { + return null; + } + return ipp; + } } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/security/global/LoginException.java b/modules/global/src/com/haulmont/cuba/security/global/LoginException.java index 3e0e555086..81a6cea31c 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/LoginException.java +++ b/modules/global/src/com/haulmont/cuba/security/global/LoginException.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.global; - -import com.haulmont.cuba.core.global.Logging; -import com.haulmont.cuba.core.global.SupportedByClient; - -/** - * Login error. Contains message localized accordingly to the current user locale. - */ -@SupportedByClient -@Logging(Logging.Type.BRIEF) -public class LoginException extends Exception { - - private static final long serialVersionUID = 6144194102176774627L; - - public LoginException(String message) { - super(message); - } - - public LoginException(String template, Object... params) { - super(String.format(template, params)); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.global; + +import com.haulmont.cuba.core.global.Logging; +import com.haulmont.cuba.core.global.SupportedByClient; + +/** + * Login error. Contains message localized accordingly to the current user locale. + */ +@SupportedByClient +@Logging(Logging.Type.BRIEF) +public class LoginException extends Exception { + + private static final long serialVersionUID = 6144194102176774627L; + + public LoginException(String message) { + super(message); + } + + public LoginException(String template, Object... params) { + super(String.format(template, params)); + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/global/NoUserSessionException.java b/modules/global/src/com/haulmont/cuba/security/global/NoUserSessionException.java index b537a78419..4a596c09d1 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/NoUserSessionException.java +++ b/modules/global/src/com/haulmont/cuba/security/global/NoUserSessionException.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.global; - -import com.haulmont.cuba.core.global.Logging; -import com.haulmont.cuba.core.global.SupportedByClient; - -import java.util.UUID; - -/** - * Raised by middleware if the client provides an invalid user session ID (e.g. if the user session has expired). - * - */ -@SupportedByClient -@Logging(Logging.Type.BRIEF) -public class NoUserSessionException extends RuntimeException { - - private static final long serialVersionUID = 4820628023682230319L; - - public NoUserSessionException(UUID sessionId) { - super(String.format("User session not found: %s", sessionId.toString())); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.global; + +import com.haulmont.cuba.core.global.Logging; +import com.haulmont.cuba.core.global.SupportedByClient; + +import java.util.UUID; + +/** + * Raised by middleware if the client provides an invalid user session ID (e.g. if the user session has expired). + * + */ +@SupportedByClient +@Logging(Logging.Type.BRIEF) +public class NoUserSessionException extends RuntimeException { + + private static final long serialVersionUID = 4820628023682230319L; + + public NoUserSessionException(UUID sessionId) { + super(String.format("User session not found: %s", sessionId.toString())); + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/global/UserSession.java b/modules/global/src/com/haulmont/cuba/security/global/UserSession.java index 565a2fe0e9..608e12416a 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/UserSession.java +++ b/modules/global/src/com/haulmont/cuba/security/global/UserSession.java @@ -1,544 +1,544 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.global; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.sys.UserInvocationContext; -import com.haulmont.cuba.security.entity.*; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * Class that encapsulates an active user session. - *

It contains user attributes, credentials, set of permissions, and methods to check permissions for certain - * objects.

- *

On the client side a descendant of this class is maintained: - * {@code com.haulmont.cuba.client.ClientUserSession}

- */ -public class UserSession implements Serializable { - - private static final long serialVersionUID = -8248326616891177382L; - - protected UUID id; - protected User user; - protected User substitutedUser; - protected List roles = new ArrayList<>(); - protected EnumSet roleTypes = EnumSet.noneOf(RoleType.class); - protected Locale locale; - protected TimeZone timeZone; - protected String address; - protected String clientInfo; - protected boolean system; - - protected Map[] permissions; - protected Map> constraints; - - protected Map attributes; - - protected transient Map localAttributes; - - /** - * INTERNAL - * Used only for kryo serialization - */ - public UserSession() { - localAttributes = new ConcurrentHashMap<>(); - } - - /** - * INTERNAL - */ - public UserSession(UUID id, User user, Collection roles, Locale locale, boolean system) { - this.id = id; - this.user = user; - this.system = system; - - for (Role role : roles) { - this.roles.add(role.getName()); - if (role.getType() != null) - roleTypes.add(role.getType()); - } - - this.locale = locale; - if (user.getTimeZone() != null) - this.timeZone = TimeZone.getTimeZone(user.getTimeZone()); - - //noinspection unchecked - permissions = new Map[PermissionType.values().length]; - for (int i = 0; i < permissions.length; i++) { - permissions[i] = new HashMap<>(); - } - - constraints = new HashMap<>(); - attributes = new ConcurrentHashMap<>(); - localAttributes = new ConcurrentHashMap<>(); - } - - /** - * INTERNAL - */ - public UserSession(UserSession src, User user, Collection roles, Locale locale) { - this(src.id, user, roles, locale, src.system); - this.user = src.user; - this.substitutedUser = this.user.equals(user) ? null : user; - } - - /** - * INTERNAL - */ - public UserSession(UserSession src) { - id = src.id; - user = src.user; - substitutedUser = src.substitutedUser; - system = src.system; - roles = src.roles; - locale = src.locale; - timeZone = src.timeZone; - permissions = src.permissions; - constraints = src.constraints; - attributes = src.attributes; - roleTypes = src.roleTypes; - localAttributes = src.localAttributes; - address = src.address; - clientInfo = src.clientInfo; - } - - private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - localAttributes = new ConcurrentHashMap<>(); - } - - /** - * Session ID - */ - public UUID getId() { - return id; - } - - /** - * Logged-in user - */ - public User getUser() { - return user; - } - - /** - * INTERNAL - */ - public void setUser(User user) { - this.user = user; - } - - /** - * Substituted user. May be null. - */ - public User getSubstitutedUser() { - return substitutedUser; - } - - /** - * INTERNAL - */ - public void setSubstitutedUser(User substitutedUser) { - this.substitutedUser = substitutedUser; - } - - /** - * Returns substituted user if it is not null, logged-in user otherwise. - */ - public User getCurrentOrSubstitutedUser() { - return substitutedUser == null ? user : substitutedUser; - } - - /** - * User role names - */ - public Collection getRoles() { - return Collections.unmodifiableList(roles); - } - - /** - * User locale - */ - public Locale getLocale() { - Locale requestScopeLocale = UserInvocationContext.getRequestScopeLocale(id); - if (requestScopeLocale != null) { - return requestScopeLocale; - } - - return locale; - } - - /** - * INTERNAL - */ - public void setLocale(Locale locale) { - this.locale = locale; - } - - /** - * User time zone. Can be null. - */ - @Nullable - public TimeZone getTimeZone() { - TimeZone requestScopeTimeZone = UserInvocationContext.getRequestScopeTimeZone(id); - if (requestScopeTimeZone != null) { - return requestScopeTimeZone; - } - - return timeZone; - } - - /** - * INTERNAL - */ - public void setTimeZone(TimeZone timeZone) { - this.timeZone = timeZone; - } - - /** - * Client IP-address - */ - public String getAddress() { - String requestScopeAddress = UserInvocationContext.getRequestScopeAddress(id); - if (requestScopeAddress != null) { - return requestScopeAddress; - } - - return address; - } - - /** - * INTERNAL - */ - public void setAddress(String address) { - this.address = address; - } - - /** - * Client application info - */ - public String getClientInfo() { - String requestScopeClientInfo = UserInvocationContext.getRequestScopeClientInfo(id); - if (requestScopeClientInfo != null) { - return requestScopeClientInfo; - } - - return clientInfo; - } - - /** - * INTERNAL - */ - public void setClientInfo(String clientInfo) { - this.clientInfo = clientInfo; - } - - /** - * INTERNAL - */ - public void addPermission(PermissionType type, String target, @Nullable String extTarget, int value) { - Integer currentValue = permissions[type.ordinal()].get(target); - if (currentValue == null || currentValue < value) { - permissions[type.ordinal()].put(target, value); - if (extTarget != null) - permissions[type.ordinal()].put(extTarget, value); - } - } - - /** - * INTERNAL - */ - public void removePermission(PermissionType type, String target) { - permissions[type.ordinal()].remove(target); - } - - /** - * INTERNAL - */ - public Integer getPermissionValue(PermissionType type, String target) { - return permissions[type.ordinal()].get(target); - } - - /** - * Get permissions by type - */ - public Map getPermissionsByType(PermissionType type) { - return Collections.unmodifiableMap(permissions[type.ordinal()]); - } - - /** - * Check user permission for the screen - */ - public boolean isScreenPermitted(String windowAlias) { - return isPermitted(PermissionType.SCREEN, windowAlias); - } - - /** - * Check user permission for the entity operation - */ - public boolean isEntityOpPermitted(MetaClass metaClass, EntityOp entityOp) { - return isPermitted(PermissionType.ENTITY_OP, - metaClass.getName() + Permission.TARGET_PATH_DELIMETER + entityOp.getId()); - } - - /** - * Check user permission for the entity attribute - */ - public boolean isEntityAttrPermitted(MetaClass metaClass, String property, EntityAttrAccess access) { - return isPermitted(PermissionType.ENTITY_ATTR, - metaClass.getName() + Permission.TARGET_PATH_DELIMETER + property, - access.getId()); - } - - /** - * Check specific user permission - */ - public boolean isSpecificPermitted(String name) { - return isPermitted(PermissionType.SPECIFIC, name); - } - - /** - * Check user permission. - *
Same as {@link #isPermitted(com.haulmont.cuba.security.entity.PermissionType, String, int)} - * with value=1 - *
This method makes sense for permission types with two possible values 0,1 - * - * @param type permission type - * @param target permission target:
    - *
  • screen - *
  • entity operation (view, create, update, delete) - *
  • entity attribute name - *
  • specific permission name - *
- * @return true if permitted, false otherwise - */ - public boolean isPermitted(PermissionType type, String target) { - return isPermitted(type, target, 1); - } - - /** - * Check user permission for the specified value. - * - * @param type permission type - * @param target permission target:
    - *
  • screen - *
  • entity operation (view, create, update, delete) - *
  • entity attribute name - *
  • specific permission name - *
- * @param value method returns true if the corresponding {@link com.haulmont.cuba.security.entity.Permission} - * record contains value equal or greater than specified - * @return true if permitted, false otherwise - */ - public boolean isPermitted(PermissionType type, String target, int value) { - // If we have super-role no need to check anything - if (roleTypes.contains(RoleType.SUPER)) - return true; - // Get permission value assigned by the set of permissions - Integer v = permissions[type.ordinal()].get(target); - // Get permission value assigned by non-standard roles - for (RoleType roleType : roleTypes) { - Integer v1 = roleType.permissionValue(type, target); - if (v1 != null && (v == null || v < v1)) { - v = v1; - } - } - // Return true if no value set for this target, or if the value is more than requested - return v == null || v >= value; - } - - /** - * INTERNAL - */ - public void addConstraint(Constraint constraint) { - String entityName = constraint.getEntityName(); - List list = constraints.computeIfAbsent(entityName, k -> new ArrayList<>()); - list.add(new ConstraintData(constraint)); - } - - /** - * INTERNAL - */ - public void removeConstraint(Constraint constraintToRemove) { - String entityName = constraintToRemove.getEntityName(); - List constraintDataList = this.constraints.get(entityName); - if (constraintDataList != null && !constraintDataList.isEmpty()) { - for (ConstraintData constraintData : new ArrayList<>(constraintDataList)) { - if (constraintToRemove.getId().equals(constraintData.getId())) - constraintDataList.remove(constraintData); - } - } - } - - /** - * INTERNAL - */ - public List getConstraints(String entityName) { - return Collections.unmodifiableList(constraints.getOrDefault(entityName, Collections.emptyList())); - } - - /** - * INTERNAL - */ - public boolean hasConstraints(String entityName) { - return constraints.containsKey(entityName); - } - - /** - * INTERNAL - */ - public boolean hasConstraints() { - return !constraints.isEmpty(); - } - - /** - * INTERNAL - */ - public List getConstraints(String entityName, Predicate predicate) { - List list = constraints.getOrDefault(entityName, Collections.emptyList()); - return Collections.unmodifiableList(list.stream().filter(predicate).collect(Collectors.toList())); - } - - /** - * Get user session attribute. Attribute is a named serializable object bound to session. - * - * @param name attribute name. The following names have predefined values: - *
    - *
  • userId - current or substituted user ID
  • - *
  • userLogin - current or substituted user login in lower case
  • - *
- * @return attribute value or null if attribute with the given name is not found - */ - @SuppressWarnings("unchecked") - @Nullable - public T getAttribute(String name) { - if ("userId".equals(name)) - return (T) getCurrentOrSubstitutedUser().getId(); - if ("userLogin".equals(name)) - return (T) getCurrentOrSubstitutedUser().getLoginLowerCase(); - else - return (T) attributes.get(name); - } - - /** - * Remove user session attribute. Attribute is a named serializable object bound to session. - * - * @param name attribute name - */ - public void removeAttribute(String name) { - attributes.remove(name); - } - - /** - * Set user session attribute. Attribute is a named serializable object bound to session. - * - * @param name attribute name - * @param value attribute value - */ - public void setAttribute(String name, Serializable value) { - attributes.put(name, value); - } - - /** - * User session attribute names. Attribute is a named serializable object bound to session. - */ - public Collection getAttributeNames() { - return new ArrayList<>(attributes.keySet()); - } - - /** - * Get local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, - * local attributes are not passed between tiers and not replicated in cluster. - * - * @param name attribute name - * @return attribute value or null if attribute with the given name is not found - */ - @SuppressWarnings("unchecked") - @Nullable - public T getLocalAttribute(String name) { - return (T) localAttributes.get(name); - } - - /** - * Remove local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, - * local attributes are not passed between tiers and not replicated in cluster. - * - * @param name attribute name - */ - public void removeLocalAttribute(String name) { - localAttributes.remove(name); - } - - /** - * Set local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, - * local attributes are not passed between tiers and not replicated in cluster. - * - * @param name attribute name - * @param value attribute value - */ - public void setLocalAttribute(String name, Object value) { - localAttributes.put(name, value); - } - - /** - * Set local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, - * local attributes are not passed between tiers and not replicated in cluster. - * - * @param name attribute name - * @param value attribute value - * @return the previous value associated with the specified key, or - * {@code null} if there was no mapping for the key. - * (A {@code null} return can also indicate that the map - * previously associated {@code null} with the key, - * if the implementation supports null values.) - */ - public Object setLocalAttributeIfAbsent(String name, Object value) { - return localAttributes.putIfAbsent(name, value); - } - - /** - * Local attribute names. Local attribute is a named object bound to session. Unlike normal user session attributes, - * local attributes are not passed between tiers and not replicated in cluster. - */ - public Collection getLocalAttributeNames() { - return new ArrayList<>(localAttributes.keySet()); - } - - /** - * System session is created by LoginWorker.loginSystem() for system users like schedulers and JMX. - *

- * It is not replicated in cluster. - */ - public boolean isSystem() { - return system; - } - - @Override - public String toString() { - return id + " [" - + user.getLogin() + (substitutedUser == null ? "" : " / " + substitutedUser.getLogin()) - + "]"; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.global; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.sys.UserInvocationContext; +import com.haulmont.cuba.security.entity.*; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * Class that encapsulates an active user session. + *

It contains user attributes, credentials, set of permissions, and methods to check permissions for certain + * objects.

+ *

On the client side a descendant of this class is maintained: + * {@code com.haulmont.cuba.client.ClientUserSession}

+ */ +public class UserSession implements Serializable { + + private static final long serialVersionUID = -8248326616891177382L; + + protected UUID id; + protected User user; + protected User substitutedUser; + protected List roles = new ArrayList<>(); + protected EnumSet roleTypes = EnumSet.noneOf(RoleType.class); + protected Locale locale; + protected TimeZone timeZone; + protected String address; + protected String clientInfo; + protected boolean system; + + protected Map[] permissions; + protected Map> constraints; + + protected Map attributes; + + protected transient Map localAttributes; + + /** + * INTERNAL + * Used only for kryo serialization + */ + public UserSession() { + localAttributes = new ConcurrentHashMap<>(); + } + + /** + * INTERNAL + */ + public UserSession(UUID id, User user, Collection roles, Locale locale, boolean system) { + this.id = id; + this.user = user; + this.system = system; + + for (Role role : roles) { + this.roles.add(role.getName()); + if (role.getType() != null) + roleTypes.add(role.getType()); + } + + this.locale = locale; + if (user.getTimeZone() != null) + this.timeZone = TimeZone.getTimeZone(user.getTimeZone()); + + //noinspection unchecked + permissions = new Map[PermissionType.values().length]; + for (int i = 0; i < permissions.length; i++) { + permissions[i] = new HashMap<>(); + } + + constraints = new HashMap<>(); + attributes = new ConcurrentHashMap<>(); + localAttributes = new ConcurrentHashMap<>(); + } + + /** + * INTERNAL + */ + public UserSession(UserSession src, User user, Collection roles, Locale locale) { + this(src.id, user, roles, locale, src.system); + this.user = src.user; + this.substitutedUser = this.user.equals(user) ? null : user; + } + + /** + * INTERNAL + */ + public UserSession(UserSession src) { + id = src.id; + user = src.user; + substitutedUser = src.substitutedUser; + system = src.system; + roles = src.roles; + locale = src.locale; + timeZone = src.timeZone; + permissions = src.permissions; + constraints = src.constraints; + attributes = src.attributes; + roleTypes = src.roleTypes; + localAttributes = src.localAttributes; + address = src.address; + clientInfo = src.clientInfo; + } + + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + localAttributes = new ConcurrentHashMap<>(); + } + + /** + * Session ID + */ + public UUID getId() { + return id; + } + + /** + * Logged-in user + */ + public User getUser() { + return user; + } + + /** + * INTERNAL + */ + public void setUser(User user) { + this.user = user; + } + + /** + * Substituted user. May be null. + */ + public User getSubstitutedUser() { + return substitutedUser; + } + + /** + * INTERNAL + */ + public void setSubstitutedUser(User substitutedUser) { + this.substitutedUser = substitutedUser; + } + + /** + * Returns substituted user if it is not null, logged-in user otherwise. + */ + public User getCurrentOrSubstitutedUser() { + return substitutedUser == null ? user : substitutedUser; + } + + /** + * User role names + */ + public Collection getRoles() { + return Collections.unmodifiableList(roles); + } + + /** + * User locale + */ + public Locale getLocale() { + Locale requestScopeLocale = UserInvocationContext.getRequestScopeLocale(id); + if (requestScopeLocale != null) { + return requestScopeLocale; + } + + return locale; + } + + /** + * INTERNAL + */ + public void setLocale(Locale locale) { + this.locale = locale; + } + + /** + * User time zone. Can be null. + */ + @Nullable + public TimeZone getTimeZone() { + TimeZone requestScopeTimeZone = UserInvocationContext.getRequestScopeTimeZone(id); + if (requestScopeTimeZone != null) { + return requestScopeTimeZone; + } + + return timeZone; + } + + /** + * INTERNAL + */ + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** + * Client IP-address + */ + public String getAddress() { + String requestScopeAddress = UserInvocationContext.getRequestScopeAddress(id); + if (requestScopeAddress != null) { + return requestScopeAddress; + } + + return address; + } + + /** + * INTERNAL + */ + public void setAddress(String address) { + this.address = address; + } + + /** + * Client application info + */ + public String getClientInfo() { + String requestScopeClientInfo = UserInvocationContext.getRequestScopeClientInfo(id); + if (requestScopeClientInfo != null) { + return requestScopeClientInfo; + } + + return clientInfo; + } + + /** + * INTERNAL + */ + public void setClientInfo(String clientInfo) { + this.clientInfo = clientInfo; + } + + /** + * INTERNAL + */ + public void addPermission(PermissionType type, String target, @Nullable String extTarget, int value) { + Integer currentValue = permissions[type.ordinal()].get(target); + if (currentValue == null || currentValue < value) { + permissions[type.ordinal()].put(target, value); + if (extTarget != null) + permissions[type.ordinal()].put(extTarget, value); + } + } + + /** + * INTERNAL + */ + public void removePermission(PermissionType type, String target) { + permissions[type.ordinal()].remove(target); + } + + /** + * INTERNAL + */ + public Integer getPermissionValue(PermissionType type, String target) { + return permissions[type.ordinal()].get(target); + } + + /** + * Get permissions by type + */ + public Map getPermissionsByType(PermissionType type) { + return Collections.unmodifiableMap(permissions[type.ordinal()]); + } + + /** + * Check user permission for the screen + */ + public boolean isScreenPermitted(String windowAlias) { + return isPermitted(PermissionType.SCREEN, windowAlias); + } + + /** + * Check user permission for the entity operation + */ + public boolean isEntityOpPermitted(MetaClass metaClass, EntityOp entityOp) { + return isPermitted(PermissionType.ENTITY_OP, + metaClass.getName() + Permission.TARGET_PATH_DELIMETER + entityOp.getId()); + } + + /** + * Check user permission for the entity attribute + */ + public boolean isEntityAttrPermitted(MetaClass metaClass, String property, EntityAttrAccess access) { + return isPermitted(PermissionType.ENTITY_ATTR, + metaClass.getName() + Permission.TARGET_PATH_DELIMETER + property, + access.getId()); + } + + /** + * Check specific user permission + */ + public boolean isSpecificPermitted(String name) { + return isPermitted(PermissionType.SPECIFIC, name); + } + + /** + * Check user permission. + *
Same as {@link #isPermitted(com.haulmont.cuba.security.entity.PermissionType, String, int)} + * with value=1 + *
This method makes sense for permission types with two possible values 0,1 + * + * @param type permission type + * @param target permission target:
    + *
  • screen + *
  • entity operation (view, create, update, delete) + *
  • entity attribute name + *
  • specific permission name + *
+ * @return true if permitted, false otherwise + */ + public boolean isPermitted(PermissionType type, String target) { + return isPermitted(type, target, 1); + } + + /** + * Check user permission for the specified value. + * + * @param type permission type + * @param target permission target:
    + *
  • screen + *
  • entity operation (view, create, update, delete) + *
  • entity attribute name + *
  • specific permission name + *
+ * @param value method returns true if the corresponding {@link com.haulmont.cuba.security.entity.Permission} + * record contains value equal or greater than specified + * @return true if permitted, false otherwise + */ + public boolean isPermitted(PermissionType type, String target, int value) { + // If we have super-role no need to check anything + if (roleTypes.contains(RoleType.SUPER)) + return true; + // Get permission value assigned by the set of permissions + Integer v = permissions[type.ordinal()].get(target); + // Get permission value assigned by non-standard roles + for (RoleType roleType : roleTypes) { + Integer v1 = roleType.permissionValue(type, target); + if (v1 != null && (v == null || v < v1)) { + v = v1; + } + } + // Return true if no value set for this target, or if the value is more than requested + return v == null || v >= value; + } + + /** + * INTERNAL + */ + public void addConstraint(Constraint constraint) { + String entityName = constraint.getEntityName(); + List list = constraints.computeIfAbsent(entityName, k -> new ArrayList<>()); + list.add(new ConstraintData(constraint)); + } + + /** + * INTERNAL + */ + public void removeConstraint(Constraint constraintToRemove) { + String entityName = constraintToRemove.getEntityName(); + List constraintDataList = this.constraints.get(entityName); + if (constraintDataList != null && !constraintDataList.isEmpty()) { + for (ConstraintData constraintData : new ArrayList<>(constraintDataList)) { + if (constraintToRemove.getId().equals(constraintData.getId())) + constraintDataList.remove(constraintData); + } + } + } + + /** + * INTERNAL + */ + public List getConstraints(String entityName) { + return Collections.unmodifiableList(constraints.getOrDefault(entityName, Collections.emptyList())); + } + + /** + * INTERNAL + */ + public boolean hasConstraints(String entityName) { + return constraints.containsKey(entityName); + } + + /** + * INTERNAL + */ + public boolean hasConstraints() { + return !constraints.isEmpty(); + } + + /** + * INTERNAL + */ + public List getConstraints(String entityName, Predicate predicate) { + List list = constraints.getOrDefault(entityName, Collections.emptyList()); + return Collections.unmodifiableList(list.stream().filter(predicate).collect(Collectors.toList())); + } + + /** + * Get user session attribute. Attribute is a named serializable object bound to session. + * + * @param name attribute name. The following names have predefined values: + *
    + *
  • userId - current or substituted user ID
  • + *
  • userLogin - current or substituted user login in lower case
  • + *
+ * @return attribute value or null if attribute with the given name is not found + */ + @SuppressWarnings("unchecked") + @Nullable + public T getAttribute(String name) { + if ("userId".equals(name)) + return (T) getCurrentOrSubstitutedUser().getId(); + if ("userLogin".equals(name)) + return (T) getCurrentOrSubstitutedUser().getLoginLowerCase(); + else + return (T) attributes.get(name); + } + + /** + * Remove user session attribute. Attribute is a named serializable object bound to session. + * + * @param name attribute name + */ + public void removeAttribute(String name) { + attributes.remove(name); + } + + /** + * Set user session attribute. Attribute is a named serializable object bound to session. + * + * @param name attribute name + * @param value attribute value + */ + public void setAttribute(String name, Serializable value) { + attributes.put(name, value); + } + + /** + * User session attribute names. Attribute is a named serializable object bound to session. + */ + public Collection getAttributeNames() { + return new ArrayList<>(attributes.keySet()); + } + + /** + * Get local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, + * local attributes are not passed between tiers and not replicated in cluster. + * + * @param name attribute name + * @return attribute value or null if attribute with the given name is not found + */ + @SuppressWarnings("unchecked") + @Nullable + public T getLocalAttribute(String name) { + return (T) localAttributes.get(name); + } + + /** + * Remove local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, + * local attributes are not passed between tiers and not replicated in cluster. + * + * @param name attribute name + */ + public void removeLocalAttribute(String name) { + localAttributes.remove(name); + } + + /** + * Set local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, + * local attributes are not passed between tiers and not replicated in cluster. + * + * @param name attribute name + * @param value attribute value + */ + public void setLocalAttribute(String name, Object value) { + localAttributes.put(name, value); + } + + /** + * Set local attribute. Local attribute is a named object bound to session. Unlike normal user session attributes, + * local attributes are not passed between tiers and not replicated in cluster. + * + * @param name attribute name + * @param value attribute value + * @return the previous value associated with the specified key, or + * {@code null} if there was no mapping for the key. + * (A {@code null} return can also indicate that the map + * previously associated {@code null} with the key, + * if the implementation supports null values.) + */ + public Object setLocalAttributeIfAbsent(String name, Object value) { + return localAttributes.putIfAbsent(name, value); + } + + /** + * Local attribute names. Local attribute is a named object bound to session. Unlike normal user session attributes, + * local attributes are not passed between tiers and not replicated in cluster. + */ + public Collection getLocalAttributeNames() { + return new ArrayList<>(localAttributes.keySet()); + } + + /** + * System session is created by LoginWorker.loginSystem() for system users like schedulers and JMX. + *

+ * It is not replicated in cluster. + */ + public boolean isSystem() { + return system; + } + + @Override + public String toString() { + return id + " [" + + user.getLogin() + (substitutedUser == null ? "" : " / " + substitutedUser.getLogin()) + + "]"; + } +} diff --git a/modules/global/src/com/haulmont/cuba/security/global/UserUtils.java b/modules/global/src/com/haulmont/cuba/security/global/UserUtils.java index e48e42abfd..0d5291e7cc 100644 --- a/modules/global/src/com/haulmont/cuba/security/global/UserUtils.java +++ b/modules/global/src/com/haulmont/cuba/security/global/UserUtils.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.security.global; - -import org.apache.commons.lang.StringUtils; - -import java.text.ParseException; - -/** - * Utility class for {@link com.haulmont.cuba.security.entity.User} full name creation. - * - */ -public class UserUtils { - - public static String formatName(String pattern, String firstName, String lastName, String middleName) throws ParseException { - if (pattern == null || pattern.length() == 0) - throw new ParseException("Pattern error", 0); - if (firstName == null || firstName.equals("null")) - firstName = ""; - if (lastName == null || lastName.equals("null")) - lastName = ""; - if (middleName == null || middleName.equals("null")) - middleName = ""; - String[] params = StringUtils.substringsBetween(pattern, "{", "}"); - int i; - for (i = 0; i < params.length; i++) { - pattern = StringUtils.replace(pattern, "{" + params[i] + "}", "{" + i + "}", 1); - params[i] = parseParam(params[i], firstName, lastName, middleName); - } - for (i = 0; i < params.length; i++) { - pattern = StringUtils.replace(pattern, "{" + i + "}", params[i], 1); - } - return pattern; - } - - private static String parseParam(String param, String firstName, String lastName, String middleName) throws ParseException { - if (param == null || param.length() == 0) - throw new ParseException("Pattern error", 0); - String last = StringUtils.substringAfter(param, "|"); - String first = StringUtils.upperCase(StringUtils.substringBefore(param, "|")); - if (first == null || first.length() == 0) - throw new ParseException("Pattern error", 0); - char type = first.charAt(0); - boolean all = true; - int length = 0; - if (first.length() > 1) { - char ch = first.charAt(1); - switch (ch) { - case 'F': - case 'L': - case 'M': - if (first.length() != 2 || type != ch) - throw new ParseException("Pattern error", 2); - break; - default: - length = Integer.parseInt(first.substring(1, first.length())); - break; - } - } else { - all = false; - length = 1; - } - switch (type) { - case 'F': - first = firstName; - break; - case 'L': - first = lastName; - break; - case 'M': - first = middleName; - break; - default: - throw new ParseException("Pattern error", 0); - } - if (!all) { - first = StringUtils.left(first, length); - } - return (first.length() > 0) ? first + last : ""; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.security.global; + +import org.apache.commons.lang.StringUtils; + +import java.text.ParseException; + +/** + * Utility class for {@link com.haulmont.cuba.security.entity.User} full name creation. + * + */ +public class UserUtils { + + public static String formatName(String pattern, String firstName, String lastName, String middleName) throws ParseException { + if (pattern == null || pattern.length() == 0) + throw new ParseException("Pattern error", 0); + if (firstName == null || firstName.equals("null")) + firstName = ""; + if (lastName == null || lastName.equals("null")) + lastName = ""; + if (middleName == null || middleName.equals("null")) + middleName = ""; + String[] params = StringUtils.substringsBetween(pattern, "{", "}"); + int i; + for (i = 0; i < params.length; i++) { + pattern = StringUtils.replace(pattern, "{" + params[i] + "}", "{" + i + "}", 1); + params[i] = parseParam(params[i], firstName, lastName, middleName); + } + for (i = 0; i < params.length; i++) { + pattern = StringUtils.replace(pattern, "{" + i + "}", params[i], 1); + } + return pattern; + } + + private static String parseParam(String param, String firstName, String lastName, String middleName) throws ParseException { + if (param == null || param.length() == 0) + throw new ParseException("Pattern error", 0); + String last = StringUtils.substringAfter(param, "|"); + String first = StringUtils.upperCase(StringUtils.substringBefore(param, "|")); + if (first == null || first.length() == 0) + throw new ParseException("Pattern error", 0); + char type = first.charAt(0); + boolean all = true; + int length = 0; + if (first.length() > 1) { + char ch = first.charAt(1); + switch (ch) { + case 'F': + case 'L': + case 'M': + if (first.length() != 2 || type != ch) + throw new ParseException("Pattern error", 2); + break; + default: + length = Integer.parseInt(first.substring(1, first.length())); + break; + } + } else { + all = false; + length = 1; + } + switch (type) { + case 'F': + first = firstName; + break; + case 'L': + first = lastName; + break; + case 'M': + first = middleName; + break; + default: + throw new ParseException("Pattern error", 0); + } + if (!all) { + first = StringUtils.left(first, length); + } + return (first.length() > 0) ? first + last : ""; + } +} diff --git a/modules/global/src/cuba-metadata.xml b/modules/global/src/cuba-metadata.xml index 6b27fa15d8..49d983c7f6 100644 --- a/modules/global/src/cuba-metadata.xml +++ b/modules/global/src/cuba-metadata.xml @@ -1,79 +1,79 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.haulmont.cuba.core.entity.AbstractNotPersistentEntity - com.haulmont.cuba.core.entity.KeyValueEntity - com.haulmont.cuba.core.entity.diff.EntityBasicPropertyDiff - com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff - com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff - com.haulmont.cuba.core.entity.diff.EntityDiff - com.haulmont.cuba.core.entity.diff.EntityPropertyDiff - com.haulmont.cuba.core.global.LockInfo - com.haulmont.cuba.security.entity.EntityLogAttr - com.haulmont.cuba.security.entity.UserSessionEntity - com.haulmont.cuba.core.config.AppPropertyEntity - com.haulmont.cuba.core.entity.ScreenProfilerEvent - com.haulmont.cuba.core.entity.CategoryAttributeEnumValue - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.haulmont.cuba.core.entity.AbstractNotPersistentEntity + com.haulmont.cuba.core.entity.KeyValueEntity + com.haulmont.cuba.core.entity.diff.EntityBasicPropertyDiff + com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff + com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff + com.haulmont.cuba.core.entity.diff.EntityDiff + com.haulmont.cuba.core.entity.diff.EntityPropertyDiff + com.haulmont.cuba.core.global.LockInfo + com.haulmont.cuba.security.entity.EntityLogAttr + com.haulmont.cuba.security.entity.UserSessionEntity + com.haulmont.cuba.core.config.AppPropertyEntity + com.haulmont.cuba.core.entity.ScreenProfilerEvent + com.haulmont.cuba.core.entity.CategoryAttributeEnumValue + + \ No newline at end of file diff --git a/modules/global/src/cuba-persistence.xml b/modules/global/src/cuba-persistence.xml index dab4c84196..ebe0cc917e 100644 --- a/modules/global/src/cuba-persistence.xml +++ b/modules/global/src/cuba-persistence.xml @@ -1,73 +1,73 @@ - - - - - - - com.haulmont.cuba.core.entity.Server - com.haulmont.cuba.core.entity.Config - com.haulmont.cuba.core.entity.FileDescriptor - com.haulmont.cuba.core.entity.LockDescriptor - com.haulmont.cuba.core.entity.Folder - com.haulmont.cuba.core.entity.AbstractSearchFolder - com.haulmont.cuba.core.entity.AppFolder - com.haulmont.cuba.core.entity.FtsQueue - com.haulmont.cuba.core.entity.EntityStatistics - com.haulmont.cuba.core.entity.SendingMessage - com.haulmont.cuba.core.entity.SendingAttachment - com.haulmont.cuba.core.entity.EntitySnapshot - com.haulmont.cuba.core.entity.ScheduledTask - com.haulmont.cuba.core.entity.ScheduledExecution - com.haulmont.cuba.core.entity.QueryResult - com.haulmont.cuba.core.entity.RestApiToken - - com.haulmont.cuba.security.entity.User - com.haulmont.cuba.security.entity.Role - com.haulmont.cuba.security.entity.UserRole - com.haulmont.cuba.security.entity.Group - com.haulmont.cuba.security.entity.GroupHierarchy - com.haulmont.cuba.security.entity.Permission - com.haulmont.cuba.security.entity.Constraint - com.haulmont.cuba.security.entity.LocalizedConstraintMessage - com.haulmont.cuba.security.entity.SessionAttribute - com.haulmont.cuba.security.entity.UserSetting - com.haulmont.cuba.security.entity.UserSubstitution - com.haulmont.cuba.security.entity.LoggedEntity - com.haulmont.cuba.security.entity.LoggedAttribute - com.haulmont.cuba.security.entity.EntityLogItem - com.haulmont.cuba.security.entity.FilterEntity - com.haulmont.cuba.security.entity.SearchFolder - com.haulmont.cuba.security.entity.Presentation - com.haulmont.cuba.security.entity.ScreenHistoryEntity - com.haulmont.cuba.security.entity.SessionLogEntry - - com.haulmont.cuba.core.entity.CategorizedEntity - com.haulmont.cuba.core.entity.Category - com.haulmont.cuba.core.entity.CategoryAttribute - com.haulmont.cuba.core.entity.CategoryAttributeValue - - com.haulmont.cuba.core.entity.JmxInstance - com.haulmont.cuba.security.entity.RememberMeToken - - com.haulmont.cuba.core.entity.ReferenceToEntity - - com.haulmont.cuba.core.entity.dummy.DummyCategorizedEntity - + + + + + + + com.haulmont.cuba.core.entity.Server + com.haulmont.cuba.core.entity.Config + com.haulmont.cuba.core.entity.FileDescriptor + com.haulmont.cuba.core.entity.LockDescriptor + com.haulmont.cuba.core.entity.Folder + com.haulmont.cuba.core.entity.AbstractSearchFolder + com.haulmont.cuba.core.entity.AppFolder + com.haulmont.cuba.core.entity.FtsQueue + com.haulmont.cuba.core.entity.EntityStatistics + com.haulmont.cuba.core.entity.SendingMessage + com.haulmont.cuba.core.entity.SendingAttachment + com.haulmont.cuba.core.entity.EntitySnapshot + com.haulmont.cuba.core.entity.ScheduledTask + com.haulmont.cuba.core.entity.ScheduledExecution + com.haulmont.cuba.core.entity.QueryResult + com.haulmont.cuba.core.entity.RestApiToken + + com.haulmont.cuba.security.entity.User + com.haulmont.cuba.security.entity.Role + com.haulmont.cuba.security.entity.UserRole + com.haulmont.cuba.security.entity.Group + com.haulmont.cuba.security.entity.GroupHierarchy + com.haulmont.cuba.security.entity.Permission + com.haulmont.cuba.security.entity.Constraint + com.haulmont.cuba.security.entity.LocalizedConstraintMessage + com.haulmont.cuba.security.entity.SessionAttribute + com.haulmont.cuba.security.entity.UserSetting + com.haulmont.cuba.security.entity.UserSubstitution + com.haulmont.cuba.security.entity.LoggedEntity + com.haulmont.cuba.security.entity.LoggedAttribute + com.haulmont.cuba.security.entity.EntityLogItem + com.haulmont.cuba.security.entity.FilterEntity + com.haulmont.cuba.security.entity.SearchFolder + com.haulmont.cuba.security.entity.Presentation + com.haulmont.cuba.security.entity.ScreenHistoryEntity + com.haulmont.cuba.security.entity.SessionLogEntry + + com.haulmont.cuba.core.entity.CategorizedEntity + com.haulmont.cuba.core.entity.Category + com.haulmont.cuba.core.entity.CategoryAttribute + com.haulmont.cuba.core.entity.CategoryAttributeValue + + com.haulmont.cuba.core.entity.JmxInstance + com.haulmont.cuba.security.entity.RememberMeToken + + com.haulmont.cuba.core.entity.ReferenceToEntity + + com.haulmont.cuba.core.entity.dummy.DummyCategorizedEntity + \ No newline at end of file diff --git a/modules/global/src/cuba-views.xml b/modules/global/src/cuba-views.xml index 909f572f61..dd63edd766 100644 --- a/modules/global/src/cuba-views.xml +++ b/modules/global/src/cuba-views.xml @@ -1,311 +1,311 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/AbstractClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/AbstractClass.java index 20e11d9823..d77f9c2ff9 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/AbstractClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/AbstractClass.java @@ -1,20 +1,20 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test; - -public class AbstractClass { -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test; + +public class AbstractClass { +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java index 1252f4e0cb..5cbac6fbc1 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java @@ -1,29 +1,29 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test; - -import com.haulmont.cuba.core.sys.javacl.test.pack1.SimpleClass1; -import com.haulmont.cuba.core.sys.javacl.test.pack2.SimpleClass2; - -public class SimpleClass extends AbstractClass { - SimpleClass1 simpleClass1 = new SimpleClass1(); - SimpleClass2 simpleClass2 = new SimpleClass2(); - - public SimpleClass() { - simpleClass1.setSimpleClass(this); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test; + +import com.haulmont.cuba.core.sys.javacl.test.pack1.SimpleClass1; +import com.haulmont.cuba.core.sys.javacl.test.pack2.SimpleClass2; + +public class SimpleClass extends AbstractClass { + SimpleClass1 simpleClass1 = new SimpleClass1(); + SimpleClass2 simpleClass2 = new SimpleClass2(); + + public SimpleClass() { + simpleClass1.setSimpleClass(this); + } +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java index 080427fe34..4b006cb462 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test.pack1; - -import com.haulmont.cuba.core.sys.javacl.test.SimpleClass; - -import java.lang.String; - -public class SimpleClass1 { - public void setSimpleClass(SimpleClass simpleClass) { - System.out.println(simpleClass); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test.pack1; + +import com.haulmont.cuba.core.sys.javacl.test.SimpleClass; + +import java.lang.String; + +public class SimpleClass1 { + public void setSimpleClass(SimpleClass simpleClass) { + System.out.println(simpleClass); + } +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java index 5cd565d985..148934fe60 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test.pack2; - -public class SimpleClass2 { - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test.pack2; + +public class SimpleClass2 { + +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack3/SimpleClass3.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack3/SimpleClass3.java index d52a0fdf5b..f84ee61e10 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack3/SimpleClass3.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack3/SimpleClass3.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test.pack3; - -import com.haulmont.cuba.core.sys.javacl.test.pack1.SimpleClass1; - -public class SimpleClass3 { - public void setSimpleClass1(SimpleClass1 simpleClass) { - System.out.println(simpleClass); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test.pack3; + +import com.haulmont.cuba.core.sys.javacl.test.pack1.SimpleClass1; + +public class SimpleClass3 { + public void setSimpleClass1(SimpleClass1 simpleClass) { + System.out.println(simpleClass); + } +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack4/SimpleClass4.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack4/SimpleClass4.java index 5c29e27217..5577873f80 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack4/SimpleClass4.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack4/SimpleClass4.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test.pack4; - -import com.haulmont.cuba.core.sys.javacl.test.pack3.SimpleClass3; - -public class SimpleClass4 { - public void setSimpleClass3(SimpleClass3 simpleClass) { - System.out.println(simpleClass); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test.pack4; + +import com.haulmont.cuba.core.sys.javacl.test.pack3.SimpleClass3; + +public class SimpleClass4 { + public void setSimpleClass3(SimpleClass3 simpleClass) { + System.out.println(simpleClass); + } +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java index a135e25915..74056a9901 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test2; - -import com.haulmont.cuba.core.sys.javacl.test2.pack1.*; - -public class DependentClass { - public void doSomething() { - new DependencyClass().doSomething(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test2; + +import com.haulmont.cuba.core.sys.javacl.test2.pack1.*; + +public class DependentClass { + public void doSomething() { + new DependencyClass().doSomething(); + } } \ No newline at end of file diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java index a387257fa4..6724ba7380 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test2.pack1; - -import com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class; - -public class DependencyClass { - - public void doSomething() { - System.out.println("DependencyClass"); - new Dependency2Class().doSomething(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test2.pack1; + +import com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class; + +public class DependencyClass { + + public void doSomething() { + System.out.println("DependencyClass"); + new Dependency2Class().doSomething(); + } } \ No newline at end of file diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack2/Dependency2Class.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack2/Dependency2Class.java index 9b97505c78..ea78a1369b 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack2/Dependency2Class.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack2/Dependency2Class.java @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test2.pack2; - -public class Dependency2Class { - - public void doSomething() { - System.out.println("Dependency2Class"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test2.pack2; + +public class Dependency2Class { + + public void doSomething() { + System.out.println("Dependency2Class"); + } } \ No newline at end of file diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java index ad664a7c40..9e969d1ec8 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test3; - -public class OuterClass { - private static class InnerClass { - } - - public void init() { - Runnable runnable = new Runnable() { - @Override - public void run() { - } - }; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test3; + +public class OuterClass { + private static class InnerClass { + } + + public void init() { + Runnable runnable = new Runnable() { + @Override + public void run() { + } + }; + } } \ No newline at end of file diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java index 0da7bfce48..86117ccbf1 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test4.pack1; - -import java.lang.String; - -public class MainClass { - public static interface MainInterface { - - } - - MainInterface object; - - public MainInterface getObject() { - return object; - } - - public void setObject(MainInterface object) { - this.object = object; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test4.pack1; + +import java.lang.String; + +public class MainClass { + public static interface MainInterface { + + } + + MainInterface object; + + public MainInterface getObject() { + return object; + } + + public void setObject(MainInterface object) { + this.object = object; + } +} diff --git a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack2/DependentClass.java b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack2/DependentClass.java index 2aa38de66e..3a54305b3a 100644 --- a/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack2/DependentClass.java +++ b/modules/global/test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack2/DependentClass.java @@ -1,23 +1,23 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl.test4.pack2; - -import com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass; - -public class DependentClass implements MainClass.MainInterface { - -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl.test4.pack2; + +import com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass; + +public class DependentClass implements MainClass.MainInterface { + +} diff --git a/modules/global/test/com/haulmont/cuba/core/entity/BaseGenericIdEntityTest.java b/modules/global/test/com/haulmont/cuba/core/entity/BaseGenericIdEntityTest.java index 795c6fa3d9..2d489eea91 100644 --- a/modules/global/test/com/haulmont/cuba/core/entity/BaseGenericIdEntityTest.java +++ b/modules/global/test/com/haulmont/cuba/core/entity/BaseGenericIdEntityTest.java @@ -1,128 +1,128 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.entity; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.Session; -import com.haulmont.chile.core.model.impl.MetaClassImpl; -import com.haulmont.chile.core.model.impl.MetaModelImpl; -import com.haulmont.chile.core.model.impl.SessionImpl; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.core.global.ReferenceToEntitySupport; -import com.haulmont.cuba.security.entity.User; -import org.junit.Assert; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; -import mockit.NonStrictExpectations; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.HashMap; - -public class BaseGenericIdEntityTest { - - @SuppressWarnings("unused") - @Mocked - protected AppBeans appBeans; - - @Mocked - protected DynamicAttributes dynamicAttributes; - - @Mocked - protected Metadata metadata; - - @Mocked - protected ReferenceToEntitySupport referenceToEntitySupport; - - @Before - public void setUp() throws Exception { - dynamicAttributes = new MockUp() { - @SuppressWarnings("UnusedDeclaration") - @Mock - CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { - CategoryAttribute categoryAttribute = new CategoryAttribute(); - categoryAttribute.setCode(code); - return categoryAttribute; - } - }.getMockInstance(); - - metadata = new MockUp() { - @SuppressWarnings("UnusedDeclaration") - @Mock - Session getSession(){ - return new SessionImpl() { - @Override - public MetaClass getClassNN(String name) { - return new MetaClassImpl(new MetaModelImpl(this, name), name); - } - - @Override - public MetaClass getClassNN(Class clazz) { - return new MetaClassImpl(new MetaModelImpl(this, clazz.getName()), clazz.getName()); - } - }; - } - - @SuppressWarnings({"UnusedDeclaration", "unchecked"}) - @Mock - T create(Class entityClass) { - if (User.class.equals(entityClass)) { - return (T) new User(); - } - if (CategoryAttributeValue.class.equals(entityClass)) { - CategoryAttributeValue attributeValue = new CategoryAttributeValue(); - attributeValue.setEntity(new ReferenceToEntity()); - return (T) attributeValue; - } - throw new IllegalArgumentException("Add support for " + entityClass.getSimpleName() + " to Mock"); - } - }.getMockInstance(); - - new NonStrictExpectations() { - { - AppBeans.get(DynamicAttributes.NAME); result = dynamicAttributes; - AppBeans.get(Metadata.NAME); result = metadata; - AppBeans.get(ReferenceToEntitySupport.class); result = referenceToEntitySupport; - } - }; - } - - @Test - public void testDynamicAttributes() throws Exception { - User user = new User(); - - try { - user.setValue("+extend", null); - Assert.fail("should fail with exception"); - } catch (Exception e) { - //do nothing - } - - user.setDynamicAttributes(new HashMap<>()); - - user.setValue("+extend", "some dynamic value"); - Assert.assertEquals("some dynamic value", user.getValue("+extend")); - - user.setValue("+extend", "another dynamic value"); - Assert.assertEquals("another dynamic value", user.getValue("+extend")); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.entity; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.Session; +import com.haulmont.chile.core.model.impl.MetaClassImpl; +import com.haulmont.chile.core.model.impl.MetaModelImpl; +import com.haulmont.chile.core.model.impl.SessionImpl; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.core.global.ReferenceToEntitySupport; +import com.haulmont.cuba.security.entity.User; +import org.junit.Assert; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; +import mockit.NonStrictExpectations; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.HashMap; + +public class BaseGenericIdEntityTest { + + @SuppressWarnings("unused") + @Mocked + protected AppBeans appBeans; + + @Mocked + protected DynamicAttributes dynamicAttributes; + + @Mocked + protected Metadata metadata; + + @Mocked + protected ReferenceToEntitySupport referenceToEntitySupport; + + @Before + public void setUp() throws Exception { + dynamicAttributes = new MockUp() { + @SuppressWarnings("UnusedDeclaration") + @Mock + CategoryAttribute getAttributeForMetaClass(MetaClass metaClass, String code) { + CategoryAttribute categoryAttribute = new CategoryAttribute(); + categoryAttribute.setCode(code); + return categoryAttribute; + } + }.getMockInstance(); + + metadata = new MockUp() { + @SuppressWarnings("UnusedDeclaration") + @Mock + Session getSession(){ + return new SessionImpl() { + @Override + public MetaClass getClassNN(String name) { + return new MetaClassImpl(new MetaModelImpl(this, name), name); + } + + @Override + public MetaClass getClassNN(Class clazz) { + return new MetaClassImpl(new MetaModelImpl(this, clazz.getName()), clazz.getName()); + } + }; + } + + @SuppressWarnings({"UnusedDeclaration", "unchecked"}) + @Mock + T create(Class entityClass) { + if (User.class.equals(entityClass)) { + return (T) new User(); + } + if (CategoryAttributeValue.class.equals(entityClass)) { + CategoryAttributeValue attributeValue = new CategoryAttributeValue(); + attributeValue.setEntity(new ReferenceToEntity()); + return (T) attributeValue; + } + throw new IllegalArgumentException("Add support for " + entityClass.getSimpleName() + " to Mock"); + } + }.getMockInstance(); + + new NonStrictExpectations() { + { + AppBeans.get(DynamicAttributes.NAME); result = dynamicAttributes; + AppBeans.get(Metadata.NAME); result = metadata; + AppBeans.get(ReferenceToEntitySupport.class); result = referenceToEntitySupport; + } + }; + } + + @Test + public void testDynamicAttributes() throws Exception { + User user = new User(); + + try { + user.setValue("+extend", null); + Assert.fail("should fail with exception"); + } catch (Exception e) { + //do nothing + } + + user.setDynamicAttributes(new HashMap<>()); + + user.setValue("+extend", "some dynamic value"); + Assert.assertEquals("some dynamic value", user.getValue("+extend")); + + user.setValue("+extend", "another dynamic value"); + Assert.assertEquals("another dynamic value", user.getValue("+extend")); + } } \ No newline at end of file diff --git a/modules/global/test/com/haulmont/cuba/core/global/QueryTransformationTest.java b/modules/global/test/com/haulmont/cuba/core/global/QueryTransformationTest.java index 04c82f894f..a121417ede 100644 --- a/modules/global/test/com/haulmont/cuba/core/global/QueryTransformationTest.java +++ b/modules/global/test/com/haulmont/cuba/core/global/QueryTransformationTest.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.global; - -import com.haulmont.cuba.core.sys.jpql.DomainModel; -import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; -import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; -import com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased; -import org.junit.Test; - -public class QueryTransformationTest { - @Test - public void testAst() throws Exception { - for (int i = 0; i < 1000; i++) { - QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(prepareDomainModel(), "select g from sec$GroupHierarchy g"); - transformerAstBased.addWhere("g.deleteTs is null"); - } - } - - @Test - public void testRegexp() throws Exception { - for (int i = 0; i < 1000; i++) { - QueryTransformerRegex queryTransformerRegex = new QueryTransformerRegex("select g from sec$GroupHierarchy g"); - queryTransformerRegex.addWhere("g.deleteTs is null"); - } - } - - private DomainModel prepareDomainModel() { - EntityBuilder builder = new EntityBuilder(); - builder.startNewEntity("sec$GroupHierarchy"); - builder.addStringAttribute("group"); - builder.addStringAttribute("createdBy"); - builder.addReferenceAttribute("parent", "sec$GroupHierarchy"); - builder.addReferenceAttribute("other", "sec$GroupHierarchy"); - builder.addCollectionReferenceAttribute("constraints", "sec$Constraint"); - JpqlEntityModel groupHierarchy = builder.produce(); - - JpqlEntityModel constraintEntity = builder.produceImmediately("sec$Constraint"); - return new DomainModel(groupHierarchy, constraintEntity); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.global; + +import com.haulmont.cuba.core.sys.jpql.DomainModel; +import com.haulmont.cuba.core.sys.jpql.model.JpqlEntityModel; +import com.haulmont.cuba.core.sys.jpql.model.EntityBuilder; +import com.haulmont.cuba.core.sys.jpql.transform.QueryTransformerAstBased; +import org.junit.Test; + +public class QueryTransformationTest { + @Test + public void testAst() throws Exception { + for (int i = 0; i < 1000; i++) { + QueryTransformerAstBased transformerAstBased = new QueryTransformerAstBased(prepareDomainModel(), "select g from sec$GroupHierarchy g"); + transformerAstBased.addWhere("g.deleteTs is null"); + } + } + + @Test + public void testRegexp() throws Exception { + for (int i = 0; i < 1000; i++) { + QueryTransformerRegex queryTransformerRegex = new QueryTransformerRegex("select g from sec$GroupHierarchy g"); + queryTransformerRegex.addWhere("g.deleteTs is null"); + } + } + + private DomainModel prepareDomainModel() { + EntityBuilder builder = new EntityBuilder(); + builder.startNewEntity("sec$GroupHierarchy"); + builder.addStringAttribute("group"); + builder.addStringAttribute("createdBy"); + builder.addReferenceAttribute("parent", "sec$GroupHierarchy"); + builder.addReferenceAttribute("other", "sec$GroupHierarchy"); + builder.addCollectionReferenceAttribute("constraints", "sec$Constraint"); + JpqlEntityModel groupHierarchy = builder.produce(); + + JpqlEntityModel constraintEntity = builder.produceImmediately("sec$Constraint"); + return new DomainModel(groupHierarchy, constraintEntity); + } } \ No newline at end of file diff --git a/modules/global/test/com/haulmont/cuba/core/sys/javacl/JavaClassLoaderTest.java b/modules/global/test/com/haulmont/cuba/core/sys/javacl/JavaClassLoaderTest.java index cfbaffd163..9d0ffbf3ba 100644 --- a/modules/global/test/com/haulmont/cuba/core/sys/javacl/JavaClassLoaderTest.java +++ b/modules/global/test/com/haulmont/cuba/core/sys/javacl/JavaClassLoaderTest.java @@ -1,229 +1,229 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.core.sys.javacl; - -import com.haulmont.cuba.core.sys.SpringBeanLoader; -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.lang.reflect.Method; -import java.util.Date; - -public class JavaClassLoaderTest { - @Test - public void testSimple() throws Exception { - System.out.println(new File(".").getAbsolutePath()); - - JavaClassLoader javaClassLoader = new JavaClassLoader(Thread.currentThread().getContextClassLoader(), "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test0.Simple"); - System.out.println("Class loaded " + class1); -// Class class2 = Class.forName("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - Class class2 = Class.forName("com.haulmont.cuba.core.sys.javacl.test0.Simple", false, javaClassLoader); - System.out.println("Class loaded " + class2); - - Assert.assertEquals(class1, class2); - } - - @Test - public void testDependencies() throws Exception { - System.out.println(new File(".").getAbsolutePath()); - - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("Class loaded"); - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java"); - System.out.println("SimpleClass modified"); - Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - Assert.assertNotSame(class1, class2); - Assert.assertEquals(javaClassLoader.compiled.size(), 4); - System.out.println("Class reloaded"); - - System.out.println("No changes"); - Class class3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - Assert.assertEquals(class2, class3); - System.out.println("Class reloaded, same class received"); - - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java"); - System.out.println("SimpleClass1 modified"); - - Class class4 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - Assert.assertNotSame(class3, class4); - System.out.println("Class reloaded"); - } - - @Test - public void testDependent() throws Exception { - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class simpleClass4 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); - System.out.println("SimpleClass4 loaded " + simpleClass4.hashCode()); - Class simpleClass = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("SimpleClass loaded " + simpleClass.hashCode()); - - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java"); - - Class simpleClass_2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("SimpleClass loaded " + simpleClass_2.hashCode()); - Class simpleClass4_2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); - System.out.println("SimpleClass4 loaded " + simpleClass4_2.hashCode()); - - Assert.assertNotSame(simpleClass, simpleClass_2); - Assert.assertNotSame(simpleClass4, simpleClass4_2); - - Class simpleClass_3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("SimpleClass loaded " + simpleClass_3.hashCode()); - Class simpleClass4_3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); - System.out.println("SimpleClass4 loaded " + simpleClass4_3.hashCode()); - - Assert.assertEquals(simpleClass_2, simpleClass_3); - Assert.assertEquals(simpleClass4_2, simpleClass4_3); - } - - @Test - public void testLinkageError() throws Exception { - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("Class loaded " + class1.hashCode()); - - Object o = class1.newInstance(); - System.out.println(o.toString()); - - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java"); - - Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); - System.out.println("Class loaded " + class2.hashCode()); - - o = class2.newInstance(); - System.out.println(o.toString()); - } - - private void modifyFile(String path) throws InterruptedException { - Thread.sleep(1000l); - File file = new File(path); - boolean result = file.setLastModified(System.currentTimeMillis()); - } - - @Test - public void testTwiceCompilation() throws Exception { - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.DependentClass"); - Class dependencyClass1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack1.DependencyClass"); - Class dependency2Class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class"); - System.out.println("Class loaded"); - Assert.assertEquals(javaClassLoader.compiled.size(), 3); - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java"); - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java"); - System.out.println("DependentClass modified"); - System.out.println("DependencyClass modified"); - - Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.DependentClass"); - Class dependencyClass2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack1.DependencyClass"); - Class dependency2Class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class"); - Assert.assertNotSame(class1, class2); - Assert.assertNotSame(dependencyClass1, dependencyClass2); - Assert.assertSame(dependency2Class1, dependency2Class2); - } - - @Test - public void testInnerClasses() throws Exception { - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test3.OuterClass"); - Class innerClass1 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$InnerClass").clazz; - Class innerClass2 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$1").clazz; - System.out.println("Class loaded"); - Assert.assertEquals(javaClassLoader.compiled.size(), 3); - modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java"); - - Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test3.OuterClass"); - Class innerClass3 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$InnerClass").clazz; - Class innerClass4 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$1").clazz; - Assert.assertNotSame(class1, class2); - Assert.assertNotSame(innerClass1, innerClass3); - Assert.assertNotSame(innerClass2, innerClass4); - } - - @Test - public void testCompanion() throws Exception { - System.out.println(new File(".").getAbsolutePath()); - - JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { - @Override - protected Date getCurrentTimestamp() { - return new Date(); - } - }; - - Class class10 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass"); - Class interface10 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass$MainInterface"); - - Object object10 = class10.newInstance(); - - Class class20 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack2.DependentClass"); - Object object20 = class20.newInstance(); - - Method method = class10.getDeclaredMethod("setObject", interface10); - method.invoke(object10, object20); - - modifyFile("test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java"); - - Class class11 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass"); - Class interface11 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass$MainInterface"); - Class class21 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack2.DependentClass"); - - Object object11 = class11.newInstance(); - Object object21 = class21.newInstance(); - - method = class11.getDeclaredMethod("setObject", interface11); - method.invoke(object11, object21); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.core.sys.javacl; + +import com.haulmont.cuba.core.sys.SpringBeanLoader; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.Date; + +public class JavaClassLoaderTest { + @Test + public void testSimple() throws Exception { + System.out.println(new File(".").getAbsolutePath()); + + JavaClassLoader javaClassLoader = new JavaClassLoader(Thread.currentThread().getContextClassLoader(), "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test0.Simple"); + System.out.println("Class loaded " + class1); +// Class class2 = Class.forName("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + Class class2 = Class.forName("com.haulmont.cuba.core.sys.javacl.test0.Simple", false, javaClassLoader); + System.out.println("Class loaded " + class2); + + Assert.assertEquals(class1, class2); + } + + @Test + public void testDependencies() throws Exception { + System.out.println(new File(".").getAbsolutePath()); + + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("Class loaded"); + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java"); + System.out.println("SimpleClass modified"); + Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + Assert.assertNotSame(class1, class2); + Assert.assertEquals(javaClassLoader.compiled.size(), 4); + System.out.println("Class reloaded"); + + System.out.println("No changes"); + Class class3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + Assert.assertEquals(class2, class3); + System.out.println("Class reloaded, same class received"); + + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack1/SimpleClass1.java"); + System.out.println("SimpleClass1 modified"); + + Class class4 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + Assert.assertNotSame(class3, class4); + System.out.println("Class reloaded"); + } + + @Test + public void testDependent() throws Exception { + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class simpleClass4 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); + System.out.println("SimpleClass4 loaded " + simpleClass4.hashCode()); + Class simpleClass = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("SimpleClass loaded " + simpleClass.hashCode()); + + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/SimpleClass.java"); + + Class simpleClass_2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("SimpleClass loaded " + simpleClass_2.hashCode()); + Class simpleClass4_2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); + System.out.println("SimpleClass4 loaded " + simpleClass4_2.hashCode()); + + Assert.assertNotSame(simpleClass, simpleClass_2); + Assert.assertNotSame(simpleClass4, simpleClass4_2); + + Class simpleClass_3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("SimpleClass loaded " + simpleClass_3.hashCode()); + Class simpleClass4_3 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.pack4.SimpleClass4"); + System.out.println("SimpleClass4 loaded " + simpleClass4_3.hashCode()); + + Assert.assertEquals(simpleClass_2, simpleClass_3); + Assert.assertEquals(simpleClass4_2, simpleClass4_3); + } + + @Test + public void testLinkageError() throws Exception { + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("Class loaded " + class1.hashCode()); + + Object o = class1.newInstance(); + System.out.println(o.toString()); + + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test/pack2/SimpleClass2.java"); + + Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test.SimpleClass"); + System.out.println("Class loaded " + class2.hashCode()); + + o = class2.newInstance(); + System.out.println(o.toString()); + } + + private void modifyFile(String path) throws InterruptedException { + Thread.sleep(1000l); + File file = new File(path); + boolean result = file.setLastModified(System.currentTimeMillis()); + } + + @Test + public void testTwiceCompilation() throws Exception { + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.DependentClass"); + Class dependencyClass1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack1.DependencyClass"); + Class dependency2Class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class"); + System.out.println("Class loaded"); + Assert.assertEquals(javaClassLoader.compiled.size(), 3); + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/DependentClass.java"); + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test2/pack1/DependencyClass.java"); + System.out.println("DependentClass modified"); + System.out.println("DependencyClass modified"); + + Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.DependentClass"); + Class dependencyClass2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack1.DependencyClass"); + Class dependency2Class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test2.pack2.Dependency2Class"); + Assert.assertNotSame(class1, class2); + Assert.assertNotSame(dependencyClass1, dependencyClass2); + Assert.assertSame(dependency2Class1, dependency2Class2); + } + + @Test + public void testInnerClasses() throws Exception { + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class1 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test3.OuterClass"); + Class innerClass1 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$InnerClass").clazz; + Class innerClass2 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$1").clazz; + System.out.println("Class loaded"); + Assert.assertEquals(javaClassLoader.compiled.size(), 3); + modifyFile("./test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test3/OuterClass.java"); + + Class class2 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test3.OuterClass"); + Class innerClass3 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$InnerClass").clazz; + Class innerClass4 = javaClassLoader.compiled.get("com.haulmont.cuba.core.sys.javacl.test3.OuterClass$1").clazz; + Assert.assertNotSame(class1, class2); + Assert.assertNotSame(innerClass1, innerClass3); + Assert.assertNotSame(innerClass2, innerClass4); + } + + @Test + public void testCompanion() throws Exception { + System.out.println(new File(".").getAbsolutePath()); + + JavaClassLoader javaClassLoader = new JavaClassLoader(null, "./test-data/javacl-sources/", "", new SpringBeanLoader()) { + @Override + protected Date getCurrentTimestamp() { + return new Date(); + } + }; + + Class class10 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass"); + Class interface10 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass$MainInterface"); + + Object object10 = class10.newInstance(); + + Class class20 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack2.DependentClass"); + Object object20 = class20.newInstance(); + + Method method = class10.getDeclaredMethod("setObject", interface10); + method.invoke(object10, object20); + + modifyFile("test-data/javacl-sources/com/haulmont/cuba/core/sys/javacl/test4/pack1/MainClass.java"); + + Class class11 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass"); + Class interface11 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack1.MainClass$MainInterface"); + Class class21 = javaClassLoader.loadClass("com.haulmont.cuba.core.sys.javacl.test4.pack2.DependentClass"); + + Object object11 = class11.newInstance(); + Object object21 = class21.newInstance(); + + method = class11.getDeclaredMethod("setObject", interface11); + method.invoke(object11, object21); + } } \ No newline at end of file diff --git a/modules/global/test/com/haulmont/cuba/core/sys/jpql/EntityPathTest.java b/modules/global/test/com/haulmont/cuba/core/sys/jpql/EntityPathTest.java index 0a088c8838..e318fa3dde 100644 --- a/modules/global/test/com/haulmont/cuba/core/sys/jpql/EntityPathTest.java +++ b/modules/global/test/com/haulmont/cuba/core/sys/jpql/EntityPathTest.java @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public class EntityPathTest { - @Test - public void parseEntityPath() { - EntityPath path = EntityPath.parseEntityPath("p.ni"); - assertEquals("p", path.topEntityVariableName); - assertEquals("ni", path.lastEntityFieldPattern); - assertArrayEquals(new String[0], path.traversedFields); - - path = EntityPath.parseEntityPath("p."); - assertEquals("p", path.topEntityVariableName); - assertEquals("", path.lastEntityFieldPattern); - assertArrayEquals(new String[0], path.traversedFields); - - path = EntityPath.parseEntityPath("p.team."); - assertEquals("p", path.topEntityVariableName); - assertEquals("", path.lastEntityFieldPattern); - assertArrayEquals(new String[]{"team"}, path.traversedFields); - - path = EntityPath.parseEntityPath("p.team.owner.na"); - assertEquals("p", path.topEntityVariableName); - assertEquals("na", path.lastEntityFieldPattern); - assertArrayEquals(new String[]{"team", "owner"}, path.traversedFields); - - path = EntityPath.parseEntityPath("."); - Assert.assertNull(path.topEntityVariableName); - assertEquals(null, path.lastEntityFieldPattern); - assertArrayEquals(new String[0], path.traversedFields); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class EntityPathTest { + @Test + public void parseEntityPath() { + EntityPath path = EntityPath.parseEntityPath("p.ni"); + assertEquals("p", path.topEntityVariableName); + assertEquals("ni", path.lastEntityFieldPattern); + assertArrayEquals(new String[0], path.traversedFields); + + path = EntityPath.parseEntityPath("p."); + assertEquals("p", path.topEntityVariableName); + assertEquals("", path.lastEntityFieldPattern); + assertArrayEquals(new String[0], path.traversedFields); + + path = EntityPath.parseEntityPath("p.team."); + assertEquals("p", path.topEntityVariableName); + assertEquals("", path.lastEntityFieldPattern); + assertArrayEquals(new String[]{"team"}, path.traversedFields); + + path = EntityPath.parseEntityPath("p.team.owner.na"); + assertEquals("p", path.topEntityVariableName); + assertEquals("na", path.lastEntityFieldPattern); + assertArrayEquals(new String[]{"team", "owner"}, path.traversedFields); + + path = EntityPath.parseEntityPath("."); + Assert.assertNull(path.topEntityVariableName); + assertEquals(null, path.lastEntityFieldPattern); + assertArrayEquals(new String[0], path.traversedFields); + } } \ No newline at end of file diff --git a/modules/global/test/com/haulmont/cuba/core/sys/jpql/Jpa2GrammarTest.java b/modules/global/test/com/haulmont/cuba/core/sys/jpql/Jpa2GrammarTest.java index ec8bbbde33..15a9051b96 100644 --- a/modules/global/test/com/haulmont/cuba/core/sys/jpql/Jpa2GrammarTest.java +++ b/modules/global/test/com/haulmont/cuba/core/sys/jpql/Jpa2GrammarTest.java @@ -1,389 +1,389 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.core.sys.jpql; - -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; -import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Parser; -import org.antlr.runtime.CharStream; -import org.antlr.runtime.CommonTokenStream; -import org.antlr.runtime.RecognitionException; -import org.antlr.runtime.TokenStream; -import org.antlr.runtime.tree.CommonErrorNode; -import org.antlr.runtime.tree.CommonTree; -import org.antlr.runtime.tree.TreeVisitor; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.List; - -public class Jpa2GrammarTest { - - @Test - public void testExtensionFunctions() throws Exception { - testQuery("select cast(e.number text) from app$MyEntity e where e.path like cast(:ds$myEntityDs.id text)"); - testQuery("select cast(e.number numeric(10,2)) from app$MyEntity e where e.number = cast(:ds$myEntityDs.id numeric(10,2))"); - testQuery("select cast(e.number varchar(100)) from app$MyEntity e where e.name = cast(:ds$myEntityDs.id varchar(100))"); - testQuery("select cast(e.number strange_type(1,2,3,4)) from app$MyEntity e where e.field1 = cast(:ds$myEntityDs.id strange_type(1,2,3,4))"); - - testQuery("select e from app$MyEntity e where e.name REGEXP '.*'"); - - testQuery("select extract(YEAR from e.createTs) from app$MyEntity e where extract(YEAR from e.createTs) > 2012"); - testQuery("select extract(MONTH from e.createTs) from app$MyEntity e where extract(MONTH from e.createTs) > 10"); - testQuery("select extract(DAY from e.createTs) from app$MyEntity e where extract(DAY from e.createTs) > 15"); - - testQuery("select extract(DAY FROM e.createTs), count(e.id) from app$MyEntity e group by extract(DAY FROM e.createTs)"); - } - - @Test - public void testGroupBy() throws Exception { - testQuery("select u.login " + - "from sec$User u " + - "where u.login = 'admin' " + - "group by u.login having u.version > 0" + - "order by u.login"); - } - - @Test - public void testGroupAlias() throws Exception { - testQuery("select group.name from sec$User u left join e.group group where u.login = 'admin'"); - } - - @Test - public void testOrderByCount() throws Exception { - testQuery("select instance.bookPublication.publisher.name, count(instance) " + - "from library$BookInstance instance " + - "group by instance.bookPublication.publisher.name order by count(instance) desc"); - - testQuery("select instance.bookPublication.publisher.name, instance.bookPublication.year, count(instance) " + - "from library$BookInstance instance " + - "group by instance.bookPublication.year, instance.bookPublication.publisher.name " + - "order by instance.bookPublication.year, instance.bookPublication.publisher.name"); - } - - @Test - @Ignore - public void testFunction() throws Exception { - testQuery("select u from sec$User u where function('DAYOFMONTH', u.createTs) = 1"); - testQuery("select u from sec$User u where function('hasRoles', u.createdBy, u.login)"); - } - - @Test - public void testParserParameters() throws Exception { - String query = "select sm from sys$SendingMessage sm " + - "where sm.status=:(?i)statusQueue or (sm.status = :statusSending and sm.updateTs<:time) " + - "order by sm.createTs"; - testQuery(query); - } - - @Test - public void testJoinOn() throws Exception { - String query = "select h " + - "from sec$Constraint u, sec$GroupHierarchy h join sec$Constraint c on c.group.id = h.parent.id " + - "where h.userGroup = :par"; - testQuery(query); - } - - @Test - public void testEscape() throws Exception { - String query = "c.name like :pattern escape '/'"; - CharStream cs = new AntlrNoCaseStringStream(query); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - JPA2Parser jpa2Parser = new JPA2Parser(tstream); - JPA2Parser.like_expression_return aReturn = jpa2Parser.like_expression(); - Assert.assertNotNull(aReturn); - - query = "c.name like :pattern escape '.'"; - cs = new AntlrNoCaseStringStream(query); - lexer = new JPA2Lexer(cs); - tstream = new CommonTokenStream(lexer); - jpa2Parser = new JPA2Parser(tstream); - aReturn = jpa2Parser.like_expression(); - Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); - } - - @Test - public void testTypeField() throws Exception { - String query = "where e.model.type = :component$filter.model_type89015"; - CharStream cs = new AntlrNoCaseStringStream(query); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - JPA2Parser jpa2Parser = new JPA2Parser(tstream); - JPA2Parser.where_clause_return aReturn = jpa2Parser.where_clause(); - Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); - } - - @Test - @Ignore - public void testMemberOf() throws Exception { - String query = "where p.owner.id = :userParam or (select u from tamsy$User u where u.id = :userParam) member of p.developers"; - CharStream cs = new AntlrNoCaseStringStream(query); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - JPA2Parser jpa2Parser = new JPA2Parser(tstream); - JPA2Parser.where_clause_return aReturn = jpa2Parser.where_clause(); - Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); - - testQuery("SELECT d FROM app$Department d WHERE (select e from app$Employee e where e.id = :eParam) MEMBER OF e.employees"); - testQuery("SELECT e FROM app$Employee e WHERE 'write code' MEMBER OF e.codes"); - testQuery("SELECT e FROM app$Employee e WHERE 'write code' NOT MEMBER OF e.codes"); - } - - @Test - public void testOrderBy() throws Exception { - testQuery("select c from ref$Contract c order by c.number"); - testQuery("select c from ref$Contract c order by c.number asc"); - testQuery("select c from ref$Contract c order by c.number desc"); - testQuery("select c from ref$Contract c order by c.order desc, c.number asc"); - testQuery("select c from ref$Contract c order by c.order asc, c.number desc"); - } - - @Test - public void testOrderByReservedWords() throws Exception { - testQuery("select c from ref$Contract c order by c.order"); - testQuery("select c from ref$Contract c order by c.from"); - testQuery("select c from ref$Contract c order by c.max"); - testQuery("select c from ref$Contract c order by c.min"); - testQuery("select c from ref$Contract c order by c.select"); - testQuery("select c from ref$Contract c order by c.count"); - testQuery("select c from ref$Contract c order by c.group"); - } - - @Test - public void testGroupByReservedWords() throws Exception { - testQuery("select c from ref$Contract c group by c.order"); - testQuery("select c from ref$Contract c group by c.from"); - testQuery("select c from ref$Contract c group by c.max"); - testQuery("select c from ref$Contract c group by c.min"); - testQuery("select c from ref$Contract c group by c.select"); - testQuery("select c from ref$Contract c group by c.count"); - testQuery("select c from ref$Contract c group by c.group"); - } - - @Test - public void testWhereReservedWords() throws Exception { - testQuery("select dB from taxi$DriverBan dB " + - "where dB.driver.id = :driverId " + - "and ((dB.till >= :date and (dB.from is null or dB.from <= :date)) or dB.bannedForever = true) " + - "and dB.type in (:account, :pin, :individual, :login)"); - - testQuery("select dB from taxi$DriverBan dB where dB.select is null"); - testQuery("select dB from taxi$DriverBan dB where dB.from is null"); - testQuery("select dB from taxi$DriverBan dB where dB.order is null"); - testQuery("select dB from taxi$DriverBan dB where dB.max is null"); - testQuery("select dB from taxi$DriverBan dB where dB.min is null"); - testQuery("select dB from taxi$DriverBan dB where dB.count is null"); - testQuery("select dB from taxi$DriverBan dB where dB.group is null"); - testQuery("select dB from taxi$DriverBan dB where dB.avg is null"); - testQuery("select dB from taxi$DriverBan dB where dB.size is null"); - } - - private void testQuery(String query) throws RecognitionException { - CharStream cs = new AntlrNoCaseStringStream(query); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - JPA2Parser jpa2Parser = new JPA2Parser(tstream); - JPA2Parser.ql_statement_return aReturn = jpa2Parser.ql_statement(); - Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); - } - - @Test - public void testIsNull() throws Exception { - String query = "select f from sec$Filter f left join f.user u " + - "where f.componentId = :component and (u.id = :userId or u is null) order by f.name"; - testQuery(query); - } - - @Test - public void testUpdate() throws Exception { - String query = "update sec$User u set u.group = :group where u.id = :userId"; - CharStream cs = new AntlrNoCaseStringStream(query); - JPA2Lexer lexer = new JPA2Lexer(cs); - TokenStream tstream = new CommonTokenStream(lexer); - JPA2Parser jpa2Parser = new JPA2Parser(tstream); - JPA2Parser.update_statement_return aReturn = jpa2Parser.update_statement(); - Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); - } - - protected boolean isValid(CommonTree tree) { - TreeVisitor visitor = new TreeVisitor(); - ErrorNodesFinder errorNodesFinder = new ErrorNodesFinder(); - visitor.visit(tree, errorNodesFinder); - - List errorNodes = errorNodesFinder.getErrorNodes(); - if (!errorNodes.isEmpty()) { - System.err.println(errorNodes); - } - - return errorNodes.isEmpty(); - } - - @Test - public void testInClause() throws Exception { - testQuery("select u from sec$User u where u.login in ('a', 'b', 'c')"); - testQuery("select u from sec$User u where u.login in (1, 2, 3)"); - } - - @Test - @Ignore - public void testTreat() throws Exception { - testQuery("SELECT e FROM app$Employee e JOIN TREAT(e.projects AS app$LargeProject) p WHERE p.budget > 1000000"); - testQuery("SELECT e FROM app$Employee e JOIN e.projects p WHERE TREAT(p as app$LargeProject).budget > 1000000"); - } - - @Test - public void testInCollectionMember() throws Exception { - testQuery("SELECT e FROM app$Employee e, IN(e.projects) p WHERE p.budget > 1000000"); - } - - @Test - public void testIsNotEmpty() throws Exception { - testQuery("SELECT e FROM app$Employee e WHERE e.projects IS EMPTY"); - testQuery("SELECT e FROM app$Employee e WHERE e.projects IS NOT EMPTY"); - } - - @Test - @Ignore - public void testEntityTypeExpression() throws Exception { - testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN :empTypes"); - testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN (:empType1, :empType2)"); - testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) <> app$Exempt"); - testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN (app$Exempt, app$Contractor)"); - } - - @Test - @Ignore - public void testCaseExpression() throws Exception { - testQuery("UPDATE app$Employee e SET e.salary = CASE e.rating WHEN 1 THEN e.salary * 1.1 WHEN 2 THEN e.salary * 1.05 ELSE e.salary * 1.01 END"); - testQuery("UPDATE app$Employee e SET e.salary = CASE WHEN e.rating = 1 THEN e.salary * 1.1 WHEN e.rating = 2 THEN e.salary * 1.05 ELSE e.salary * 1.01 END"); - testQuery("SELECT e.name, CASE TYPE(e) WHEN app$Exempt THEN 'Exempt' WHEN app$Contractor THEN 'Contractor' WHEN app$Intern THEN 'Intern' ELSE 'NonExempt' END FROM app$Employee e " + - "WHERE e.dept.name = 'Engineering'"); - testQuery("SELECT e.name, f.name, CONCAT(CASE WHEN f.annualMiles > 50000 THEN 'Platinum ' WHEN f.annualMiles > 25000 THEN 'Gold ' ELSE '' END, 'Frequent Flyer') " + - "FROM app$Employee e JOIN e.frequentFlierPlan f"); - } - - @Test - public void testArithmeticFunctions() throws Exception { - testQuery("SELECT w.name FROM app$Course c JOIN c.studentWaitlist w WHERE c.name = 'Calculus' AND INDEX(w) = 0"); - testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND SIZE(c.studentWaitlist) = 1"); - testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND ABS(c.time) = 10"); - testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND SQRT(c.time) = 10.5"); - testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND MOD(c.time, c.time1) = 2"); - } - - - @Test - @Ignore - public void testStringFunctions() throws Exception { - testQuery("SELECT x FROM app$Magazine x WHERE CONCAT(x.title, 's') = 'JDJs'"); - - testQuery("SELECT x FROM app$Magazine x WHERE SUBSTRING(x.title, 1, 1) = 'J'"); - testQuery("SELECT x FROM app$Magazine x WHERE SUBSTRING(x.title, 1) = 'J'"); - - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(TRAILING FROM x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(LEADING FROM x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(BOTH FROM x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(FROM x.title) = 'D'"); - - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(TRAILING 'J' FROM x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(LEADING 'J' FROM x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE TRIM(BOTH 'J' FROM x.title) = 'D'"); - - testQuery("SELECT x FROM app$Magazine x WHERE LOWER(x.title) = 'd'"); - testQuery("SELECT x FROM app$Magazine x WHERE UPPER(x.title) = 'D'"); - testQuery("SELECT x FROM app$Magazine x WHERE LENGTH(x.title) = 10"); - - testQuery("SELECT x FROM app$Magazine x WHERE LOCATE('A', x.title, 4) = 6"); - testQuery("SELECT x FROM app$Magazine x WHERE LOCATE('A', x.title) = 2"); - } - - @Test - public void testHaving() throws RecognitionException { - testQuery("SELECT c, COUNT(o) FROM app$Customer c JOIN c.orders o GROUP BY c HAVING COUNT(o) > 5"); - testQuery("SELECT c.status, AVG(c.filledOrderCount), COUNT(c) FROM app$Customer c GROUP BY c.status HAVING c.status IN (1, 2)"); - } - - @Test - public void testNullIfCoalesce() throws RecognitionException { - testQuery("SELECT NULLIF(emp.salary, 10) FROM app$Employee emp"); - testQuery("SELECT COALESCE(emp.salary, emp.salaryOld, 10) FROM app$Employee emp"); - } - - @Test - public void testAllAnySome() throws RecognitionException { - testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > ALL (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); - testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > ANY (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); - testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > SOME (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); - } - - @Test - @Ignore - public void testNewObjectInSelect() throws RecognitionException { - testQuery("SELECT NEW com.acme.example.CustomerDetails(c.id, c.status, o.count) FROM app$Customer c JOIN c.orders o WHERE o.count > 100"); - } - - @Test - @Ignore - public void testKeyValueColection() throws RecognitionException { - testQuery("SELECT v.location.street, KEY(i).title, VALUE(i) FROM app$VideoStore v JOIN v.videoInventory i WHERE v.location.zipcode = '94301' AND VALUE(i) > 0"); - } - - @Test - @Ignore - public void testLiterals() throws RecognitionException { - testQuery("SELECT e FROM app$Employee e WHERE e.name = 'Bob'"); - - testQuery("SELECT e FROM app$Employee e WHERE e.id = 1234"); - testQuery("SELECT e FROM app$Employee e WHERE e.id = -1234"); - - testQuery("SELECT e FROM app$Employee e WHERE e.id = 1234L"); - testQuery("SELECT e FROM app$Employee e WHERE e.id = -1234L"); - - testQuery("SELECT s FROM app$Stat s WHERE s.ratio > 3.14F"); - testQuery("SELECT s FROM app$Stat s WHERE s.ratio > -3.14F"); - - testQuery("SELECT s FROM app$Stat s WHERE s.ratio > 3.14e32D"); - testQuery("SELECT s FROM app$Stat s WHERE s.ratio > -3.14e32D"); - - testQuery("SELECT e FROM app$Employee e WHERE e.active = TRUE"); - - testQuery("SELECT e FROM app$Employee e WHERE e.startDate = {d'2012-01-03'}"); - testQuery("SELECT e FROM app$Employee e WHERE e.startTime = {t'09:00:00'}"); - testQuery("SELECT e FROM app$Employee e WHERE e.version = {ts'2012-01-03 09:00:00.000000001'}"); - - testQuery("UPDATE app$Employee e SET e.manager = NULL WHERE e.manager = :manager"); - } - - @Test - public void testAggregateFunctions() throws RecognitionException { - testQuery("SELECT AVG(o.quantity)/2 FROM app$Order o"); - //testQuery("SELECT AVG(o.quantity)/2.0 FROM app$Order o"); - testQuery("SELECT AVG(o.price) FROM app$Order o"); - testQuery("SELECT AVG(o.quantity * o.price) FROM app$Order o"); - testQuery("SELECT AVG(CASE WHEN o.orderType = 1 THEN o.price ELSE 0 END), AVG(CASE WHEN o.orderType = 2 THEN o.price ELSE 0 END) FROM app$Order o"); - } - - @Test - @Ignore - public void testSubQueries() throws RecognitionException { - testQuery("SELECT goodCustomer FROM app$Customer goodCustomer WHERE goodCustomer.balanceOwed < (SELECT AVG(c.balanceOwed)/2.0 FROM app$Customer c)"); - testQuery("SELECT c FROM app$Customer c WHERE (SELECT AVG(o.price) FROM c.orders o) > 100"); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.core.sys.jpql; + +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Lexer; +import com.haulmont.cuba.core.sys.jpql.antlr2.JPA2Parser; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.TokenStream; +import org.antlr.runtime.tree.CommonErrorNode; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeVisitor; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.List; + +public class Jpa2GrammarTest { + + @Test + public void testExtensionFunctions() throws Exception { + testQuery("select cast(e.number text) from app$MyEntity e where e.path like cast(:ds$myEntityDs.id text)"); + testQuery("select cast(e.number numeric(10,2)) from app$MyEntity e where e.number = cast(:ds$myEntityDs.id numeric(10,2))"); + testQuery("select cast(e.number varchar(100)) from app$MyEntity e where e.name = cast(:ds$myEntityDs.id varchar(100))"); + testQuery("select cast(e.number strange_type(1,2,3,4)) from app$MyEntity e where e.field1 = cast(:ds$myEntityDs.id strange_type(1,2,3,4))"); + + testQuery("select e from app$MyEntity e where e.name REGEXP '.*'"); + + testQuery("select extract(YEAR from e.createTs) from app$MyEntity e where extract(YEAR from e.createTs) > 2012"); + testQuery("select extract(MONTH from e.createTs) from app$MyEntity e where extract(MONTH from e.createTs) > 10"); + testQuery("select extract(DAY from e.createTs) from app$MyEntity e where extract(DAY from e.createTs) > 15"); + + testQuery("select extract(DAY FROM e.createTs), count(e.id) from app$MyEntity e group by extract(DAY FROM e.createTs)"); + } + + @Test + public void testGroupBy() throws Exception { + testQuery("select u.login " + + "from sec$User u " + + "where u.login = 'admin' " + + "group by u.login having u.version > 0" + + "order by u.login"); + } + + @Test + public void testGroupAlias() throws Exception { + testQuery("select group.name from sec$User u left join e.group group where u.login = 'admin'"); + } + + @Test + public void testOrderByCount() throws Exception { + testQuery("select instance.bookPublication.publisher.name, count(instance) " + + "from library$BookInstance instance " + + "group by instance.bookPublication.publisher.name order by count(instance) desc"); + + testQuery("select instance.bookPublication.publisher.name, instance.bookPublication.year, count(instance) " + + "from library$BookInstance instance " + + "group by instance.bookPublication.year, instance.bookPublication.publisher.name " + + "order by instance.bookPublication.year, instance.bookPublication.publisher.name"); + } + + @Test + @Ignore + public void testFunction() throws Exception { + testQuery("select u from sec$User u where function('DAYOFMONTH', u.createTs) = 1"); + testQuery("select u from sec$User u where function('hasRoles', u.createdBy, u.login)"); + } + + @Test + public void testParserParameters() throws Exception { + String query = "select sm from sys$SendingMessage sm " + + "where sm.status=:(?i)statusQueue or (sm.status = :statusSending and sm.updateTs<:time) " + + "order by sm.createTs"; + testQuery(query); + } + + @Test + public void testJoinOn() throws Exception { + String query = "select h " + + "from sec$Constraint u, sec$GroupHierarchy h join sec$Constraint c on c.group.id = h.parent.id " + + "where h.userGroup = :par"; + testQuery(query); + } + + @Test + public void testEscape() throws Exception { + String query = "c.name like :pattern escape '/'"; + CharStream cs = new AntlrNoCaseStringStream(query); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + JPA2Parser jpa2Parser = new JPA2Parser(tstream); + JPA2Parser.like_expression_return aReturn = jpa2Parser.like_expression(); + Assert.assertNotNull(aReturn); + + query = "c.name like :pattern escape '.'"; + cs = new AntlrNoCaseStringStream(query); + lexer = new JPA2Lexer(cs); + tstream = new CommonTokenStream(lexer); + jpa2Parser = new JPA2Parser(tstream); + aReturn = jpa2Parser.like_expression(); + Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); + } + + @Test + public void testTypeField() throws Exception { + String query = "where e.model.type = :component$filter.model_type89015"; + CharStream cs = new AntlrNoCaseStringStream(query); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + JPA2Parser jpa2Parser = new JPA2Parser(tstream); + JPA2Parser.where_clause_return aReturn = jpa2Parser.where_clause(); + Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); + } + + @Test + @Ignore + public void testMemberOf() throws Exception { + String query = "where p.owner.id = :userParam or (select u from tamsy$User u where u.id = :userParam) member of p.developers"; + CharStream cs = new AntlrNoCaseStringStream(query); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + JPA2Parser jpa2Parser = new JPA2Parser(tstream); + JPA2Parser.where_clause_return aReturn = jpa2Parser.where_clause(); + Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); + + testQuery("SELECT d FROM app$Department d WHERE (select e from app$Employee e where e.id = :eParam) MEMBER OF e.employees"); + testQuery("SELECT e FROM app$Employee e WHERE 'write code' MEMBER OF e.codes"); + testQuery("SELECT e FROM app$Employee e WHERE 'write code' NOT MEMBER OF e.codes"); + } + + @Test + public void testOrderBy() throws Exception { + testQuery("select c from ref$Contract c order by c.number"); + testQuery("select c from ref$Contract c order by c.number asc"); + testQuery("select c from ref$Contract c order by c.number desc"); + testQuery("select c from ref$Contract c order by c.order desc, c.number asc"); + testQuery("select c from ref$Contract c order by c.order asc, c.number desc"); + } + + @Test + public void testOrderByReservedWords() throws Exception { + testQuery("select c from ref$Contract c order by c.order"); + testQuery("select c from ref$Contract c order by c.from"); + testQuery("select c from ref$Contract c order by c.max"); + testQuery("select c from ref$Contract c order by c.min"); + testQuery("select c from ref$Contract c order by c.select"); + testQuery("select c from ref$Contract c order by c.count"); + testQuery("select c from ref$Contract c order by c.group"); + } + + @Test + public void testGroupByReservedWords() throws Exception { + testQuery("select c from ref$Contract c group by c.order"); + testQuery("select c from ref$Contract c group by c.from"); + testQuery("select c from ref$Contract c group by c.max"); + testQuery("select c from ref$Contract c group by c.min"); + testQuery("select c from ref$Contract c group by c.select"); + testQuery("select c from ref$Contract c group by c.count"); + testQuery("select c from ref$Contract c group by c.group"); + } + + @Test + public void testWhereReservedWords() throws Exception { + testQuery("select dB from taxi$DriverBan dB " + + "where dB.driver.id = :driverId " + + "and ((dB.till >= :date and (dB.from is null or dB.from <= :date)) or dB.bannedForever = true) " + + "and dB.type in (:account, :pin, :individual, :login)"); + + testQuery("select dB from taxi$DriverBan dB where dB.select is null"); + testQuery("select dB from taxi$DriverBan dB where dB.from is null"); + testQuery("select dB from taxi$DriverBan dB where dB.order is null"); + testQuery("select dB from taxi$DriverBan dB where dB.max is null"); + testQuery("select dB from taxi$DriverBan dB where dB.min is null"); + testQuery("select dB from taxi$DriverBan dB where dB.count is null"); + testQuery("select dB from taxi$DriverBan dB where dB.group is null"); + testQuery("select dB from taxi$DriverBan dB where dB.avg is null"); + testQuery("select dB from taxi$DriverBan dB where dB.size is null"); + } + + private void testQuery(String query) throws RecognitionException { + CharStream cs = new AntlrNoCaseStringStream(query); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + JPA2Parser jpa2Parser = new JPA2Parser(tstream); + JPA2Parser.ql_statement_return aReturn = jpa2Parser.ql_statement(); + Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); + } + + @Test + public void testIsNull() throws Exception { + String query = "select f from sec$Filter f left join f.user u " + + "where f.componentId = :component and (u.id = :userId or u is null) order by f.name"; + testQuery(query); + } + + @Test + public void testUpdate() throws Exception { + String query = "update sec$User u set u.group = :group where u.id = :userId"; + CharStream cs = new AntlrNoCaseStringStream(query); + JPA2Lexer lexer = new JPA2Lexer(cs); + TokenStream tstream = new CommonTokenStream(lexer); + JPA2Parser jpa2Parser = new JPA2Parser(tstream); + JPA2Parser.update_statement_return aReturn = jpa2Parser.update_statement(); + Assert.assertTrue(isValid((CommonTree) aReturn.getTree())); + } + + protected boolean isValid(CommonTree tree) { + TreeVisitor visitor = new TreeVisitor(); + ErrorNodesFinder errorNodesFinder = new ErrorNodesFinder(); + visitor.visit(tree, errorNodesFinder); + + List errorNodes = errorNodesFinder.getErrorNodes(); + if (!errorNodes.isEmpty()) { + System.err.println(errorNodes); + } + + return errorNodes.isEmpty(); + } + + @Test + public void testInClause() throws Exception { + testQuery("select u from sec$User u where u.login in ('a', 'b', 'c')"); + testQuery("select u from sec$User u where u.login in (1, 2, 3)"); + } + + @Test + @Ignore + public void testTreat() throws Exception { + testQuery("SELECT e FROM app$Employee e JOIN TREAT(e.projects AS app$LargeProject) p WHERE p.budget > 1000000"); + testQuery("SELECT e FROM app$Employee e JOIN e.projects p WHERE TREAT(p as app$LargeProject).budget > 1000000"); + } + + @Test + public void testInCollectionMember() throws Exception { + testQuery("SELECT e FROM app$Employee e, IN(e.projects) p WHERE p.budget > 1000000"); + } + + @Test + public void testIsNotEmpty() throws Exception { + testQuery("SELECT e FROM app$Employee e WHERE e.projects IS EMPTY"); + testQuery("SELECT e FROM app$Employee e WHERE e.projects IS NOT EMPTY"); + } + + @Test + @Ignore + public void testEntityTypeExpression() throws Exception { + testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN :empTypes"); + testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN (:empType1, :empType2)"); + testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) <> app$Exempt"); + testQuery("SELECT e FROM app$Employee e WHERE TYPE(e) IN (app$Exempt, app$Contractor)"); + } + + @Test + @Ignore + public void testCaseExpression() throws Exception { + testQuery("UPDATE app$Employee e SET e.salary = CASE e.rating WHEN 1 THEN e.salary * 1.1 WHEN 2 THEN e.salary * 1.05 ELSE e.salary * 1.01 END"); + testQuery("UPDATE app$Employee e SET e.salary = CASE WHEN e.rating = 1 THEN e.salary * 1.1 WHEN e.rating = 2 THEN e.salary * 1.05 ELSE e.salary * 1.01 END"); + testQuery("SELECT e.name, CASE TYPE(e) WHEN app$Exempt THEN 'Exempt' WHEN app$Contractor THEN 'Contractor' WHEN app$Intern THEN 'Intern' ELSE 'NonExempt' END FROM app$Employee e " + + "WHERE e.dept.name = 'Engineering'"); + testQuery("SELECT e.name, f.name, CONCAT(CASE WHEN f.annualMiles > 50000 THEN 'Platinum ' WHEN f.annualMiles > 25000 THEN 'Gold ' ELSE '' END, 'Frequent Flyer') " + + "FROM app$Employee e JOIN e.frequentFlierPlan f"); + } + + @Test + public void testArithmeticFunctions() throws Exception { + testQuery("SELECT w.name FROM app$Course c JOIN c.studentWaitlist w WHERE c.name = 'Calculus' AND INDEX(w) = 0"); + testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND SIZE(c.studentWaitlist) = 1"); + testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND ABS(c.time) = 10"); + testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND SQRT(c.time) = 10.5"); + testQuery("SELECT w.name FROM app$Course c WHERE c.name = 'Calculus' AND MOD(c.time, c.time1) = 2"); + } + + + @Test + @Ignore + public void testStringFunctions() throws Exception { + testQuery("SELECT x FROM app$Magazine x WHERE CONCAT(x.title, 's') = 'JDJs'"); + + testQuery("SELECT x FROM app$Magazine x WHERE SUBSTRING(x.title, 1, 1) = 'J'"); + testQuery("SELECT x FROM app$Magazine x WHERE SUBSTRING(x.title, 1) = 'J'"); + + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(TRAILING FROM x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(LEADING FROM x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(BOTH FROM x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(FROM x.title) = 'D'"); + + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(TRAILING 'J' FROM x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(LEADING 'J' FROM x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE TRIM(BOTH 'J' FROM x.title) = 'D'"); + + testQuery("SELECT x FROM app$Magazine x WHERE LOWER(x.title) = 'd'"); + testQuery("SELECT x FROM app$Magazine x WHERE UPPER(x.title) = 'D'"); + testQuery("SELECT x FROM app$Magazine x WHERE LENGTH(x.title) = 10"); + + testQuery("SELECT x FROM app$Magazine x WHERE LOCATE('A', x.title, 4) = 6"); + testQuery("SELECT x FROM app$Magazine x WHERE LOCATE('A', x.title) = 2"); + } + + @Test + public void testHaving() throws RecognitionException { + testQuery("SELECT c, COUNT(o) FROM app$Customer c JOIN c.orders o GROUP BY c HAVING COUNT(o) > 5"); + testQuery("SELECT c.status, AVG(c.filledOrderCount), COUNT(c) FROM app$Customer c GROUP BY c.status HAVING c.status IN (1, 2)"); + } + + @Test + public void testNullIfCoalesce() throws RecognitionException { + testQuery("SELECT NULLIF(emp.salary, 10) FROM app$Employee emp"); + testQuery("SELECT COALESCE(emp.salary, emp.salaryOld, 10) FROM app$Employee emp"); + } + + @Test + public void testAllAnySome() throws RecognitionException { + testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > ALL (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); + testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > ANY (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); + testQuery("SELECT emp FROM app$Employee emp WHERE emp.salary > SOME (SELECT m.salary FROM app$Manager m WHERE m.department = emp.department)"); + } + + @Test + @Ignore + public void testNewObjectInSelect() throws RecognitionException { + testQuery("SELECT NEW com.acme.example.CustomerDetails(c.id, c.status, o.count) FROM app$Customer c JOIN c.orders o WHERE o.count > 100"); + } + + @Test + @Ignore + public void testKeyValueColection() throws RecognitionException { + testQuery("SELECT v.location.street, KEY(i).title, VALUE(i) FROM app$VideoStore v JOIN v.videoInventory i WHERE v.location.zipcode = '94301' AND VALUE(i) > 0"); + } + + @Test + @Ignore + public void testLiterals() throws RecognitionException { + testQuery("SELECT e FROM app$Employee e WHERE e.name = 'Bob'"); + + testQuery("SELECT e FROM app$Employee e WHERE e.id = 1234"); + testQuery("SELECT e FROM app$Employee e WHERE e.id = -1234"); + + testQuery("SELECT e FROM app$Employee e WHERE e.id = 1234L"); + testQuery("SELECT e FROM app$Employee e WHERE e.id = -1234L"); + + testQuery("SELECT s FROM app$Stat s WHERE s.ratio > 3.14F"); + testQuery("SELECT s FROM app$Stat s WHERE s.ratio > -3.14F"); + + testQuery("SELECT s FROM app$Stat s WHERE s.ratio > 3.14e32D"); + testQuery("SELECT s FROM app$Stat s WHERE s.ratio > -3.14e32D"); + + testQuery("SELECT e FROM app$Employee e WHERE e.active = TRUE"); + + testQuery("SELECT e FROM app$Employee e WHERE e.startDate = {d'2012-01-03'}"); + testQuery("SELECT e FROM app$Employee e WHERE e.startTime = {t'09:00:00'}"); + testQuery("SELECT e FROM app$Employee e WHERE e.version = {ts'2012-01-03 09:00:00.000000001'}"); + + testQuery("UPDATE app$Employee e SET e.manager = NULL WHERE e.manager = :manager"); + } + + @Test + public void testAggregateFunctions() throws RecognitionException { + testQuery("SELECT AVG(o.quantity)/2 FROM app$Order o"); + //testQuery("SELECT AVG(o.quantity)/2.0 FROM app$Order o"); + testQuery("SELECT AVG(o.price) FROM app$Order o"); + testQuery("SELECT AVG(o.quantity * o.price) FROM app$Order o"); + testQuery("SELECT AVG(CASE WHEN o.orderType = 1 THEN o.price ELSE 0 END), AVG(CASE WHEN o.orderType = 2 THEN o.price ELSE 0 END) FROM app$Order o"); + } + + @Test + @Ignore + public void testSubQueries() throws RecognitionException { + testQuery("SELECT goodCustomer FROM app$Customer goodCustomer WHERE goodCustomer.balanceOwed < (SELECT AVG(c.balanceOwed)/2.0 FROM app$Customer c)"); + testQuery("SELECT c FROM app$Customer c WHERE (SELECT AVG(o.price) FROM c.orders o) > 100"); + } } \ No newline at end of file diff --git a/modules/global/test/com/haulmont/cuba/security/global/IpMatcherTest.java b/modules/global/test/com/haulmont/cuba/security/global/IpMatcherTest.java index 1854574fd7..dc73113c7a 100644 --- a/modules/global/test/com/haulmont/cuba/security/global/IpMatcherTest.java +++ b/modules/global/test/com/haulmont/cuba/security/global/IpMatcherTest.java @@ -1,72 +1,72 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.security.global; - -import junit.framework.TestCase; - -public class IpMatcherTest extends TestCase { - - public void testValid() { - boolean match; - IpMatcher matcher; - - matcher = new IpMatcher("192.168.1.1"); - match = matcher.match(null); - assertTrue(match); - match = matcher.match(""); - assertTrue(match); - match = matcher.match("127.0.0.1"); - assertTrue(match); - match = matcher.match("192.168.1.1"); - assertTrue(match); - match = matcher.match("192.168.1.2"); - assertFalse(match); - - matcher = new IpMatcher("192.168.1.*"); - match = matcher.match("192.168.1.2"); - assertTrue(match); - match = matcher.match("192.168.1.21"); - assertTrue(match); - match = matcher.match("192.168.2.21"); - assertFalse(match); - - matcher = new IpMatcher("192.168.1.*, 85.68.129.*"); - match = matcher.match("192.168.2.2"); - assertFalse(match); - match = matcher.match("85.68.129.10"); - assertTrue(match); - - matcher = new IpMatcher("192.168.*.*, 85.68.129.*"); - match = matcher.match("192.168.2.2"); - assertTrue(match); - match = matcher.match("192.10.2.2"); - assertFalse(match); - } - - public void testInvalid() { - boolean match; - IpMatcher matcher; - - matcher = new IpMatcher("192.168.*"); - match = matcher.match("192.10.1.1"); - assertTrue(match); - - matcher = new IpMatcher("192.168.1.*"); - match = matcher.match("192.10.1.1.767"); - assertTrue(match); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.security.global; + +import junit.framework.TestCase; + +public class IpMatcherTest extends TestCase { + + public void testValid() { + boolean match; + IpMatcher matcher; + + matcher = new IpMatcher("192.168.1.1"); + match = matcher.match(null); + assertTrue(match); + match = matcher.match(""); + assertTrue(match); + match = matcher.match("127.0.0.1"); + assertTrue(match); + match = matcher.match("192.168.1.1"); + assertTrue(match); + match = matcher.match("192.168.1.2"); + assertFalse(match); + + matcher = new IpMatcher("192.168.1.*"); + match = matcher.match("192.168.1.2"); + assertTrue(match); + match = matcher.match("192.168.1.21"); + assertTrue(match); + match = matcher.match("192.168.2.21"); + assertFalse(match); + + matcher = new IpMatcher("192.168.1.*, 85.68.129.*"); + match = matcher.match("192.168.2.2"); + assertFalse(match); + match = matcher.match("85.68.129.10"); + assertTrue(match); + + matcher = new IpMatcher("192.168.*.*, 85.68.129.*"); + match = matcher.match("192.168.2.2"); + assertTrue(match); + match = matcher.match("192.10.2.2"); + assertFalse(match); + } + + public void testInvalid() { + boolean match; + IpMatcher matcher; + + matcher = new IpMatcher("192.168.*"); + match = matcher.match("192.10.1.1"); + assertTrue(match); + + matcher = new IpMatcher("192.168.1.*"); + match = matcher.match("192.10.1.1.767"); + assertTrue(match); + } +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/AppConfig.java b/modules/gui/src/com/haulmont/cuba/gui/AppConfig.java index 497320590c..988897169b 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/AppConfig.java +++ b/modules/gui/src/com/haulmont/cuba/gui/AppConfig.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.ClientType; -import com.haulmont.cuba.core.global.Messages; -import com.haulmont.cuba.core.sys.AppContext; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.executors.BackgroundWorker; -import com.haulmont.cuba.gui.export.ExportDisplay; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; - -import javax.annotation.Nullable; - -/** - * GenericUI class holding common information about client application configuration, - * as well as some static helper methods to obtain infrastructure objects. - * - */ -public abstract class AppConfig { - - public static final String CLIENT_TYPE_PROP = "cuba.clientType"; - - /** - * Current client type. - *
Set up through the app property {@link #CLIENT_TYPE_PROP} on a client tier. - * @return current client type - */ - public static ClientType getClientType() { - return ClientType.valueOf(AppContext.getProperty(CLIENT_TYPE_PROP)); - } - - /** - * Main messages pack used by GenericUI components and application code. - *
Set up through app property {@code cuba.messagePack} depending on the client type and set of base projects. - * - *
This method is outdated but not deprecated because it is used in lots of places. Preferred method to - * obtain the main message pack is {@link com.haulmont.cuba.core.global.Messages#getMainMessagePack()}. - * - *
To obtain a message from the main message pack use {@link com.haulmont.cuba.core.global.Messages#getMainMessage(String)}. - */ - public static String getMessagesPack() { - Messages messages = AppBeans.get(Messages.NAME); - return messages.getMainMessagePack(); - } - - /** - * Create an ExportDisplay implementation. - * - * @param frame current frame. It is needed for desktop implementation to correctly show dialog inside of currently - * active main window. Can be null, but in this case a position of the dialog is not guaranteed. - * @return a new ExportDisplay instance - */ - public static ExportDisplay createExportDisplay(@Nullable Frame frame) { - ExportDisplay exportDisplay = AppBeans.get(ExportDisplay.NAME); - exportDisplay.setFrame(frame); - return exportDisplay; - } - - /** - * Client-specific BackgroundWorker - * @return BackgroundWorker instance - */ - public static BackgroundWorker getBackgroundWorker() { - return AppBeans.get(BackgroundWorker.NAME); - } - - /** - * Client-specific components factory - * @return ComponentsFactory instance - */ - public static ComponentsFactory getFactory() { - return AppBeans.get(ComponentsFactory.NAME); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.ClientType; +import com.haulmont.cuba.core.global.Messages; +import com.haulmont.cuba.core.sys.AppContext; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.executors.BackgroundWorker; +import com.haulmont.cuba.gui.export.ExportDisplay; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; + +import javax.annotation.Nullable; + +/** + * GenericUI class holding common information about client application configuration, + * as well as some static helper methods to obtain infrastructure objects. + * + */ +public abstract class AppConfig { + + public static final String CLIENT_TYPE_PROP = "cuba.clientType"; + + /** + * Current client type. + *
Set up through the app property {@link #CLIENT_TYPE_PROP} on a client tier. + * @return current client type + */ + public static ClientType getClientType() { + return ClientType.valueOf(AppContext.getProperty(CLIENT_TYPE_PROP)); + } + + /** + * Main messages pack used by GenericUI components and application code. + *
Set up through app property {@code cuba.messagePack} depending on the client type and set of base projects. + * + *
This method is outdated but not deprecated because it is used in lots of places. Preferred method to + * obtain the main message pack is {@link com.haulmont.cuba.core.global.Messages#getMainMessagePack()}. + * + *
To obtain a message from the main message pack use {@link com.haulmont.cuba.core.global.Messages#getMainMessage(String)}. + */ + public static String getMessagesPack() { + Messages messages = AppBeans.get(Messages.NAME); + return messages.getMainMessagePack(); + } + + /** + * Create an ExportDisplay implementation. + * + * @param frame current frame. It is needed for desktop implementation to correctly show dialog inside of currently + * active main window. Can be null, but in this case a position of the dialog is not guaranteed. + * @return a new ExportDisplay instance + */ + public static ExportDisplay createExportDisplay(@Nullable Frame frame) { + ExportDisplay exportDisplay = AppBeans.get(ExportDisplay.NAME); + exportDisplay.setFrame(frame); + return exportDisplay; + } + + /** + * Client-specific BackgroundWorker + * @return BackgroundWorker instance + */ + public static BackgroundWorker getBackgroundWorker() { + return AppBeans.get(BackgroundWorker.NAME); + } + + /** + * Client-specific components factory + * @return ComponentsFactory instance + */ + public static ComponentsFactory getFactory() { + return AppBeans.get(ComponentsFactory.NAME); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/ComponentFinder.java b/modules/gui/src/com/haulmont/cuba/gui/ComponentFinder.java index ddcd758a89..dd820df7ce 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/ComponentFinder.java +++ b/modules/gui/src/com/haulmont/cuba/gui/ComponentFinder.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.gui.components.Component; - -/** - * Visitor used in {@link com.haulmont.cuba.gui.ComponentsHelper#walkComponents(com.haulmont.cuba.gui.components.Component.Container, com.haulmont.cuba.gui.ComponentFinder)} - */ -public interface ComponentFinder { - - /** - * @param component visiting component - */ - boolean visit(Component component); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.gui.components.Component; + +/** + * Visitor used in {@link com.haulmont.cuba.gui.ComponentsHelper#walkComponents(com.haulmont.cuba.gui.components.Component.Container, com.haulmont.cuba.gui.ComponentFinder)} + */ +public interface ComponentFinder { + + /** + * @param component visiting component + */ + boolean visit(Component component); } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/ComponentPalette.java b/modules/gui/src/com/haulmont/cuba/gui/ComponentPalette.java index 37ec4dd994..6f890a9f64 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/ComponentPalette.java +++ b/modules/gui/src/com/haulmont/cuba/gui/ComponentPalette.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.xml.layout.ComponentLoader; - -import java.util.Map; - -/** - * Palette with UI components for screen descriptors - * - * @deprecated Use {@link com.haulmont.cuba.gui.xml.layout.ExternalUIComponentsSource} or app-components mechanism - */ -@Deprecated -public interface ComponentPalette { - - /** - * Get loaders for XML screen descriptors - * @return Loaders - */ - Map> getLoaders(); - - /** - * Get components for register in ComponentsFactory - * @return Components - */ - Map> getComponents(); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.xml.layout.ComponentLoader; + +import java.util.Map; + +/** + * Palette with UI components for screen descriptors + * + * @deprecated Use {@link com.haulmont.cuba.gui.xml.layout.ExternalUIComponentsSource} or app-components mechanism + */ +@Deprecated +public interface ComponentPalette { + + /** + * Get loaders for XML screen descriptors + * @return Loaders + */ + Map> getLoaders(); + + /** + * Get components for register in ComponentsFactory + * @return Components + */ + Map> getComponents(); } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/ComponentVisitor.java b/modules/gui/src/com/haulmont/cuba/gui/ComponentVisitor.java index d70b175e37..f25206c839 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/ComponentVisitor.java +++ b/modules/gui/src/com/haulmont/cuba/gui/ComponentVisitor.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.gui.components.Component; - -/** - * Visitor used in {@link ComponentsHelper#walkComponents(com.haulmont.cuba.gui.components.Component.Container, ComponentVisitor)} - */ -public interface ComponentVisitor { - - /** - * @param component visiting component - * @param name full path to the visiting component, including its own ID - */ - void visit(Component component, String name); -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.gui.components.Component; + +/** + * Visitor used in {@link ComponentsHelper#walkComponents(com.haulmont.cuba.gui.components.Component.Container, ComponentVisitor)} + */ +public interface ComponentVisitor { + + /** + * @param component visiting component + * @param name full path to the visiting component, including its own ID + */ + void visit(Component component, String name); +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/ComponentsHelper.java b/modules/gui/src/com/haulmont/cuba/gui/ComponentsHelper.java index a3447e0b7b..7dc232f462 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/ComponentsHelper.java +++ b/modules/gui/src/com/haulmont/cuba/gui/ComponentsHelper.java @@ -1,610 +1,610 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.chile.core.model.MetaProperty; -import com.haulmont.chile.core.model.MetaPropertyPath; -import com.haulmont.chile.core.model.MetadataObject; -import com.haulmont.cuba.core.entity.BaseGenericIdEntity; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.annotation.Lookup; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.MetadataTools; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.actions.*; -import com.haulmont.cuba.gui.components.mainwindow.AppWorkArea; -import com.haulmont.cuba.gui.data.Datasource; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.Collectors; - -import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.getFilteredAttributes; - -/** - * Utility class working with GenericUI components. - */ -public abstract class ComponentsHelper { - public static final String[] UNIT_SYMBOLS = { "px", "pt", "pc", "em", "ex", "mm", "cm", "in", "%" }; - - /** - * Returns the collection of components within the specified container and all of its children. - * - * @param container container to start from - * @return collection of components - */ - public static Collection getComponents(Component.Container container) { - // do not return LinkedHashSet, it uses much more memory than ArrayList - Collection res = new ArrayList<>(); - - fillChildComponents(container, res); - - if (res.isEmpty()) { - return Collections.emptyList(); - } - - return Collections.unmodifiableCollection(res); - } - - @Nullable - public static Component getWindowComponent( - Window window, String id) { - final String[] elements = ValuePathHelper.parse(id); - if (elements.length == 1) { - Component component = window.getRegisteredComponent(id); - if (component != null) - return component; - else - return window.getTimer(id); - } else { - Component innerComponent = window.getRegisteredComponent(elements[0]); - if (innerComponent instanceof FieldGroup) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - - FieldGroup fieldGroup = (FieldGroup) innerComponent; - FieldGroup.FieldConfig field = fieldGroup.getField(subPath); - - return field != null ? field.getComponent() : null; - } else if (innerComponent instanceof Component.Container) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((Component.Container) innerComponent).getComponent(subPath); - } else if (innerComponent instanceof Component.HasNamedComponents) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); - } - - return null; - } - } - - @Nullable - public static Component getFrameComponent(Frame frame, String id) { - final String[] elements = ValuePathHelper.parse(id); - if (elements.length == 1) { - Component component = frame.getRegisteredComponent(id); - if (component == null && frame.getFrame() != null && frame.getFrame() != frame) { - component = frame.getFrame().getComponent(id); - } - return component; - } else { - Component innerComponent = frame.getRegisteredComponent(elements[0]); - if (innerComponent instanceof FieldGroup) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - - FieldGroup fieldGroup = (FieldGroup) innerComponent; - FieldGroup.FieldConfig field = fieldGroup.getField(subPath); - - return field != null ? field.getComponent() : null; - } else if (innerComponent instanceof Component.Container) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((Component.Container) innerComponent).getComponent(subPath); - } else if (innerComponent instanceof Component.HasNamedComponents) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); - } - - return null; - } - } - - @Nullable - public static Component getComponent(Component.Container container, String id) { - final String[] elements = ValuePathHelper.parse(id); - if (elements.length == 1) { - final com.haulmont.cuba.gui.components.Component component = container.getOwnComponent(id); - - if (component == null) - return getComponentByIteration(container, id); - else - return component; - - } else { - Component innerComponent = container.getOwnComponent(elements[0]); - - if (innerComponent == null) { - return getComponentByIteration(container, id); - } else { - if (innerComponent instanceof FieldGroup) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - - FieldGroup fieldGroup = (FieldGroup) innerComponent; - FieldGroup.FieldConfig field = fieldGroup.getField(subPath); - - return field != null ? field.getComponent() : null; - } else if (innerComponent instanceof Component.Container) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((com.haulmont.cuba.gui.components.Component.Container) innerComponent).getComponent(subPath); - } else if (innerComponent instanceof Component.HasNamedComponents) { - final List subList = Arrays.asList(elements).subList(1, elements.length); - String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); - return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); - } - - return null; - } - } - } - - @Nullable - private static Component getComponentByIteration(Component.Container container, String id) { - for (Component component : container.getOwnComponents()) { - if (id.equals(component.getId())) { - return component; - } else if (component instanceof Component.Container) { - Component innerComponent = getComponentByIteration((Component.Container) component, id); - if (innerComponent != null) { - return innerComponent; - } - } - } - return null; - } - - private static void fillChildComponents(Component.Container container, Collection components) { - final Collection ownComponents = container.getOwnComponents(); - components.addAll(ownComponents); - - for (Component component : ownComponents) { - if (component instanceof Component.Container) { - fillChildComponents((Component.Container) component, components); - } - } - } - - /** - * Searches for a component by identifier, down by the hierarchy of frames. - * @param frame frame to start from - * @param id component identifier - * @return component instance or null if not found - */ - @Nullable - public static Component findComponent(Frame frame, String id) { - Component find = frame.getComponent(id); - if (find != null) { - return find; - } else { - for (Component c : frame.getComponents()) { - if (c instanceof Frame) { - Component comp = ((Frame) c).getComponent(id); - if (comp != null) { - return comp; - } else { - return findComponent((Frame) c, id); - } - } - } - } - return null; - } - - /** - * Visit all components below the specified container. - * @param container container to start from - * @param visitor visitor instance - */ - public static void walkComponents( - com.haulmont.cuba.gui.components.Component.Container container, - ComponentVisitor visitor - ) { - __walkComponents(container, visitor, ""); - } - - private static void __walkComponents( - com.haulmont.cuba.gui.components.Component.Container container, - ComponentVisitor visitor, - String path - ) { - for (com.haulmont.cuba.gui.components.Component component : container.getOwnComponents()) { - String id = component.getId(); - if (id == null && component instanceof Component.ActionOwner - && ((Component.ActionOwner) component).getAction() != null) { - id = ((Component.ActionOwner) component).getAction().getId(); - } - if (id == null) { - id = component.getClass().getSimpleName(); - } - visitor.visit(component, path + id); - - if (component instanceof com.haulmont.cuba.gui.components.Component.Container) { - String p = component instanceof Frame ? - path + id + "." : - path; - __walkComponents(((com.haulmont.cuba.gui.components.Component.Container) component), visitor, p); - } else if (component instanceof AppWorkArea) { - AppWorkArea workArea = (AppWorkArea) component; - if (workArea.getState() == AppWorkArea.State.INITIAL_LAYOUT) { - VBoxLayout initialLayout = workArea.getInitialLayout(); - - __walkComponents(initialLayout, visitor, path); - } - } - } - } - - /** - * Find first component by predicate - * - * @param container container to start from - * @param finder finder instance - */ - public static boolean walkComponents(com.haulmont.cuba.gui.components.Component.Container container, - ComponentFinder finder) { - return __walkComponents(container, finder); - } - - private static boolean __walkComponents(com.haulmont.cuba.gui.components.Component.Container container, - ComponentFinder finder) { - for (com.haulmont.cuba.gui.components.Component component : container.getOwnComponents()) { - if (finder.visit(component)) { - return true; - } - - if (component instanceof com.haulmont.cuba.gui.components.Component.Container) { - if (__walkComponents(((com.haulmont.cuba.gui.components.Component.Container) component), finder)) { - return true; - } - } - } - return false; - } - - public static String getFilterComponentPath(Filter filter) { - StringBuilder sb = new StringBuilder(filter.getId() != null ? filter.getId() : "filterWithoutId"); - Frame frame = filter.getFrame(); - while (frame != null) { - sb.insert(0, "."); - String s = frame.getId() != null ? frame.getId() : "frameWithoutId"; - if (s.contains(".")) { - s = "[" + s + "]"; - } - sb.insert(0, s); - if (frame instanceof Window) { - break; - } - frame = frame.getFrame(); - } - return sb.toString(); - } - - /** - * Get the topmost window for the specified component. - * @param component component instance - * @return topmost window in the hierarchy of frames for this component. - *
If the window has a controller class, an instance of the controller is returned. - *
Can be null only if the component wasn't properly initialized. - */ - @Nullable - public static Window getWindow(Component.BelongToFrame component) { - Frame frame = component.getFrame(); - while (frame != null) { - if (frame instanceof Window && frame.getFrame() == frame) { - Window window = (Window) frame; - return window instanceof WrappedWindow ? ((WrappedWindow) window).getWrapper() : window; - } - frame = frame.getFrame(); - } - return null; - } - - /** - * Get the topmost window for the specified component. - * @param component component instance - * @return topmost client specific window in the hierarchy of frames for this component. - * - *
Can be null only if the component wasn't properly initialized. - */ - @Nullable - public static Window getWindowImplementation(Component.BelongToFrame component) { - Frame frame = component.getFrame(); - while (frame != null) { - if (frame instanceof Window && frame.getFrame() == frame) { - Window window = (Window) frame; - return window instanceof Window.Wrapper ? ((Window.Wrapper) window).getWrappedWindow() : window; - } - frame = frame.getFrame(); - } - return null; - } - - public static Frame getFrameController(Frame frame) { - if (frame instanceof WrappedFrame) { - return ((WrappedFrame) frame).getWrapper(); - } else if (frame instanceof WrappedWindow) { - return ((WrappedWindow) frame).getWrapper(); - } else { - return frame; - } - } - - public static String getFullFrameId(Frame frame) { - LinkedList frameIds = new LinkedList<>(); - frameIds.addFirst(frame.getId()); - while (frame != null && !(frame instanceof Window) && frame != frame.getFrame()) { - frame = frame.getFrame(); - if (frame != null) - frameIds.addFirst(frame.getId()); - } - return StringUtils.join(frameIds, '.'); - } - - /** - * Searches for an action by name. - * @param actionName action name, can be a path to an action contained in some {@link Component.ActionsHolder} - * @param frame current frame - * @return action instance or null if there is no action with the specified name - * @throws IllegalStateException if the component denoted by the path doesn't exist or is not an ActionsHolder - */ - @Nullable - public static Action findAction(String actionName, Frame frame) { - String[] elements = ValuePathHelper.parse(actionName); - if (elements.length > 1) { - String id = elements[elements.length - 1]; - - String[] subPath = (String[]) ArrayUtils.subarray(elements, 0, elements.length - 1); - Component component = frame.getComponent(ValuePathHelper.format(subPath)); - if (component != null) { - if (component instanceof Component.ActionsHolder) { - return ((Component.ActionsHolder) component).getAction(id); - } else { - throw new IllegalArgumentException( - String.format("Component '%s' can't contain actions", Arrays.toString(subPath))); - } - } else { - throw new IllegalArgumentException( - String.format("Can't find component '%s'", Arrays.toString(subPath))); - } - } else if (elements.length == 1) { - String id = elements[0]; - return frame.getAction(id); - } else { - throw new IllegalArgumentException("Invalid action name: " + actionName); - } - } - - public static String getComponentPath(Component c) { - StringBuilder sb = new StringBuilder(c.getId() == null ? "" : c.getId()); - if (c instanceof Component.BelongToFrame) { - Frame frame = ((Component.BelongToFrame) c).getFrame(); - while (frame != null) { - sb.insert(0, "."); - String s = frame.getId(); - if (s.contains(".")) - s = "[" + s + "]"; - sb.insert(0, s); - if (frame instanceof Window) - break; - frame = frame.getFrame(); - } - } - return sb.toString(); - } - - public static String getComponentWidth(Component c) { - float width = c.getWidth(); - int widthUnit = c.getWidthUnits(); - return width + UNIT_SYMBOLS[widthUnit]; - } - - public static String getComponentHeigth(Component c) { - float height = c.getHeight(); - int heightUnit = c.getHeightUnits(); - return height + UNIT_SYMBOLS[heightUnit]; - } - - public static boolean hasFullWidth(Component c) { - return (int) c.getWidth() == 100 && c.getWidthUnits() == Component.UNITS_PERCENTAGE; - } - - public static boolean hasFullHeight(Component c) { - return (int) c.getHeight() == 100 && c.getHeightUnits() == Component.UNITS_PERCENTAGE; - } - - /** - * Creates standard Create, Edit and Remove actions for the component - * @param owner List, Table or Tree component - */ - public static void createActions(ListComponent owner) { - createActions(owner, EnumSet.of(ListActionType.CREATE, ListActionType.EDIT, ListActionType.REMOVE)); - } - - /** - * Creates standard actions for the component - * @param owner List, Table or Tree component - * @param actions set of actions to create - */ - public static void createActions(ListComponent owner, EnumSet actions) { - if (actions.contains(ListActionType.CREATE)) - owner.addAction(CreateAction.create(owner)); - - if (actions.contains(ListActionType.EDIT)) - owner.addAction(EditAction.create(owner)); - - if (actions.contains(ListActionType.REMOVE)) - owner.addAction(RemoveAction.create(owner)); - - if (actions.contains(ListActionType.REFRESH)) - owner.addAction(RefreshAction.create(owner)); - } - - /** - * Converts \n and \t symbols to HTML form. - * - * @param message HTML text - * @return HTML text or null if the input is null - */ - public static String preprocessHtmlMessage(String message) { - if (message == null) - return null; - String html = StringUtils.replace(message, "\n", "
"); - html = StringUtils.replace(html, "\t", "    "); - return html; - } - - /** - * Place component with error message to validation errors container. - * - * @param component validatable component - * @param e exception - * @param errors errors container - */ - public static void fillErrorMessages(Component.Validatable component, ValidationException e, - ValidationErrors errors) { - if (e instanceof ValidationException.HasRelatedComponent) { - errors.add(((ValidationException.HasRelatedComponent) e).getComponent(), e.getMessage()); - } else if (e instanceof CompositeValidationException) { - for (CompositeValidationException.ViolationCause cause : ((CompositeValidationException) e).getCauses()) { - errors.add((Component) component, cause.getMessage()); - } - } else if (e instanceof FieldGroup.FieldsValidationException) { - FieldGroup.FieldsValidationException fve = (FieldGroup.FieldsValidationException) e; - Map fields = fve.getProblemFields(); - for (Map.Entry problem : fields.entrySet()) { - ValidationException exception = problem.getValue(); - - fillErrorMessages(problem.getKey(), exception, errors); - } - } else { - errors.add((Component) component, e.getMessage()); - } - } - - /** - * @deprecated Use guava {@link Iterables#indexOf(Iterable, Predicate)} - */ - @Deprecated - public static int indexOf(Iterable components, Component component) { - Preconditions.checkNotNullArgument(components); - - Iterator iterator = components.iterator(); - for (int i = 0; iterator.hasNext(); i++) { - Component current = iterator.next(); - if (current == component) { - return i; - } - } - return -1; - } - - /** - * Set field's "required" flag to false if the value has been filtered by Row Level Security - * This is necessary to allow user to submit form with filtered attribute even if attribute is required - */ - public static void handleFilteredAttributes(Field component, Datasource datasource, MetaPropertyPath mpp) { - if (component.isRequired() - && datasource.getState() == Datasource.State.VALID - && datasource.getItem() != null - && mpp.getMetaProperty().getRange().isClass()) { - - Entity targetItem = datasource.getItem(); - - MetaProperty[] propertiesChain = mpp.getMetaProperties(); - if (propertiesChain.length > 1) { - List basePropertiesList = Arrays.stream(propertiesChain) - .limit(propertiesChain.length - 1) - .map(MetadataObject::getName) - .collect(Collectors.toList()); - - String basePropertyItem = StringUtils.join(basePropertiesList, '.'); - targetItem = datasource.getItem().getValueEx(basePropertyItem); - } - - if (targetItem instanceof BaseGenericIdEntity) { - String metaPropertyName = mpp.getMetaProperty().getName(); - Object value = targetItem.getValue(metaPropertyName); - - BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) targetItem; - String[] filteredAttributes = getFilteredAttributes(baseGenericIdEntity); - - if (value == null && filteredAttributes != null - && ArrayUtils.contains(filteredAttributes, metaPropertyName)) { - component.setRequired(false); - } - } - } - } - - public static int findActionById(List actionList, String actionId) { - int oldIndex = -1; - for (int i = 0; i < actionList.size(); i++) { - Action a = actionList.get(i); - if (Objects.equals(a.getId(), actionId)) { - oldIndex = i; - break; - } - } - return oldIndex; - } - - /** - * INTERNAL. - * Adds actions specified in {@link Lookup} annotation on entity attribute to the given PickerField. - */ - public static boolean createActionsByMetaAnnotations(PickerField pickerField) { - MetaPropertyPath mpp = pickerField.getMetaPropertyPath(); - if (mpp == null) - return false; - - String[] actions = (String[]) AppBeans.get(MetadataTools.class) - .getMetaAnnotationAttributes(mpp.getMetaProperty().getAnnotations(), Lookup.class) - .get("actions"); - if (actions != null && actions.length > 0) { - for (String actionId : actions) { - for (PickerField.ActionType actionType : PickerField.ActionType.values()) { - if (actionType.getId().equals(actionId.trim())) { - pickerField.addAction(actionType.createAction(pickerField)); - break; - } - } - } - return true; - } - return false; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.chile.core.model.MetaProperty; +import com.haulmont.chile.core.model.MetaPropertyPath; +import com.haulmont.chile.core.model.MetadataObject; +import com.haulmont.cuba.core.entity.BaseGenericIdEntity; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.annotation.Lookup; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.MetadataTools; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.actions.*; +import com.haulmont.cuba.gui.components.mainwindow.AppWorkArea; +import com.haulmont.cuba.gui.data.Datasource; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.stream.Collectors; + +import static com.haulmont.cuba.core.entity.BaseEntityInternalAccess.getFilteredAttributes; + +/** + * Utility class working with GenericUI components. + */ +public abstract class ComponentsHelper { + public static final String[] UNIT_SYMBOLS = { "px", "pt", "pc", "em", "ex", "mm", "cm", "in", "%" }; + + /** + * Returns the collection of components within the specified container and all of its children. + * + * @param container container to start from + * @return collection of components + */ + public static Collection getComponents(Component.Container container) { + // do not return LinkedHashSet, it uses much more memory than ArrayList + Collection res = new ArrayList<>(); + + fillChildComponents(container, res); + + if (res.isEmpty()) { + return Collections.emptyList(); + } + + return Collections.unmodifiableCollection(res); + } + + @Nullable + public static Component getWindowComponent( + Window window, String id) { + final String[] elements = ValuePathHelper.parse(id); + if (elements.length == 1) { + Component component = window.getRegisteredComponent(id); + if (component != null) + return component; + else + return window.getTimer(id); + } else { + Component innerComponent = window.getRegisteredComponent(elements[0]); + if (innerComponent instanceof FieldGroup) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + + FieldGroup fieldGroup = (FieldGroup) innerComponent; + FieldGroup.FieldConfig field = fieldGroup.getField(subPath); + + return field != null ? field.getComponent() : null; + } else if (innerComponent instanceof Component.Container) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((Component.Container) innerComponent).getComponent(subPath); + } else if (innerComponent instanceof Component.HasNamedComponents) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); + } + + return null; + } + } + + @Nullable + public static Component getFrameComponent(Frame frame, String id) { + final String[] elements = ValuePathHelper.parse(id); + if (elements.length == 1) { + Component component = frame.getRegisteredComponent(id); + if (component == null && frame.getFrame() != null && frame.getFrame() != frame) { + component = frame.getFrame().getComponent(id); + } + return component; + } else { + Component innerComponent = frame.getRegisteredComponent(elements[0]); + if (innerComponent instanceof FieldGroup) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + + FieldGroup fieldGroup = (FieldGroup) innerComponent; + FieldGroup.FieldConfig field = fieldGroup.getField(subPath); + + return field != null ? field.getComponent() : null; + } else if (innerComponent instanceof Component.Container) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((Component.Container) innerComponent).getComponent(subPath); + } else if (innerComponent instanceof Component.HasNamedComponents) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); + } + + return null; + } + } + + @Nullable + public static Component getComponent(Component.Container container, String id) { + final String[] elements = ValuePathHelper.parse(id); + if (elements.length == 1) { + final com.haulmont.cuba.gui.components.Component component = container.getOwnComponent(id); + + if (component == null) + return getComponentByIteration(container, id); + else + return component; + + } else { + Component innerComponent = container.getOwnComponent(elements[0]); + + if (innerComponent == null) { + return getComponentByIteration(container, id); + } else { + if (innerComponent instanceof FieldGroup) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + + FieldGroup fieldGroup = (FieldGroup) innerComponent; + FieldGroup.FieldConfig field = fieldGroup.getField(subPath); + + return field != null ? field.getComponent() : null; + } else if (innerComponent instanceof Component.Container) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((com.haulmont.cuba.gui.components.Component.Container) innerComponent).getComponent(subPath); + } else if (innerComponent instanceof Component.HasNamedComponents) { + final List subList = Arrays.asList(elements).subList(1, elements.length); + String subPath = ValuePathHelper.format(subList.toArray(new String[subList.size()])); + return ((Component.HasNamedComponents) innerComponent).getComponent(subPath); + } + + return null; + } + } + } + + @Nullable + private static Component getComponentByIteration(Component.Container container, String id) { + for (Component component : container.getOwnComponents()) { + if (id.equals(component.getId())) { + return component; + } else if (component instanceof Component.Container) { + Component innerComponent = getComponentByIteration((Component.Container) component, id); + if (innerComponent != null) { + return innerComponent; + } + } + } + return null; + } + + private static void fillChildComponents(Component.Container container, Collection components) { + final Collection ownComponents = container.getOwnComponents(); + components.addAll(ownComponents); + + for (Component component : ownComponents) { + if (component instanceof Component.Container) { + fillChildComponents((Component.Container) component, components); + } + } + } + + /** + * Searches for a component by identifier, down by the hierarchy of frames. + * @param frame frame to start from + * @param id component identifier + * @return component instance or null if not found + */ + @Nullable + public static Component findComponent(Frame frame, String id) { + Component find = frame.getComponent(id); + if (find != null) { + return find; + } else { + for (Component c : frame.getComponents()) { + if (c instanceof Frame) { + Component comp = ((Frame) c).getComponent(id); + if (comp != null) { + return comp; + } else { + return findComponent((Frame) c, id); + } + } + } + } + return null; + } + + /** + * Visit all components below the specified container. + * @param container container to start from + * @param visitor visitor instance + */ + public static void walkComponents( + com.haulmont.cuba.gui.components.Component.Container container, + ComponentVisitor visitor + ) { + __walkComponents(container, visitor, ""); + } + + private static void __walkComponents( + com.haulmont.cuba.gui.components.Component.Container container, + ComponentVisitor visitor, + String path + ) { + for (com.haulmont.cuba.gui.components.Component component : container.getOwnComponents()) { + String id = component.getId(); + if (id == null && component instanceof Component.ActionOwner + && ((Component.ActionOwner) component).getAction() != null) { + id = ((Component.ActionOwner) component).getAction().getId(); + } + if (id == null) { + id = component.getClass().getSimpleName(); + } + visitor.visit(component, path + id); + + if (component instanceof com.haulmont.cuba.gui.components.Component.Container) { + String p = component instanceof Frame ? + path + id + "." : + path; + __walkComponents(((com.haulmont.cuba.gui.components.Component.Container) component), visitor, p); + } else if (component instanceof AppWorkArea) { + AppWorkArea workArea = (AppWorkArea) component; + if (workArea.getState() == AppWorkArea.State.INITIAL_LAYOUT) { + VBoxLayout initialLayout = workArea.getInitialLayout(); + + __walkComponents(initialLayout, visitor, path); + } + } + } + } + + /** + * Find first component by predicate + * + * @param container container to start from + * @param finder finder instance + */ + public static boolean walkComponents(com.haulmont.cuba.gui.components.Component.Container container, + ComponentFinder finder) { + return __walkComponents(container, finder); + } + + private static boolean __walkComponents(com.haulmont.cuba.gui.components.Component.Container container, + ComponentFinder finder) { + for (com.haulmont.cuba.gui.components.Component component : container.getOwnComponents()) { + if (finder.visit(component)) { + return true; + } + + if (component instanceof com.haulmont.cuba.gui.components.Component.Container) { + if (__walkComponents(((com.haulmont.cuba.gui.components.Component.Container) component), finder)) { + return true; + } + } + } + return false; + } + + public static String getFilterComponentPath(Filter filter) { + StringBuilder sb = new StringBuilder(filter.getId() != null ? filter.getId() : "filterWithoutId"); + Frame frame = filter.getFrame(); + while (frame != null) { + sb.insert(0, "."); + String s = frame.getId() != null ? frame.getId() : "frameWithoutId"; + if (s.contains(".")) { + s = "[" + s + "]"; + } + sb.insert(0, s); + if (frame instanceof Window) { + break; + } + frame = frame.getFrame(); + } + return sb.toString(); + } + + /** + * Get the topmost window for the specified component. + * @param component component instance + * @return topmost window in the hierarchy of frames for this component. + *
If the window has a controller class, an instance of the controller is returned. + *
Can be null only if the component wasn't properly initialized. + */ + @Nullable + public static Window getWindow(Component.BelongToFrame component) { + Frame frame = component.getFrame(); + while (frame != null) { + if (frame instanceof Window && frame.getFrame() == frame) { + Window window = (Window) frame; + return window instanceof WrappedWindow ? ((WrappedWindow) window).getWrapper() : window; + } + frame = frame.getFrame(); + } + return null; + } + + /** + * Get the topmost window for the specified component. + * @param component component instance + * @return topmost client specific window in the hierarchy of frames for this component. + * + *
Can be null only if the component wasn't properly initialized. + */ + @Nullable + public static Window getWindowImplementation(Component.BelongToFrame component) { + Frame frame = component.getFrame(); + while (frame != null) { + if (frame instanceof Window && frame.getFrame() == frame) { + Window window = (Window) frame; + return window instanceof Window.Wrapper ? ((Window.Wrapper) window).getWrappedWindow() : window; + } + frame = frame.getFrame(); + } + return null; + } + + public static Frame getFrameController(Frame frame) { + if (frame instanceof WrappedFrame) { + return ((WrappedFrame) frame).getWrapper(); + } else if (frame instanceof WrappedWindow) { + return ((WrappedWindow) frame).getWrapper(); + } else { + return frame; + } + } + + public static String getFullFrameId(Frame frame) { + LinkedList frameIds = new LinkedList<>(); + frameIds.addFirst(frame.getId()); + while (frame != null && !(frame instanceof Window) && frame != frame.getFrame()) { + frame = frame.getFrame(); + if (frame != null) + frameIds.addFirst(frame.getId()); + } + return StringUtils.join(frameIds, '.'); + } + + /** + * Searches for an action by name. + * @param actionName action name, can be a path to an action contained in some {@link Component.ActionsHolder} + * @param frame current frame + * @return action instance or null if there is no action with the specified name + * @throws IllegalStateException if the component denoted by the path doesn't exist or is not an ActionsHolder + */ + @Nullable + public static Action findAction(String actionName, Frame frame) { + String[] elements = ValuePathHelper.parse(actionName); + if (elements.length > 1) { + String id = elements[elements.length - 1]; + + String[] subPath = (String[]) ArrayUtils.subarray(elements, 0, elements.length - 1); + Component component = frame.getComponent(ValuePathHelper.format(subPath)); + if (component != null) { + if (component instanceof Component.ActionsHolder) { + return ((Component.ActionsHolder) component).getAction(id); + } else { + throw new IllegalArgumentException( + String.format("Component '%s' can't contain actions", Arrays.toString(subPath))); + } + } else { + throw new IllegalArgumentException( + String.format("Can't find component '%s'", Arrays.toString(subPath))); + } + } else if (elements.length == 1) { + String id = elements[0]; + return frame.getAction(id); + } else { + throw new IllegalArgumentException("Invalid action name: " + actionName); + } + } + + public static String getComponentPath(Component c) { + StringBuilder sb = new StringBuilder(c.getId() == null ? "" : c.getId()); + if (c instanceof Component.BelongToFrame) { + Frame frame = ((Component.BelongToFrame) c).getFrame(); + while (frame != null) { + sb.insert(0, "."); + String s = frame.getId(); + if (s.contains(".")) + s = "[" + s + "]"; + sb.insert(0, s); + if (frame instanceof Window) + break; + frame = frame.getFrame(); + } + } + return sb.toString(); + } + + public static String getComponentWidth(Component c) { + float width = c.getWidth(); + int widthUnit = c.getWidthUnits(); + return width + UNIT_SYMBOLS[widthUnit]; + } + + public static String getComponentHeigth(Component c) { + float height = c.getHeight(); + int heightUnit = c.getHeightUnits(); + return height + UNIT_SYMBOLS[heightUnit]; + } + + public static boolean hasFullWidth(Component c) { + return (int) c.getWidth() == 100 && c.getWidthUnits() == Component.UNITS_PERCENTAGE; + } + + public static boolean hasFullHeight(Component c) { + return (int) c.getHeight() == 100 && c.getHeightUnits() == Component.UNITS_PERCENTAGE; + } + + /** + * Creates standard Create, Edit and Remove actions for the component + * @param owner List, Table or Tree component + */ + public static void createActions(ListComponent owner) { + createActions(owner, EnumSet.of(ListActionType.CREATE, ListActionType.EDIT, ListActionType.REMOVE)); + } + + /** + * Creates standard actions for the component + * @param owner List, Table or Tree component + * @param actions set of actions to create + */ + public static void createActions(ListComponent owner, EnumSet actions) { + if (actions.contains(ListActionType.CREATE)) + owner.addAction(CreateAction.create(owner)); + + if (actions.contains(ListActionType.EDIT)) + owner.addAction(EditAction.create(owner)); + + if (actions.contains(ListActionType.REMOVE)) + owner.addAction(RemoveAction.create(owner)); + + if (actions.contains(ListActionType.REFRESH)) + owner.addAction(RefreshAction.create(owner)); + } + + /** + * Converts \n and \t symbols to HTML form. + * + * @param message HTML text + * @return HTML text or null if the input is null + */ + public static String preprocessHtmlMessage(String message) { + if (message == null) + return null; + String html = StringUtils.replace(message, "\n", "
"); + html = StringUtils.replace(html, "\t", "    "); + return html; + } + + /** + * Place component with error message to validation errors container. + * + * @param component validatable component + * @param e exception + * @param errors errors container + */ + public static void fillErrorMessages(Component.Validatable component, ValidationException e, + ValidationErrors errors) { + if (e instanceof ValidationException.HasRelatedComponent) { + errors.add(((ValidationException.HasRelatedComponent) e).getComponent(), e.getMessage()); + } else if (e instanceof CompositeValidationException) { + for (CompositeValidationException.ViolationCause cause : ((CompositeValidationException) e).getCauses()) { + errors.add((Component) component, cause.getMessage()); + } + } else if (e instanceof FieldGroup.FieldsValidationException) { + FieldGroup.FieldsValidationException fve = (FieldGroup.FieldsValidationException) e; + Map fields = fve.getProblemFields(); + for (Map.Entry problem : fields.entrySet()) { + ValidationException exception = problem.getValue(); + + fillErrorMessages(problem.getKey(), exception, errors); + } + } else { + errors.add((Component) component, e.getMessage()); + } + } + + /** + * @deprecated Use guava {@link Iterables#indexOf(Iterable, Predicate)} + */ + @Deprecated + public static int indexOf(Iterable components, Component component) { + Preconditions.checkNotNullArgument(components); + + Iterator iterator = components.iterator(); + for (int i = 0; iterator.hasNext(); i++) { + Component current = iterator.next(); + if (current == component) { + return i; + } + } + return -1; + } + + /** + * Set field's "required" flag to false if the value has been filtered by Row Level Security + * This is necessary to allow user to submit form with filtered attribute even if attribute is required + */ + public static void handleFilteredAttributes(Field component, Datasource datasource, MetaPropertyPath mpp) { + if (component.isRequired() + && datasource.getState() == Datasource.State.VALID + && datasource.getItem() != null + && mpp.getMetaProperty().getRange().isClass()) { + + Entity targetItem = datasource.getItem(); + + MetaProperty[] propertiesChain = mpp.getMetaProperties(); + if (propertiesChain.length > 1) { + List basePropertiesList = Arrays.stream(propertiesChain) + .limit(propertiesChain.length - 1) + .map(MetadataObject::getName) + .collect(Collectors.toList()); + + String basePropertyItem = StringUtils.join(basePropertiesList, '.'); + targetItem = datasource.getItem().getValueEx(basePropertyItem); + } + + if (targetItem instanceof BaseGenericIdEntity) { + String metaPropertyName = mpp.getMetaProperty().getName(); + Object value = targetItem.getValue(metaPropertyName); + + BaseGenericIdEntity baseGenericIdEntity = (BaseGenericIdEntity) targetItem; + String[] filteredAttributes = getFilteredAttributes(baseGenericIdEntity); + + if (value == null && filteredAttributes != null + && ArrayUtils.contains(filteredAttributes, metaPropertyName)) { + component.setRequired(false); + } + } + } + } + + public static int findActionById(List actionList, String actionId) { + int oldIndex = -1; + for (int i = 0; i < actionList.size(); i++) { + Action a = actionList.get(i); + if (Objects.equals(a.getId(), actionId)) { + oldIndex = i; + break; + } + } + return oldIndex; + } + + /** + * INTERNAL. + * Adds actions specified in {@link Lookup} annotation on entity attribute to the given PickerField. + */ + public static boolean createActionsByMetaAnnotations(PickerField pickerField) { + MetaPropertyPath mpp = pickerField.getMetaPropertyPath(); + if (mpp == null) + return false; + + String[] actions = (String[]) AppBeans.get(MetadataTools.class) + .getMetaAnnotationAttributes(mpp.getMetaProperty().getAnnotations(), Lookup.class) + .get("actions"); + if (actions != null && actions.length > 0) { + for (String actionId : actions) { + for (PickerField.ActionType actionType : PickerField.ActionType.values()) { + if (actionType.getId().equals(actionId.trim())) { + pickerField.addAction(actionType.createAction(pickerField)); + break; + } + } + } + return true; + } + return false; + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/FrameContext.java b/modules/gui/src/com/haulmont/cuba/gui/FrameContext.java index 712faadbe8..47e2b926ff 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/FrameContext.java +++ b/modules/gui/src/com/haulmont/cuba/gui/FrameContext.java @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.data.ValueListener; - -import java.util.Map; - -/** - * Provides access to frame parameters and component values. - */ -public interface FrameContext { - - Frame getFrame(); - - /** - * For a window contains parameters passed to the window on opening. - *
For a frame, linked to the window in XML, contains owning window parameters. - *
For a frame, opened dynamically by {@code openFrame()} method contains parameters, passed to the method. - */ - Map getParams(); - - /** - * Value of an external parameters passed to the window on opening. - */ - T getParamValue(String param); - - /** - * Retrieves value of a component by complex name, dereferencing path to the component - * and possible drill down to the value - * @param property path to the value. Parsed by the following rules: - *
First split by dots taking into account square brackets, and looking for a component from left to right. - *
If a component not found, return null. - *
If a component found and it is a {@link com.haulmont.cuba.gui.components.Component.HasValue} - * or {@link com.haulmont.cuba.gui.components.ListComponent}, retrieve its value. - *
If the value is null, return it. - *
If there is nothing left in the path after the component name, return the value. - *
Else if the value is {@link com.haulmont.chile.core.model.Instance}, drill down to it and return the value - * of the property by remaining property path. - *
If the value is an {@link com.haulmont.chile.core.datatypes.impl.EnumClass} and remaining - * property path is "id", return EnumClass.getId() value. - */ - T getValue(String property); - - /** - * Set value of a component by its path in the window - * @param property path to the component (separated by dots, taking into account square brackets) - * @param value value to set - * @throws UnsupportedOperationException if the component not found or is not a {@link com.haulmont.cuba.gui.components.Component.HasValue} - */ - void setValue(String property, Object value); - - /** Add the value listener to the specified component */ - @Deprecated - void addValueListener(String componentName, ValueListener listener); - - /** Remove the value listener from the specified component */ - @Deprecated - void removeValueListener(String componentName, ValueListener listener); - - /** Add the value listener to the specified component */ - void addValueChangeListener(String componentName, Component.ValueChangeListener listener); - - /** Remove the value listener from the specified component */ - void removeValueChangeListener(String componentName, Component.ValueChangeListener listener); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.data.ValueListener; + +import java.util.Map; + +/** + * Provides access to frame parameters and component values. + */ +public interface FrameContext { + + Frame getFrame(); + + /** + * For a window contains parameters passed to the window on opening. + *
For a frame, linked to the window in XML, contains owning window parameters. + *
For a frame, opened dynamically by {@code openFrame()} method contains parameters, passed to the method. + */ + Map getParams(); + + /** + * Value of an external parameters passed to the window on opening. + */ + T getParamValue(String param); + + /** + * Retrieves value of a component by complex name, dereferencing path to the component + * and possible drill down to the value + * @param property path to the value. Parsed by the following rules: + *
First split by dots taking into account square brackets, and looking for a component from left to right. + *
If a component not found, return null. + *
If a component found and it is a {@link com.haulmont.cuba.gui.components.Component.HasValue} + * or {@link com.haulmont.cuba.gui.components.ListComponent}, retrieve its value. + *
If the value is null, return it. + *
If there is nothing left in the path after the component name, return the value. + *
Else if the value is {@link com.haulmont.chile.core.model.Instance}, drill down to it and return the value + * of the property by remaining property path. + *
If the value is an {@link com.haulmont.chile.core.datatypes.impl.EnumClass} and remaining + * property path is "id", return EnumClass.getId() value. + */ + T getValue(String property); + + /** + * Set value of a component by its path in the window + * @param property path to the component (separated by dots, taking into account square brackets) + * @param value value to set + * @throws UnsupportedOperationException if the component not found or is not a {@link com.haulmont.cuba.gui.components.Component.HasValue} + */ + void setValue(String property, Object value); + + /** Add the value listener to the specified component */ + @Deprecated + void addValueListener(String componentName, ValueListener listener); + + /** Remove the value listener from the specified component */ + @Deprecated + void removeValueListener(String componentName, ValueListener listener); + + /** Add the value listener to the specified component */ + void addValueChangeListener(String componentName, Component.ValueChangeListener listener); + + /** Remove the value listener from the specified component */ + void removeValueChangeListener(String componentName, Component.ValueChangeListener listener); } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/FrameContextImpl.java b/modules/gui/src/com/haulmont/cuba/gui/FrameContextImpl.java index 2848bcb4d2..6188badf30 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/FrameContextImpl.java +++ b/modules/gui/src/com/haulmont/cuba/gui/FrameContextImpl.java @@ -1,179 +1,179 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; -import com.haulmont.cuba.gui.data.ValueListener; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.chile.core.datatypes.impl.EnumClass; -import org.apache.commons.lang.ArrayUtils; - -import java.util.*; -import java.util.List; - -public class FrameContextImpl implements FrameContext { - - private final Frame frame; - private Map params; - - public FrameContextImpl(Frame window, Map params) { - this.frame = window; - this.params = params; - - frame.getComponents(); - } - - public Collection getParameterNames() { - List names = new ArrayList<>(); - for (String s : params.keySet()) { - names.add(s.substring("param$".length())); - } - return names; - } - - public T getParameterValue(String property) { - //noinspection unchecked - return (T) params.get("param$" + property); - } - - @Override - public Frame getFrame() { - return frame; - } - - @Override - public Map getParams() { - return params; - } - - @Override - public T getParamValue(String param) { - return (T) params.get(param); - } - - @Override - public T getValue(String property) { - final String[] elements = ValuePathHelper.parse(property); - String[] path = elements; - - Component component = frame.getComponent(property); - while (component == null && path.length > 1) { - // in case of property contains a drill-down part - path = (String[]) ArrayUtils.subarray(path, 0, path.length - 1); - component = frame.getComponent(ValuePathHelper.format(path)); - } - - if (component == null || component == frame - || ((component instanceof Component.Wrapper) && ((Component.Wrapper) component).getComponent() == frame)) - { - // if component not found or found the frame itself, try to search in parent frame - if (frame.getFrame() != null && frame.getFrame() != frame) - return frame.getFrame().getContext().getValue(property); - else - return null; - } - - final Object value = getValue(component); - if (value == null) - return null; - - if (path.length == elements.length) { - //noinspection unchecked - return (T) value; - } else { - final java.util.List propertyPath = Arrays.asList(elements).subList(path.length, elements.length); - final String[] properties = propertyPath.toArray(new String[propertyPath.size()]); - - if (value instanceof Instance) { - //noinspection RedundantTypeArguments - return InstanceUtils.getValueEx(((Instance) value), properties); - } else if (value instanceof EnumClass) { - if (properties.length == 1 && "id".equals(properties[0])) { - //noinspection unchecked - return (T) ((EnumClass) value).getId(); - } else { - throw new UnsupportedOperationException(String.format("Can't get property '%s' of enum %s", propertyPath, value)); - } - } else { - return null; - } - } - } - - protected T getValue(Component component) { - if (component instanceof Component.HasValue) { - //noinspection RedundantTypeArguments - return ((Component.HasValue) component).getValue(); - } else if (component instanceof ListComponent) { - ListComponent list = (ListComponent) component; - //noinspection unchecked - return list.isMultiSelect() ? (T)list.getSelected() : (T)list.getSingleSelected(); - } else { - return null; - } - } - - @Override - public void setValue(String property, Object value) { - final Component component = frame.getComponent(property); - if (component instanceof Component.HasValue) { - ((Component.HasValue) component).setValue(value); - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public void addValueListener(String componentName, ValueListener listener) { - addValueChangeListener(componentName, new ComponentValueListenerWrapper(listener)); - } - - @Override - public void removeValueListener(String componentName, ValueListener listener) { - removeValueChangeListener(componentName, new ComponentValueListenerWrapper(listener)); - } - - @Override - public void addValueChangeListener(String componentName, Component.ValueChangeListener listener) { - Component component = frame.getComponent(componentName); - if (component == null) - throw new RuntimeException("Component not found: " + componentName); - if (component instanceof Component.HasValue) { - ((Component.HasValue) component).addValueChangeListener(listener); - } else if (component instanceof ListComponent) { - throw new UnsupportedOperationException("List component is not supported yet"); - } else { - throw new RuntimeException("Unable to add listener to the component " + component); - } - } - - @Override - public void removeValueChangeListener(String componentName, Component.ValueChangeListener listener) { - Component component = frame.getComponent(componentName); - if (component == null) - throw new RuntimeException("Component not found: " + componentName); - if (component instanceof Component.HasValue) { - ((Component.HasValue) component).removeValueChangeListener(listener); - } else if (component instanceof ListComponent) { - throw new UnsupportedOperationException("List component is not supported yet"); - } else { - throw new RuntimeException("Unable to add listener to the component " + component); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.compatibility.ComponentValueListenerWrapper; +import com.haulmont.cuba.gui.data.ValueListener; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.chile.core.datatypes.impl.EnumClass; +import org.apache.commons.lang.ArrayUtils; + +import java.util.*; +import java.util.List; + +public class FrameContextImpl implements FrameContext { + + private final Frame frame; + private Map params; + + public FrameContextImpl(Frame window, Map params) { + this.frame = window; + this.params = params; + + frame.getComponents(); + } + + public Collection getParameterNames() { + List names = new ArrayList<>(); + for (String s : params.keySet()) { + names.add(s.substring("param$".length())); + } + return names; + } + + public T getParameterValue(String property) { + //noinspection unchecked + return (T) params.get("param$" + property); + } + + @Override + public Frame getFrame() { + return frame; + } + + @Override + public Map getParams() { + return params; + } + + @Override + public T getParamValue(String param) { + return (T) params.get(param); + } + + @Override + public T getValue(String property) { + final String[] elements = ValuePathHelper.parse(property); + String[] path = elements; + + Component component = frame.getComponent(property); + while (component == null && path.length > 1) { + // in case of property contains a drill-down part + path = (String[]) ArrayUtils.subarray(path, 0, path.length - 1); + component = frame.getComponent(ValuePathHelper.format(path)); + } + + if (component == null || component == frame + || ((component instanceof Component.Wrapper) && ((Component.Wrapper) component).getComponent() == frame)) + { + // if component not found or found the frame itself, try to search in parent frame + if (frame.getFrame() != null && frame.getFrame() != frame) + return frame.getFrame().getContext().getValue(property); + else + return null; + } + + final Object value = getValue(component); + if (value == null) + return null; + + if (path.length == elements.length) { + //noinspection unchecked + return (T) value; + } else { + final java.util.List propertyPath = Arrays.asList(elements).subList(path.length, elements.length); + final String[] properties = propertyPath.toArray(new String[propertyPath.size()]); + + if (value instanceof Instance) { + //noinspection RedundantTypeArguments + return InstanceUtils.getValueEx(((Instance) value), properties); + } else if (value instanceof EnumClass) { + if (properties.length == 1 && "id".equals(properties[0])) { + //noinspection unchecked + return (T) ((EnumClass) value).getId(); + } else { + throw new UnsupportedOperationException(String.format("Can't get property '%s' of enum %s", propertyPath, value)); + } + } else { + return null; + } + } + } + + protected T getValue(Component component) { + if (component instanceof Component.HasValue) { + //noinspection RedundantTypeArguments + return ((Component.HasValue) component).getValue(); + } else if (component instanceof ListComponent) { + ListComponent list = (ListComponent) component; + //noinspection unchecked + return list.isMultiSelect() ? (T)list.getSelected() : (T)list.getSingleSelected(); + } else { + return null; + } + } + + @Override + public void setValue(String property, Object value) { + final Component component = frame.getComponent(property); + if (component instanceof Component.HasValue) { + ((Component.HasValue) component).setValue(value); + } else { + throw new UnsupportedOperationException(); + } + } + + @Override + public void addValueListener(String componentName, ValueListener listener) { + addValueChangeListener(componentName, new ComponentValueListenerWrapper(listener)); + } + + @Override + public void removeValueListener(String componentName, ValueListener listener) { + removeValueChangeListener(componentName, new ComponentValueListenerWrapper(listener)); + } + + @Override + public void addValueChangeListener(String componentName, Component.ValueChangeListener listener) { + Component component = frame.getComponent(componentName); + if (component == null) + throw new RuntimeException("Component not found: " + componentName); + if (component instanceof Component.HasValue) { + ((Component.HasValue) component).addValueChangeListener(listener); + } else if (component instanceof ListComponent) { + throw new UnsupportedOperationException("List component is not supported yet"); + } else { + throw new RuntimeException("Unable to add listener to the component " + component); + } + } + + @Override + public void removeValueChangeListener(String componentName, Component.ValueChangeListener listener) { + Component component = frame.getComponent(componentName); + if (component == null) + throw new RuntimeException("Component not found: " + componentName); + if (component instanceof Component.HasValue) { + ((Component.HasValue) component).removeValueChangeListener(listener); + } else if (component instanceof ListComponent) { + throw new UnsupportedOperationException("List component is not supported yet"); + } else { + throw new RuntimeException("Unable to add listener to the component " + component); + } + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/GuiDevelopmentException.java b/modules/gui/src/com/haulmont/cuba/gui/GuiDevelopmentException.java index e4fe9374ea..360287d2c1 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/GuiDevelopmentException.java +++ b/modules/gui/src/com/haulmont/cuba/gui/GuiDevelopmentException.java @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.core.global.DevelopmentException; - -import java.util.Map; - -public class GuiDevelopmentException extends DevelopmentException { - - protected String frameId; - - public GuiDevelopmentException(String message, String frameId) { - super(message); - this.frameId = frameId; - } - - public GuiDevelopmentException(String message, String frameId, String paramKey, Object paramValue) { - super(message, paramKey, paramValue); - this.frameId = frameId; - } - - public GuiDevelopmentException(String message, String frameId, Map params) { - super(message, params); - this.frameId = frameId; - } - - public String getFrameId() { - return frameId; - } - - @Override - public String toString() { - return super.toString() + (frameId != null ? ", frameId=" + frameId : ""); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.core.global.DevelopmentException; + +import java.util.Map; + +public class GuiDevelopmentException extends DevelopmentException { + + protected String frameId; + + public GuiDevelopmentException(String message, String frameId) { + super(message); + this.frameId = frameId; + } + + public GuiDevelopmentException(String message, String frameId, String paramKey, Object paramValue) { + super(message, paramKey, paramValue); + this.frameId = frameId; + } + + public GuiDevelopmentException(String message, String frameId, Map params) { + super(message, params); + this.frameId = frameId; + } + + public String getFrameId() { + return frameId; + } + + @Override + public String toString() { + return super.toString() + (frameId != null ? ", frameId=" + frameId : ""); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/NoSuchScreenException.java b/modules/gui/src/com/haulmont/cuba/gui/NoSuchScreenException.java index 7e79068b7e..6131b30390 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/NoSuchScreenException.java +++ b/modules/gui/src/com/haulmont/cuba/gui/NoSuchScreenException.java @@ -1,38 +1,38 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -/** - * Raised on attempt to open an unknown screen. - * - * - */ -public class NoSuchScreenException extends RuntimeException { - - private static final long serialVersionUID = -3751833162235475862L; - - private final String screenId; - - public NoSuchScreenException(String screenId) { - super("Screen '" + screenId + "' is not defined"); - this.screenId = screenId; - } - - public String getScreenId() { - return screenId; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +/** + * Raised on attempt to open an unknown screen. + * + * + */ +public class NoSuchScreenException extends RuntimeException { + + private static final long serialVersionUID = -3751833162235475862L; + + private final String screenId; + + public NoSuchScreenException(String screenId) { + super("Screen '" + screenId + "' is not defined"); + this.screenId = screenId; + } + + public String getScreenId() { + return screenId; + } +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/ScreenHistorySupport.java b/modules/gui/src/com/haulmont/cuba/gui/ScreenHistorySupport.java index 1c8431d98c..589c11089c 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/ScreenHistorySupport.java +++ b/modules/gui/src/com/haulmont/cuba/gui/ScreenHistorySupport.java @@ -1,143 +1,143 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import com.haulmont.bali.util.URLEncodeUtils; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.client.ClientConfig; -import com.haulmont.cuba.core.app.DataService; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.gui.config.WindowConfig; -import com.haulmont.cuba.security.entity.EntityOp; -import com.haulmont.cuba.security.entity.ScreenHistoryEntity; -import org.apache.commons.lang.StringUtils; - -import java.util.*; - -/** - * Class that encapsulates screen opening history functionality. It is used by WindowManager and should not be invoked - * from application code. - */ -public class ScreenHistorySupport { - - protected Set screenIds = new HashSet<>(); - - protected Metadata metadata; - protected Messages messages; - protected Configuration configuration; - - public ScreenHistorySupport() { - metadata = AppBeans.get(Metadata.NAME); - messages = AppBeans.get(Messages.NAME); - configuration = AppBeans.get(Configuration.NAME); - - String property = configuration.getConfig(ClientConfig.class).getScreenIdsToSaveHistory(); - if (StringUtils.isNotBlank(property)) { - screenIds.addAll(Arrays.asList(StringUtils.split(property, ','))); - } - - WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); - for (MetaClass metaClass : metadata.getTools().getAllPersistentMetaClasses()) { - Map attributes = metadata.getTools().getMetaAnnotationAttributes(metaClass.getAnnotations(), - TrackEditScreenHistory.class); - if (Boolean.TRUE.equals(attributes.get("value"))) { - screenIds.add(windowConfig.getEditorScreenId(metaClass)); - } - } - } - - public void saveScreenHistory(Window window, WindowManager.OpenMode openMode) { - Security security = AppBeans.get(Security.NAME); - if (security.isEntityOpPermitted(ScreenHistoryEntity.class, EntityOp.CREATE) - && window.getFrame() != null - && (window.getFrame() instanceof Window.Editor) - && openMode != WindowManager.OpenMode.DIALOG - && (screenIds == null || screenIds.contains(window.getId()))) - { - String caption = window.getCaption(); - UUID entityId = null; - Frame frame = window.getFrame(); - Entity entity = null; - if (frame instanceof Window.Editor) { - entity = ((Window.Editor) frame).getItem(); - if (entity != null) { - if (PersistenceHelper.isNew(entity)) { - return; - } - if (StringUtils.isBlank(caption)) - caption = messages.getTools().getEntityCaption(entity.getMetaClass()) + " " + entity.getInstanceName(); - entityId = (UUID) entity.getId(); - } - } - ScreenHistoryEntity screenHistoryEntity = metadata.create(ScreenHistoryEntity.class); - screenHistoryEntity.setCaption(StringUtils.abbreviate(caption, 255)); - screenHistoryEntity.setUrl(makeLink(window)); - screenHistoryEntity.setEntityId(entityId); - addAdditionalFields(screenHistoryEntity, entity); - - CommitContext cc = new CommitContext(Collections.singleton(screenHistoryEntity)); - DataService dataService = AppBeans.get(DataService.NAME); - dataService.commit(cc); - } - } - - protected void addAdditionalFields(ScreenHistoryEntity screenHistoryEntity, Entity entity) { - - } - - protected String makeLink(Window window) { - Entity entity = null; - if (window.getFrame() instanceof Window.Editor) - entity = ((Window.Editor) window.getFrame()).getItem(); - String url = configuration.getConfig(GlobalConfig.class).getWebAppUrl() + "/open?" + - "screen=" + window.getFrame().getId(); - if (entity != null) { - String item = metadata.getSession().getClassNN(entity.getClass()).getName() + "-" + entity.getId(); - url += "&" + "item=" + item + "&" + "params=item:" + item; - } - Map params = getWindowParams(window); - StringBuilder sb = new StringBuilder(); - if (params != null) { - for (Map.Entry param : params.entrySet()) { - Object value = param.getValue(); - if (value instanceof String /*|| value instanceof Integer || value instanceof Double*/ - || value instanceof Boolean) { - sb.append(",").append(param.getKey()).append(":") - .append(URLEncodeUtils.encodeUtf8(value.toString())); - } - } - } - if (sb.length() > 0) { - if (entity != null) { - url += sb.toString(); - } else { - url += "¶ms=" + sb.deleteCharAt(0).toString(); - } - } - - return url; - } - - protected Map getWindowParams(Window window) { - return window.getContext().getParams(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import com.haulmont.bali.util.URLEncodeUtils; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.client.ClientConfig; +import com.haulmont.cuba.core.app.DataService; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.annotation.TrackEditScreenHistory; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.gui.config.WindowConfig; +import com.haulmont.cuba.security.entity.EntityOp; +import com.haulmont.cuba.security.entity.ScreenHistoryEntity; +import org.apache.commons.lang.StringUtils; + +import java.util.*; + +/** + * Class that encapsulates screen opening history functionality. It is used by WindowManager and should not be invoked + * from application code. + */ +public class ScreenHistorySupport { + + protected Set screenIds = new HashSet<>(); + + protected Metadata metadata; + protected Messages messages; + protected Configuration configuration; + + public ScreenHistorySupport() { + metadata = AppBeans.get(Metadata.NAME); + messages = AppBeans.get(Messages.NAME); + configuration = AppBeans.get(Configuration.NAME); + + String property = configuration.getConfig(ClientConfig.class).getScreenIdsToSaveHistory(); + if (StringUtils.isNotBlank(property)) { + screenIds.addAll(Arrays.asList(StringUtils.split(property, ','))); + } + + WindowConfig windowConfig = AppBeans.get(WindowConfig.NAME); + for (MetaClass metaClass : metadata.getTools().getAllPersistentMetaClasses()) { + Map attributes = metadata.getTools().getMetaAnnotationAttributes(metaClass.getAnnotations(), + TrackEditScreenHistory.class); + if (Boolean.TRUE.equals(attributes.get("value"))) { + screenIds.add(windowConfig.getEditorScreenId(metaClass)); + } + } + } + + public void saveScreenHistory(Window window, WindowManager.OpenMode openMode) { + Security security = AppBeans.get(Security.NAME); + if (security.isEntityOpPermitted(ScreenHistoryEntity.class, EntityOp.CREATE) + && window.getFrame() != null + && (window.getFrame() instanceof Window.Editor) + && openMode != WindowManager.OpenMode.DIALOG + && (screenIds == null || screenIds.contains(window.getId()))) + { + String caption = window.getCaption(); + UUID entityId = null; + Frame frame = window.getFrame(); + Entity entity = null; + if (frame instanceof Window.Editor) { + entity = ((Window.Editor) frame).getItem(); + if (entity != null) { + if (PersistenceHelper.isNew(entity)) { + return; + } + if (StringUtils.isBlank(caption)) + caption = messages.getTools().getEntityCaption(entity.getMetaClass()) + " " + entity.getInstanceName(); + entityId = (UUID) entity.getId(); + } + } + ScreenHistoryEntity screenHistoryEntity = metadata.create(ScreenHistoryEntity.class); + screenHistoryEntity.setCaption(StringUtils.abbreviate(caption, 255)); + screenHistoryEntity.setUrl(makeLink(window)); + screenHistoryEntity.setEntityId(entityId); + addAdditionalFields(screenHistoryEntity, entity); + + CommitContext cc = new CommitContext(Collections.singleton(screenHistoryEntity)); + DataService dataService = AppBeans.get(DataService.NAME); + dataService.commit(cc); + } + } + + protected void addAdditionalFields(ScreenHistoryEntity screenHistoryEntity, Entity entity) { + + } + + protected String makeLink(Window window) { + Entity entity = null; + if (window.getFrame() instanceof Window.Editor) + entity = ((Window.Editor) window.getFrame()).getItem(); + String url = configuration.getConfig(GlobalConfig.class).getWebAppUrl() + "/open?" + + "screen=" + window.getFrame().getId(); + if (entity != null) { + String item = metadata.getSession().getClassNN(entity.getClass()).getName() + "-" + entity.getId(); + url += "&" + "item=" + item + "&" + "params=item:" + item; + } + Map params = getWindowParams(window); + StringBuilder sb = new StringBuilder(); + if (params != null) { + for (Map.Entry param : params.entrySet()) { + Object value = param.getValue(); + if (value instanceof String /*|| value instanceof Integer || value instanceof Double*/ + || value instanceof Boolean) { + sb.append(",").append(param.getKey()).append(":") + .append(URLEncodeUtils.encodeUtf8(value.toString())); + } + } + } + if (sb.length() > 0) { + if (entity != null) { + url += sb.toString(); + } else { + url += "¶ms=" + sb.deleteCharAt(0).toString(); + } + } + + return url; + } + + protected Map getWindowParams(Window window) { + return window.getContext().getParams(); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/WindowCreationHelper.java b/modules/gui/src/com/haulmont/cuba/gui/WindowCreationHelper.java index 54ca2b021e..83b41f51a3 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/WindowCreationHelper.java +++ b/modules/gui/src/com/haulmont/cuba/gui/WindowCreationHelper.java @@ -1,192 +1,192 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; -import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; -import com.haulmont.cuba.gui.components.ActionsPermissions; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Frame; -import com.haulmont.cuba.gui.components.Window; -import com.haulmont.cuba.security.entity.Permission; -import com.haulmont.cuba.security.entity.PermissionType; -import com.haulmont.cuba.security.global.UserSession; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Utility class used by the framework when it creates frames and windows. Not for use in application code. - * - */ -public final class WindowCreationHelper { - - private static final Pattern INNER_COMPONENT_PATTERN = Pattern.compile("(.+?)\\[(.+?)\\]"); - private static final Pattern COMPONENT_ACTION_PATTERN = Pattern.compile("(.+?)<(.+?)>"); - - private static final Logger log = LoggerFactory.getLogger(WindowCreationHelper.class); - - private WindowCreationHelper() { - } - - /** - * Apply UI permissions to a frame. - * - * @param container frame - */ - public static void applyUiPermissions(Frame container) { - Window window = container instanceof Window ? (Window) container : ComponentsHelper.getWindow(container); - if (window == null) { - log.warn(String.format("Unable to find window for container %s with id '%s'", container.getClass(), container.getId())); - return; - } - - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - UserSession userSession = sessionSource.getUserSession(); - - String screenId = window.getId(); - Map uiPermissions = userSession.getPermissionsByType(PermissionType.UI); - for (Map.Entry permissionEntry : uiPermissions.entrySet()) { - String target = permissionEntry.getKey(); - String targetComponentId = getTargetComponentId(target, screenId); - if (targetComponentId != null) { - if (targetComponentId.contains("[")) { - applyCompositeComponentPermission(window, screenId, permissionEntry.getValue(), targetComponentId); - } else if (targetComponentId.contains(">")) { - applyComponentActionPermission(window, screenId, permissionEntry.getValue(), targetComponentId); - } else { - applyComponentPermission(window, screenId, permissionEntry.getValue(), targetComponentId); - } - } - } - } - - @Nullable - private static String getTargetComponentId(String target, String screenId) { - if (StringUtils.isNotBlank(target)) { - int delimeterIndex = target.indexOf(Permission.TARGET_PATH_DELIMETER); - if (delimeterIndex >= 0) { - String targetScreenId = target.substring(0, delimeterIndex); - if (StringUtils.equals(screenId, targetScreenId)) { - return target.substring(delimeterIndex + 1); - } - } - } - return null; - } - - private static void applyComponentPermission(Window window, String screenId, - Integer permissionValue, String targetComponentId) { - Component component = window.getComponent(targetComponentId); - - if (component != null) { - if (permissionValue == UiPermissionValue.HIDE.getValue()) { - component.setVisible(false); - } else if (permissionValue == UiPermissionValue.READ_ONLY.getValue()) { - if (component instanceof Component.Editable) { - ((Component.Editable) component).setEditable(false); - } else { - component.setEnabled(false); - } - } - } else { - log.info(String.format("Couldn't find component %s in window %s", targetComponentId, screenId)); - } - } - - private static void applyCompositeComponentPermission(Window window, String screenId, - Integer permissionValue, String componentId) { - final Matcher matcher = INNER_COMPONENT_PATTERN.matcher(componentId); - if (matcher.find()) { - final String customComponentId = matcher.group(1); - final String subComponentId = matcher.group(2); - final Component compositeComponent = window.getComponent(customComponentId); - - if (compositeComponent != null) { - if (compositeComponent instanceof Component.UiPermissionAware) { - Component.UiPermissionAware uiPermissionAwareComponent = (Component.UiPermissionAware) compositeComponent; - UiPermissionValue uiPermissionValue = UiPermissionValue.fromId(permissionValue); - - UiPermissionDescriptor permissionDescriptor; - if (subComponentId.contains("<")) { - final Matcher actionMatcher = COMPONENT_ACTION_PATTERN.matcher(subComponentId); - if (actionMatcher.find()) { - final String actionHolderComponentId = actionMatcher.group(1); - final String actionId = actionMatcher.group(2); - - permissionDescriptor = new UiPermissionDescriptor(uiPermissionValue, screenId, - actionHolderComponentId, actionId); - } else { - log.warn(String.format("Incorrect permission definition for component %s in window %s", subComponentId, screenId)); - return; - } - } else { - permissionDescriptor = new UiPermissionDescriptor(uiPermissionValue, screenId, subComponentId); - } - - uiPermissionAwareComponent.applyPermission(permissionDescriptor); - } - } else { - log.info(String.format("Couldn't find component %s in window %s", componentId, screenId)); - } - } - } - - /** - * Process permissions for actions in action holder - * - * @param window Window - * @param screenId Screen Id - * @param permissionValue Permission value - * @param componentId Component Id - */ - private static void applyComponentActionPermission(Window window, String screenId, - Integer permissionValue, String componentId) { - final Matcher matcher = COMPONENT_ACTION_PATTERN.matcher(componentId); - if (matcher.find()) { - final String customComponentId = matcher.group(1); - final String actionId = matcher.group(2); - final Component actionHolderComponent = window.getComponent(customComponentId); - if (actionHolderComponent != null) { - if (actionHolderComponent instanceof Component.SecuredActionsHolder) { - ActionsPermissions permissions = - ((Component.SecuredActionsHolder) actionHolderComponent).getActionsPermissions(); - if (permissionValue == UiPermissionValue.HIDE.getValue()) { - permissions.addHiddenActionPermission(actionId); - } else if (permissionValue == UiPermissionValue.READ_ONLY.getValue()) { - permissions.addDisabledActionPermission(actionId); - } - } else { - log.warn(String.format("Couldn't apply permission on action %s for component %s in window %s", - actionId, customComponentId, screenId)); - } - } else { - log.info(String.format("Couldn't find component %s in window %s", componentId, screenId)); - } - } else { - log.warn(String.format("Incorrect permission definition for component %s in window %s", componentId, screenId)); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionDescriptor; +import com.haulmont.cuba.gui.app.security.role.edit.UiPermissionValue; +import com.haulmont.cuba.gui.components.ActionsPermissions; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Frame; +import com.haulmont.cuba.gui.components.Window; +import com.haulmont.cuba.security.entity.Permission; +import com.haulmont.cuba.security.entity.PermissionType; +import com.haulmont.cuba.security.global.UserSession; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class used by the framework when it creates frames and windows. Not for use in application code. + * + */ +public final class WindowCreationHelper { + + private static final Pattern INNER_COMPONENT_PATTERN = Pattern.compile("(.+?)\\[(.+?)\\]"); + private static final Pattern COMPONENT_ACTION_PATTERN = Pattern.compile("(.+?)<(.+?)>"); + + private static final Logger log = LoggerFactory.getLogger(WindowCreationHelper.class); + + private WindowCreationHelper() { + } + + /** + * Apply UI permissions to a frame. + * + * @param container frame + */ + public static void applyUiPermissions(Frame container) { + Window window = container instanceof Window ? (Window) container : ComponentsHelper.getWindow(container); + if (window == null) { + log.warn(String.format("Unable to find window for container %s with id '%s'", container.getClass(), container.getId())); + return; + } + + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + UserSession userSession = sessionSource.getUserSession(); + + String screenId = window.getId(); + Map uiPermissions = userSession.getPermissionsByType(PermissionType.UI); + for (Map.Entry permissionEntry : uiPermissions.entrySet()) { + String target = permissionEntry.getKey(); + String targetComponentId = getTargetComponentId(target, screenId); + if (targetComponentId != null) { + if (targetComponentId.contains("[")) { + applyCompositeComponentPermission(window, screenId, permissionEntry.getValue(), targetComponentId); + } else if (targetComponentId.contains(">")) { + applyComponentActionPermission(window, screenId, permissionEntry.getValue(), targetComponentId); + } else { + applyComponentPermission(window, screenId, permissionEntry.getValue(), targetComponentId); + } + } + } + } + + @Nullable + private static String getTargetComponentId(String target, String screenId) { + if (StringUtils.isNotBlank(target)) { + int delimeterIndex = target.indexOf(Permission.TARGET_PATH_DELIMETER); + if (delimeterIndex >= 0) { + String targetScreenId = target.substring(0, delimeterIndex); + if (StringUtils.equals(screenId, targetScreenId)) { + return target.substring(delimeterIndex + 1); + } + } + } + return null; + } + + private static void applyComponentPermission(Window window, String screenId, + Integer permissionValue, String targetComponentId) { + Component component = window.getComponent(targetComponentId); + + if (component != null) { + if (permissionValue == UiPermissionValue.HIDE.getValue()) { + component.setVisible(false); + } else if (permissionValue == UiPermissionValue.READ_ONLY.getValue()) { + if (component instanceof Component.Editable) { + ((Component.Editable) component).setEditable(false); + } else { + component.setEnabled(false); + } + } + } else { + log.info(String.format("Couldn't find component %s in window %s", targetComponentId, screenId)); + } + } + + private static void applyCompositeComponentPermission(Window window, String screenId, + Integer permissionValue, String componentId) { + final Matcher matcher = INNER_COMPONENT_PATTERN.matcher(componentId); + if (matcher.find()) { + final String customComponentId = matcher.group(1); + final String subComponentId = matcher.group(2); + final Component compositeComponent = window.getComponent(customComponentId); + + if (compositeComponent != null) { + if (compositeComponent instanceof Component.UiPermissionAware) { + Component.UiPermissionAware uiPermissionAwareComponent = (Component.UiPermissionAware) compositeComponent; + UiPermissionValue uiPermissionValue = UiPermissionValue.fromId(permissionValue); + + UiPermissionDescriptor permissionDescriptor; + if (subComponentId.contains("<")) { + final Matcher actionMatcher = COMPONENT_ACTION_PATTERN.matcher(subComponentId); + if (actionMatcher.find()) { + final String actionHolderComponentId = actionMatcher.group(1); + final String actionId = actionMatcher.group(2); + + permissionDescriptor = new UiPermissionDescriptor(uiPermissionValue, screenId, + actionHolderComponentId, actionId); + } else { + log.warn(String.format("Incorrect permission definition for component %s in window %s", subComponentId, screenId)); + return; + } + } else { + permissionDescriptor = new UiPermissionDescriptor(uiPermissionValue, screenId, subComponentId); + } + + uiPermissionAwareComponent.applyPermission(permissionDescriptor); + } + } else { + log.info(String.format("Couldn't find component %s in window %s", componentId, screenId)); + } + } + } + + /** + * Process permissions for actions in action holder + * + * @param window Window + * @param screenId Screen Id + * @param permissionValue Permission value + * @param componentId Component Id + */ + private static void applyComponentActionPermission(Window window, String screenId, + Integer permissionValue, String componentId) { + final Matcher matcher = COMPONENT_ACTION_PATTERN.matcher(componentId); + if (matcher.find()) { + final String customComponentId = matcher.group(1); + final String actionId = matcher.group(2); + final Component actionHolderComponent = window.getComponent(customComponentId); + if (actionHolderComponent != null) { + if (actionHolderComponent instanceof Component.SecuredActionsHolder) { + ActionsPermissions permissions = + ((Component.SecuredActionsHolder) actionHolderComponent).getActionsPermissions(); + if (permissionValue == UiPermissionValue.HIDE.getValue()) { + permissions.addHiddenActionPermission(actionId); + } else if (permissionValue == UiPermissionValue.READ_ONLY.getValue()) { + permissions.addDisabledActionPermission(actionId); + } + } else { + log.warn(String.format("Couldn't apply permission on action %s for component %s in window %s", + actionId, customComponentId, screenId)); + } + } else { + log.info(String.format("Couldn't find component %s in window %s", componentId, screenId)); + } + } else { + log.warn(String.format("Incorrect permission definition for component %s in window %s", componentId, screenId)); + } + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/WindowManager.java b/modules/gui/src/com/haulmont/cuba/gui/WindowManager.java index ce70460adf..f878c67ecb 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/WindowManager.java +++ b/modules/gui/src/com/haulmont/cuba/gui/WindowManager.java @@ -1,1357 +1,1357 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui; - -import com.haulmont.bali.datastruct.Pair; -import com.haulmont.bali.util.Preconditions; -import com.haulmont.bali.util.ReflectionHelper; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.config.WindowInfo; -import com.haulmont.cuba.gui.data.DataSupplier; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.DsContext; -import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; -import com.haulmont.cuba.gui.data.impl.DsContextImplementation; -import com.haulmont.cuba.gui.data.impl.GenericDataSupplier; -import com.haulmont.cuba.gui.executors.BackgroundWorker; -import com.haulmont.cuba.gui.logging.UIPerformanceLogger; -import com.haulmont.cuba.gui.logging.UIPerformanceLogger.LifeCycle; -import com.haulmont.cuba.gui.logging.UserActionsLogger; -import com.haulmont.cuba.gui.settings.Settings; -import com.haulmont.cuba.gui.settings.SettingsImpl; -import com.haulmont.cuba.gui.xml.data.DsContextLoader; -import com.haulmont.cuba.gui.xml.layout.ComponentLoader; -import com.haulmont.cuba.gui.xml.layout.LayoutLoader; -import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig; -import com.haulmont.cuba.gui.xml.layout.ScreenXmlLoader; -import com.haulmont.cuba.gui.xml.layout.loaders.ComponentLoaderContext; -import com.haulmont.cuba.security.entity.PermissionType; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.dom4j.Element; -import org.perf4j.StopWatch; -import org.perf4j.log4j.Log4JStopWatch; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.Callable; - -/** - * GenericUI class intended for creation and opening application screens. - */ -public abstract class WindowManager { - private org.slf4j.Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); - - /** - * Constant that is passed to {@link Window#close(String)} and {@link Window#close(String, boolean)} methods when - * the screen is closed by window manager. Propagated to {@link Window.CloseListener#windowClosed}. - */ - public static final String MAIN_MENU_ACTION_ID = "mainMenu"; - - /** - * How to open a screen: {@link #NEW_TAB}, {@link #THIS_TAB}, {@link #DIALOG}, {@link #NEW_WINDOW}. - *
- * You can set additional parameters for window using builder style methods: - *

-     * openEditor("sales$Customer.edit", customer,
-     *            OpenType.DIALOG.width(300).resizable(false), params);
-     * 
- */ - public final static class OpenType { - /** - * Open a screen in new tab of the main window. - *
In Web Client with {@code AppWindow.Mode.SINGLE} the new screen replaces current screen. - */ - public static final OpenType NEW_TAB = new OpenType(OpenMode.NEW_TAB, false); - - /** - * Open a screen on top of the current tab screens stack. - */ - public static final OpenType THIS_TAB = new OpenType(OpenMode.THIS_TAB, false); - - /** - * Open a screen as modal dialog. - */ - public static final OpenType DIALOG = new OpenType(OpenMode.DIALOG, false); - - /** - * In Desktop Client open a screen in new main window, in Web Client the same as new {@link #NEW_TAB} - */ - public static final OpenType NEW_WINDOW = new OpenType(OpenMode.NEW_WINDOW, false); - - private OpenMode openMode; - private boolean mutable = true; - - private Float width; - private SizeUnit widthUnit; - private Float height; - private SizeUnit heightUnit; - - private Integer positionX; - private Integer positionY; - - private Boolean resizable; - private Boolean closeable; - private Boolean modal; - private Boolean closeOnClickOutside; - private Boolean maximized; - - public OpenType(OpenMode openMode) { - this.openMode = openMode; - } - - private OpenType(OpenMode openMode, boolean mutable) { - this.openMode = openMode; - this.mutable = mutable; - } - - public OpenMode getOpenMode() { - return openMode; - } - - public OpenType setOpenMode(OpenMode openMode) { - OpenType instance = getMutableInstance(); - - instance.openMode = openMode; - return instance; - } - - public SizeUnit getHeightUnit() { - return heightUnit; - } - - public OpenType setHeightUnit(SizeUnit heightUnit) { - OpenType instance = getMutableInstance(); - instance.heightUnit = heightUnit; - return instance; - } - - public Float getHeight() { - return height; - } - - /** - * @deprecated Use {@link #height(Float)} instead. - */ - @Deprecated - public OpenType height(Integer height) { - return height(height.floatValue()); - } - - /** - * @deprecated Use {@link #setHeight(Float)} instead. - */ - @Deprecated - public OpenType setHeight(Integer height) { - return setHeight(height.floatValue()); - } - - public OpenType height(Float height) { - OpenType instance = getMutableInstance(); - - instance.height = height; - return instance; - } - - public OpenType setHeight(Float height) { - OpenType instance = getMutableInstance(); - - instance.height = height; - return instance; - } - - public OpenType height(String height) { - return setHeight(height); - } - - public OpenType setHeight(String height) { - OpenType instance = getMutableInstance(); - - SizeWithUnit size = SizeWithUnit.parseStringSize(height); - - instance.height = size.getSize(); - instance.heightUnit = size.getUnit(); - return instance; - } - - public OpenType heightAuto() { - OpenType instance = getMutableInstance(); - - instance.height = -1.0f; - instance.heightUnit = SizeUnit.PIXELS; - return instance; - } - - public SizeUnit getWidthUnit() { - return widthUnit; - } - - public OpenType setWidthUnit(SizeUnit widthUnit) { - OpenType instance = getMutableInstance(); - instance.widthUnit = widthUnit; - return instance; - } - - public Float getWidth() { - return width; - } - - /** - * @deprecated Use {@link #width(Float)} instead. - */ - @Deprecated - public OpenType width(Integer width) { - return width(width.floatValue()); - } - - /** - * @deprecated Use {@link #setWidth(Float)} instead. - */ - @Deprecated - public OpenType setWidth(Integer width) { - return setWidth(width.floatValue()); - } - - public OpenType width(Float width) { - OpenType instance = getMutableInstance(); - - instance.width = width; - return instance; - } - - public OpenType setWidth(Float width) { - OpenType instance = getMutableInstance(); - - instance.width = width; - return instance; - } - - public OpenType width(String width) { - return setWidth(width); - } - - public OpenType setWidth(String width) { - OpenType instance = getMutableInstance(); - - SizeWithUnit size = SizeWithUnit.parseStringSize(width); - - instance.width = size.getSize(); - instance.widthUnit = size.getUnit(); - return instance; - } - - public OpenType widthAuto() { - OpenType instance = getMutableInstance(); - - instance.width = -1.0f; - instance.widthUnit = SizeUnit.PIXELS; - return instance; - } - - public Integer getPositionX() { - return positionX; - } - - public OpenType setPositionX(Integer positionX) { - OpenType instance = getMutableInstance(); - - instance.positionX = positionX; - return instance; - } - - public OpenType positionX(Integer positionX) { - OpenType instance = getMutableInstance(); - - instance.positionX = positionX; - return instance; - } - - public Integer getPositionY() { - return positionY; - } - - public OpenType setPositionY(Integer positionY) { - OpenType instance = getMutableInstance(); - - instance.positionY = positionY; - return instance; - } - - public OpenType positionY(Integer positionY) { - OpenType instance = getMutableInstance(); - - instance.positionY = positionY; - return instance; - } - - public OpenType center() { - OpenType instance = getMutableInstance(); - instance.positionX = null; - instance.positionY = null; - return instance; - } - - public Boolean getResizable() { - return resizable; - } - - public OpenType setResizable(Boolean resizable) { - OpenType instance = getMutableInstance(); - - instance.resizable = resizable; - return instance; - } - - public OpenType resizable(Boolean resizable) { - OpenType instance = getMutableInstance(); - - instance.resizable = resizable; - return instance; - } - - public Boolean getCloseable() { - return closeable; - } - - public OpenType closeable(Boolean closeable) { - OpenType instance = getMutableInstance(); - - instance.closeable = closeable; - return instance; - } - - public OpenType setCloseable(Boolean closeable) { - OpenType instance = getMutableInstance(); - - instance.closeable = closeable; - return instance; - } - - public Boolean getModal() { - return modal; - } - - public OpenType modal(Boolean modal) { - OpenType instance = getMutableInstance(); - - instance.modal = modal; - return instance; - } - - public OpenType setModal(Boolean modal) { - OpenType instance = getMutableInstance(); - - instance.modal = modal; - return instance; - } - - /** - * @return true if a window can be closed by click on outside window area - */ - public Boolean getCloseOnClickOutside() { - return closeOnClickOutside; - } - - /** - * Set closeOnClickOutside to true if a window should be closed by click on outside window area. - * It works when a window has a modal mode. - */ - public OpenType closeOnClickOutside(Boolean closeOnClickOutside) { - OpenType instance = getMutableInstance(); - - instance.closeOnClickOutside = closeOnClickOutside; - return instance; - } - - /** - * Set closeOnClickOutside to true if a window should be closed by click on outside window area. - * It works when a window has a modal mode. - */ - public OpenType setCloseOnClickOutside(Boolean closeOnClickOutside) { - OpenType instance = getMutableInstance(); - - instance.closeOnClickOutside = closeOnClickOutside; - return instance; - } - - /** - * @return true if a window is maximized across the screen. - */ - public Boolean getMaximized() { - return maximized; - } - - /** - * Set maximized to true if a window should be maximized across the screen. - */ - public OpenType maximized(Boolean maximized) { - OpenType instance = getMutableInstance(); - - instance.maximized = maximized; - return instance; - } - - /** - * Set maximized to true if a window should be maximized across the screen. - */ - public OpenType setMaximized(Boolean maximized) { - OpenType instance = getMutableInstance(); - - instance.maximized = maximized; - return instance; - } - - private OpenType getMutableInstance() { - if (!mutable) { - return copy(); - } - - return this; - } - - public static OpenType valueOf(String openTypeString) { - Preconditions.checkNotNullArgument(openTypeString, "openTypeString should not be null"); - - switch (openTypeString) { - case "NEW_TAB": - return NEW_TAB; - - case "THIS_TAB": - return THIS_TAB; - - case "DIALOG": - return DIALOG; - - case "NEW_WINDOW": - return NEW_WINDOW; - - default: - throw new IllegalArgumentException("Unable to parse OpenType"); - } - } - - public OpenType copy() { - OpenType openType = new OpenType(openMode); - - openType.setModal(modal); - openType.setResizable(resizable); - openType.setCloseable(closeable); - openType.setHeight(height); - openType.setHeightUnit(heightUnit); - openType.setWidth(width); - openType.setWidthUnit(widthUnit); - openType.setCloseOnClickOutside(closeOnClickOutside); - openType.setMaximized(maximized); - openType.setPositionX(positionX); - openType.setPositionY(positionY); - - return openType; - } - } - - public enum OpenMode { - /** - * Open a screen in new tab of the main window. - *
In Web Client with {@code AppWindow.Mode.SINGLE} the new screen replaces current screen. - */ - NEW_TAB, - /** - * Open a screen on top of the current tab screens stack. - */ - THIS_TAB, - /** - * Open a screen as modal dialog. - */ - DIALOG, - /** - * In Desktop Client open a screen in new main window, in Web Client the same as new {@link #NEW_TAB} - */ - NEW_WINDOW - } - - public interface WindowCloseListener { - void onWindowClose(Window window, boolean anyOpenWindowExist); - } - - protected DataSupplier defaultDataSupplier; - - protected Messages messages = AppBeans.get(Messages.NAME); - - protected Scripting scripting = AppBeans.get(Scripting.NAME); - - protected Resources resources = AppBeans.get(Resources.NAME); - - protected Security security = AppBeans.get(Security.NAME); - - protected Configuration configuration = AppBeans.get(Configuration.NAME); - - protected BackgroundWorker backgroundWorker = AppBeans.get(BackgroundWorker.NAME); - - protected UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); - - protected ScreenXmlLoader screenXmlLoader = AppBeans.get(ScreenXmlLoader.NAME); - - protected ScreenViewsLoader screenViewsLoader = AppBeans.get(ScreenViewsLoader.NAME); - - private DialogParams dialogParams; - - protected List listeners = new ArrayList<>(); - - protected WindowManager() { - dialogParams = createDialogParams(); - defaultDataSupplier = new GenericDataSupplier(); - } - - public abstract Collection getOpenWindows(); - - /** - * Select tab with window in main tabsheet. - */ - public abstract void selectWindowTab(Window window); - - /** - * @deprecated Please use {@link Window#setCaption(String)} ()} and {@link Window#setDescription(String)} ()} methods. - */ - @Deprecated - public abstract void setWindowCaption(Window window, String caption, String description); - - protected Integer getHash(WindowInfo windowInfo, Map params) { - return windowInfo.hashCode() + params.hashCode(); - } - - protected Window createWindow(WindowInfo windowInfo, OpenType openType, Map params, - LayoutLoaderConfig layoutConfig, boolean topLevel) { - if (!topLevel) { - checkPermission(windowInfo); - } - - StopWatch loadDescriptorWatch = new Log4JStopWatch(windowInfo.getId() + "#" + - LifeCycle.LOAD, - Logger.getLogger(UIPerformanceLogger.class)); - - Element element = screenXmlLoader.load(windowInfo.getTemplate(), windowInfo.getId(), params); - - preloadMainScreenClass(element);//try to load main screen class to resolve dynamic compilation dependencies issues - - ComponentLoaderContext componentLoaderContext = new ComponentLoaderContext(params); - componentLoaderContext.setFullFrameId(windowInfo.getId()); - componentLoaderContext.setCurrentFrameId(windowInfo.getId()); - - ComponentLoader windowLoader = createLayout(windowInfo, element, componentLoaderContext, layoutConfig); - Window clientSpecificWindow = (Window) windowLoader.getResultComponent(); - Window windowWrapper = wrapByCustomClass(clientSpecificWindow, element); - - screenViewsLoader.deployViews(element); - - DsContext dsContext = loadDsContext(element); - initDatasources(clientSpecificWindow, dsContext, params); - - componentLoaderContext.setDsContext(dsContext); - - WindowContext windowContext = new WindowContextImpl(clientSpecificWindow, openType, params); - clientSpecificWindow.setContext(windowContext); - dsContext.setFrameContext(windowContext); - - //noinspection unchecked - windowLoader.loadComponent(); - - clientSpecificWindow.setWindowManager(this); - - loadDescriptorWatch.stop(); - - initWrapperFrame(windowWrapper, componentLoaderContext, element, params); - - componentLoaderContext.setFrame(windowWrapper); - componentLoaderContext.executePostInitTasks(); - - if (configuration.getConfig(GlobalConfig.class).getTestMode()) { - initDebugIds(clientSpecificWindow); - } - - StopWatch uiPermissionsWatch = new Log4JStopWatch(windowInfo.getId() + "#" + - LifeCycle.UI_PERMISSIONS, - Logger.getLogger(UIPerformanceLogger.class)); - - // apply ui permissions - WindowCreationHelper.applyUiPermissions(clientSpecificWindow); - - uiPermissionsWatch.stop(); - - return windowWrapper; - } - - protected void preloadMainScreenClass(Element element) { - String screenClass = element.attributeValue("class"); - if (!StringUtils.isBlank(screenClass)) { - scripting.loadClass(screenClass); - } - } - - protected void initDebugIds(Frame frame) { - } - - protected void checkPermission(WindowInfo windowInfo) { - boolean permitted = security.isScreenPermitted(windowInfo.getId()); - if (!permitted) { - throw new AccessDeniedException(PermissionType.SCREEN, windowInfo.getId()); - } - } - - protected void initDatasources(Window window, DsContext dsContext, Map params) { - window.setDsContext(dsContext); - - for (Datasource ds : dsContext.getAll()) { - if (Datasource.State.NOT_INITIALIZED.equals(ds.getState()) && ds instanceof DatasourceImplementation) { - ((DatasourceImplementation) ds).initialized(); - } - } - } - - protected ComponentLoader createLayout(WindowInfo windowInfo, Element rootElement, - ComponentLoader.Context context, LayoutLoaderConfig layoutConfig) { - String descriptorPath = windowInfo.getTemplate(); - - LayoutLoader layoutLoader = new LayoutLoader(context, AppConfig.getFactory(), layoutConfig); - layoutLoader.setLocale(getLocale()); - if (!StringUtils.isEmpty(descriptorPath)) { - if (descriptorPath.contains("/")) { - descriptorPath = StringUtils.substring(descriptorPath, 0, descriptorPath.lastIndexOf("/")); - } - - String path = descriptorPath.replaceAll("/", "."); - int start = path.startsWith(".") ? 1 : 0; - path = path.substring(start); - - layoutLoader.setMessagesPack(path); - } - //noinspection UnnecessaryLocalVariable - ComponentLoader windowLoader = layoutLoader.createWindow(rootElement, windowInfo.getId()); - return windowLoader; - } - - protected DsContext loadDsContext(Element element) { - DataSupplier dataSupplier; - - String dataSupplierClass = element.attributeValue("dataSupplier"); - if (StringUtils.isEmpty(dataSupplierClass)) { - dataSupplier = defaultDataSupplier; - } else { - Class aClass = ReflectionHelper.getClass(dataSupplierClass); - try { - dataSupplier = (DataSupplier) aClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Unable to create data supplier for screen", e); - } - } - - //noinspection UnnecessaryLocalVariable - DsContext dsContext = new DsContextLoader(dataSupplier).loadDatasources(element.element("dsContext"), null); - return dsContext; - } - - protected Window createWindow(WindowInfo windowInfo, Map params) { - Window window; - try { - window = (Window) windowInfo.getScreenClass().newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException("Unable to instantiate window class", e); - } - - window.setId(windowInfo.getId()); - window.setWindowManager(this); - - init(window, params); - - StopWatch uiPermissionsWatch = new Log4JStopWatch(windowInfo.getId() + "#" + - LifeCycle.UI_PERMISSIONS, - Logger.getLogger(UIPerformanceLogger.class)); - - // apply ui permissions - WindowCreationHelper.applyUiPermissions(window); - - uiPermissionsWatch.stop(); - - return window; - } - - protected Window createWindowByScreenClass(WindowInfo windowInfo, Map params) { - Class screenClass = windowInfo.getScreenClass(); - - Class[] paramTypes = ReflectionHelper.getParamTypes(params); - Constructor constructor = null; - try { - constructor = screenClass.getConstructor(paramTypes); - } catch (NoSuchMethodException e) { - // - } - - Object obj; - try { - if (constructor == null) { - obj = screenClass.newInstance(); - } else { - obj = constructor.newInstance(params); - } - } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException("Unable to instantiate window class", e); - } - - if (obj instanceof Callable) { - try { - Callable callable = (Callable) obj; - Window window = (Window) callable.call(); - return window; - } catch (Exception e) { - throw new RuntimeException("Unable to instantiate window class", e); - } - } else if (obj instanceof Runnable) { - ((Runnable) obj).run(); - return null; - } else - throw new IllegalStateException("Screen class must be an instance of Callable or Runnable"); - } - - public boolean windowExist(WindowInfo windowInfo, Map params) { - return (getWindow(getHash(windowInfo, params)) != null); - } - - public Window openWindow(WindowInfo windowInfo, OpenType openType, Map params) { - if (params == null) { - params = Collections.emptyMap(); - } - - checkCanOpenWindow(windowInfo, openType, params); - Integer hashCode = getHash(windowInfo, params); - params = createParametersMap(windowInfo, params); - String template = windowInfo.getTemplate(); - - Window window; - - if (template != null) { - window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getWindowLoaders(), false); - String caption = loadCaption(window, params); - String description = loadDescription(window, params); - if (isOpenAsNewTab(openType)) { - putToWindowMap(window, hashCode); - } - showWindow(window, caption, description, openType, windowInfo.getMultipleOpen()); - userActionsLog.trace("Window {} was opened", windowInfo.getId()); - return window; - } else { - Class screenClass = windowInfo.getScreenClass(); - if (screenClass != null) { - window = createWindowByScreenClass(windowInfo, params); - if (isOpenAsNewTab(openType)) { - putToWindowMap(window, hashCode); - } - userActionsLog.trace("Window {} was opened", windowInfo.getId()); - return window; - } else - return null; - } - } - - protected boolean isOpenAsNewTab(OpenType openType) { - return openType.getOpenMode() == OpenMode.NEW_TAB; - } - - public Window openWindow(WindowInfo windowInfo, OpenType openType) { - return openWindow(windowInfo, openType, Collections.emptyMap()); - } - - protected abstract void putToWindowMap(Window window, Integer hashCode); - - protected abstract Window getWindow(Integer hashCode); - - protected abstract void checkCanOpenWindow(WindowInfo windowInfo, OpenType openType, Map params); - - protected String loadCaption(Window window, Map params) { - String caption = window.getCaption(); - if (!StringUtils.isEmpty(caption)) { - caption = TemplateHelper.processTemplate(caption, params); - } else { - caption = WindowParams.CAPTION.getString(params); - if (StringUtils.isEmpty(caption)) { - String msgPack = window.getMessagesPack(); - if (msgPack != null) { - caption = messages.getMessage(msgPack, "caption"); - if (!"caption".equals(caption)) { - caption = TemplateHelper.processTemplate(caption, params); - } - } - } else { - caption = TemplateHelper.processTemplate(caption, params); - } - } - window.setCaption(caption); - - return caption; - } - - protected String loadDescription(Window window, Map params) { - String description = window.getDescription(); - if (!StringUtils.isEmpty(description)) { - return TemplateHelper.processTemplate(description, params); - } else { - description = WindowParams.DESCRIPTION.getString(params); - if (StringUtils.isEmpty(description)) { - description = null; - } else { - description = TemplateHelper.processTemplate(description, params); - } - } - window.setDescription(description); - - return description; - } - - public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType, - Datasource parentDs) { - return openEditor(windowInfo, item, openType, Collections.emptyMap(), parentDs); - } - - public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType) { - return openEditor(windowInfo, item, openType, Collections.emptyMap()); - } - - public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType, Map params) { - return openEditor(windowInfo, item, openType, params, null); - } - - public Window.Editor openEditor(WindowInfo windowInfo, Entity item, - OpenType openType, Map params, - Datasource parentDs) { - if (params == null) { - params = Collections.emptyMap(); - } - - checkCanOpenWindow(windowInfo, openType, params); - - Integer hashCode = getHash(windowInfo, params); - String template = windowInfo.getTemplate(); - - if (openType.getOpenMode() != OpenMode.DIALOG) { - Window existingWindow = getWindow(hashCode); - if (existingWindow != null) { - params = createParametersMap(windowInfo, params); - String caption = loadCaption(existingWindow, params); - String description = loadDescription(existingWindow, params); - - showWindow(existingWindow, caption, description, openType, false); - return (Window.Editor) existingWindow; - } - } - - params = createParametersMap(windowInfo, params); - WindowParams.ITEM.set(params, item instanceof Datasource ? ((Datasource) item).getItem() : item); - - Window window; - if (template != null) { - window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getEditorLoaders(), false); - } else { - Class windowClass = windowInfo.getScreenClass(); - if (windowClass != null) { - window = createWindow(windowInfo, params); - if (!(window instanceof Window.Editor)) { - throw new IllegalStateException( - String.format("Class %s does't implement Window.Editor interface", windowClass)); - } - } else { - throw new IllegalStateException("Invalid WindowInfo: " + windowInfo); - } - } - ((Window.Editor) window).setParentDs(parentDs); - - StopWatch setItemWatch = new Log4JStopWatch(windowInfo.getId() + "#" + - LifeCycle.SET_ITEM, - Logger.getLogger(UIPerformanceLogger.class)); - - ((Window.Editor) window).setItem(item); - - setItemWatch.stop(); - - String caption = loadCaption(window, params); - String description = loadDescription(window, params); - showWindow(window, caption, description, openType, false); - - userActionsLog.trace("Editor {} was opened", windowInfo.getId()); - - return (Window.Editor) window; - } - - public Window.Lookup openLookup(WindowInfo windowInfo, Window.Lookup.Handler handler, - OpenType openType, Map params) { - if (params == null) { - params = Collections.emptyMap(); - } - - checkCanOpenWindow(windowInfo, openType, params); - - params = createParametersMap(windowInfo, params); - - String template = windowInfo.getTemplate(); - Window window; - - if (template != null) { - window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getLookupLoaders(), false); - - ((Window.Lookup) window).initLookupLayout(); - - Element element = ((Component.HasXmlDescriptor) window).getXmlDescriptor(); - String lookupComponent = element.attributeValue("lookupComponent"); - if (!StringUtils.isEmpty(lookupComponent)) { - Component component = window.getComponent(lookupComponent); - ((Window.Lookup) window).setLookupComponent(component); - } - } else { - Class windowClass = windowInfo.getScreenClass(); - if (windowClass != null) { - window = createWindow(windowInfo, params); - if (!(window instanceof Window.Lookup)) { - throw new IllegalStateException( - String.format("Class %s does't implement Window.Lookup interface", windowClass)); - } - } else { - throw new IllegalStateException("Invalid WindowInfo: " + windowInfo); - } - } - - ((Window.Lookup) window).setLookupHandler(handler); - - String caption = loadCaption(window, params); - String description = loadDescription(window, params); - - showWindow(window, caption, description, openType, false); - - userActionsLog.trace("Lookup {} was opened", windowInfo.getId()); - - return (Window.Lookup) window; - } - - public Window.Lookup openLookup(WindowInfo windowInfo, Window.Lookup.Handler handler, OpenType openType) { - return openLookup(windowInfo, handler, openType, Collections.emptyMap()); - } - - public Frame openFrame(Frame parentFrame, Component parent, WindowInfo windowInfo) { - return openFrame(parentFrame, parent, windowInfo, Collections.emptyMap()); - } - - public Frame openFrame(Frame parentFrame, Component parent, WindowInfo windowInfo, Map params) { - return openFrame(parentFrame, parent, null, windowInfo, params); - } - - public Frame openFrame(Frame parentFrame, Component parent, @Nullable String id, - WindowInfo windowInfo, Map params) { - if (params == null) { - params = Collections.emptyMap(); - } - - // Parameters can be useful later - params = createParametersMap(windowInfo, params); - - String src = windowInfo.getTemplate(); - - ComponentLoaderContext context = new ComponentLoaderContext(params); - context.setDsContext(parentFrame.getDsContext()); - context.setFullFrameId(windowInfo.getId()); - context.setCurrentFrameId(windowInfo.getId()); - - LayoutLoader loader = new LayoutLoader(context, AppConfig.getFactory(), LayoutLoaderConfig.getFrameLoaders()); - loader.setLocale(getLocale()); - loader.setMessagesPack(parentFrame.getMessagesPack()); - - StopWatch loadDescriptorWatch = new Log4JStopWatch(windowInfo.getId() + "#" + - LifeCycle.LOAD, - Logger.getLogger(UIPerformanceLogger.class)); - - Frame component; - String frameId = id != null ? id : windowInfo.getId(); - - Pair loaderElementPair = loader.createFrameComponent(src, frameId, context.getParams()); - component = (Frame) loaderElementPair.getFirst().getResultComponent(); - - if (parent != null) { - showFrame(parent, component); - } else { - component.setFrame(parentFrame); - } - - loaderElementPair.getFirst().loadComponent(); - - if (component.getMessagesPack() == null) { - component.setMessagesPack(parentFrame.getMessagesPack()); - } - - context.executeInjectTasks(); - context.setFrame(component); - context.executePostWrapTasks(); - - // init of frame - context.executeInitTasks(); - - context.executePostInitTasks(); - - loadDescriptorWatch.stop(); - - initDebugIds(component); - - userActionsLog.trace("Frame {} was opened", windowInfo.getId()); - - return component; - } - - protected Map createParametersMap(WindowInfo windowInfo, Map params) { - Map map = new HashMap<>(params.size()); - - Element element = windowInfo.getDescriptor(); - if (element != null) { - Element paramsElement = element.element("params") != null ? element.element("params") : element; - if (paramsElement != null) { - @SuppressWarnings({"unchecked"}) - List paramElements = paramsElement.elements("param"); - for (Element paramElement : paramElements) { - String name = paramElement.attributeValue("name"); - String value = paramElement.attributeValue("value"); - if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) { - Boolean booleanValue = Boolean.valueOf(value); - map.put(name, booleanValue); - } else { - map.put(name, value); - } - } - } - } - map.putAll(params); - - return map; - } - - @Deprecated - protected DialogParams createDialogParams() { - return new DialogParams(); - } - - @Deprecated - public DialogParams getDialogParams() { - return dialogParams; - } - - protected void fireListeners(Window window, boolean anyOpenWindowExist) { - for (WindowCloseListener wcl : listeners) { - wcl.onWindowClose(window, anyOpenWindowExist); - } - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - protected abstract void showWindow(Window window, String caption, OpenType openType, boolean multipleOpen); - - protected abstract void showWindow(Window window, String caption, String description, OpenType openType, boolean multipleOpen); - - protected abstract void showFrame(Component parent, Frame frame); - - @Deprecated - protected void copyDialogParamsToOpenType(OpenType mutableOpenType) { - DialogParams dialogParams = getDialogParams(); - if (dialogParams.getCloseable() != null && mutableOpenType.getCloseable() == null) { - mutableOpenType.closeable(dialogParams.getCloseable()); - } - if (dialogParams.getModal() != null && mutableOpenType.getModal() == null) { - mutableOpenType.setModal(dialogParams.getModal()); - } - if (dialogParams.getResizable() != null && mutableOpenType.getResizable() == null) { - mutableOpenType.setResizable(dialogParams.getResizable()); - } - if (dialogParams.getWidth() != null && mutableOpenType.getWidth() == null) { - mutableOpenType.setWidth(dialogParams.getWidth()); - } - if (dialogParams.getWidthUnit() != null && mutableOpenType.getWidthUnit() == null) { - mutableOpenType.setWidthUnit(dialogParams.getWidthUnit()); - } - if (dialogParams.getHeight() != null && mutableOpenType.getHeight() == null) { - mutableOpenType.setHeight(dialogParams.getHeight()); - } - if (dialogParams.getHeightUnit() != null && mutableOpenType.getHeightUnit() == null) { - mutableOpenType.setHeightUnit(dialogParams.getHeightUnit()); - } - } - - protected OpenType overrideOpenTypeParams(OpenType mutableOpenType, DialogOptions dialogOptions) { - if (BooleanUtils.isTrue(dialogOptions.getForceDialog())) { - mutableOpenType.setOpenMode(OpenMode.DIALOG); - } - - if (dialogOptions.getHeight() != null) { - mutableOpenType.setHeight(dialogOptions.getHeight()); - } - - if (dialogOptions.getHeightUnit() != null) { - mutableOpenType.setHeightUnit(dialogOptions.getHeightUnit()); - } - - if (dialogOptions.getWidth() != null) { - mutableOpenType.setWidth(dialogOptions.getWidth()); - } - - if (dialogOptions.getWidthUnit() != null) { - mutableOpenType.setWidthUnit(dialogOptions.getWidthUnit()); - } - - if (dialogOptions.getResizable() != null) { - mutableOpenType.setResizable(dialogOptions.getResizable()); - } - - if (dialogOptions.getCloseable() != null) { - mutableOpenType.setCloseable(dialogOptions.getCloseable()); - } - - if (dialogOptions.getModal() != null) { - mutableOpenType.setModal(dialogOptions.getModal()); - } - - if(dialogOptions.getCloseOnClickOutside() != null){ - mutableOpenType.setCloseOnClickOutside(dialogOptions.getCloseOnClickOutside()); - } - - if (dialogOptions.getMaximized() != null) { - mutableOpenType.setMaximized(dialogOptions.getMaximized()); - } - - if (dialogOptions.getPositionX() != null) { - mutableOpenType.setPositionX(dialogOptions.getPositionX()); - } - - if (dialogOptions.getPositionY() != null) { - mutableOpenType.setPositionY(dialogOptions.getPositionY()); - } - - return mutableOpenType; - } - - protected Settings getSettingsImpl(String id) { - return new SettingsImpl(id); - } - - protected void afterShowWindow(Window window) { - if (!WindowParams.DISABLE_APPLY_SETTINGS.getBool(window.getContext())) { - window.applySettings(getSettingsImpl(window.getId())); - } - if (!WindowParams.DISABLE_RESUME_SUSPENDED.getBool(window.getContext())) { - ((DsContextImplementation) window.getDsContext()).resumeSuspended(); - } - - if (window instanceof AbstractWindow) { - AbstractWindow abstractWindow = (AbstractWindow) window; - - if (abstractWindow.isAttributeAccessControlEnabled()) { - AttributeAccessSupport attributeAccessSupport = AppBeans.get(AttributeAccessSupport.NAME); - attributeAccessSupport.applyAttributeAccess(abstractWindow, false); - } - - StopWatch readyStopWatch = new Log4JStopWatch(window.getId() + "#" + - LifeCycle.READY, - Logger.getLogger(UIPerformanceLogger.class)); - - abstractWindow.ready(); - - readyStopWatch.stop(); - } - } - - public abstract void close(Window window); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - protected Locale getLocale() { - return userSessionSource.getUserSession().getLocale(); - } - - protected Window wrapByCustomClass(Frame window, Element element) { - String screenClass = element.attributeValue("class"); - if (StringUtils.isBlank(screenClass)) { - throw new GuiDevelopmentException("'class' attribute is not defined in XML descriptor", window.getId()); - } - - Class aClass = scripting.loadClass(screenClass); - if (aClass == null) { - throw new GuiDevelopmentException("Unable to load controller class", window.getId()); - } - //noinspection UnnecessaryLocalVariable - Window wrappingWindow = ((WrappedWindow) window).wrapBy(aClass); - return wrappingWindow; - } - - protected void initWrapperFrame(Window wrappingWindow, ComponentLoaderContext context, Element element, - Map params) { - if (wrappingWindow instanceof AbstractWindow) { - Element companionsElem = element.element("companions"); - if (companionsElem != null) { - StopWatch companionStopWatch = new Log4JStopWatch(wrappingWindow.getId() + "#" + - LifeCycle.COMPANION, - Logger.getLogger(UIPerformanceLogger.class)); - - initCompanion(companionsElem, (AbstractWindow) wrappingWindow); - - companionStopWatch.stop(); - } - } - - StopWatch injectStopWatch = new Log4JStopWatch(wrappingWindow.getId() + "#" + - LifeCycle.INJECTION, - Logger.getLogger(UIPerformanceLogger.class)); - - ControllerDependencyInjector dependencyInjector = new ControllerDependencyInjector(wrappingWindow, params); - dependencyInjector.inject(); - - injectStopWatch.stop(); - - context.executeInjectTasks(); - context.executePostWrapTasks(); - - init(wrappingWindow, params); - - context.executeInitTasks(); - } - - protected void init(Window window, Map params) { - if (window instanceof AbstractWindow) { - StopWatch initStopWatch = new Log4JStopWatch(window.getId() + - "#" + LifeCycle.INIT, - Logger.getLogger(UIPerformanceLogger.class)); - - ((AbstractWindow) window).init(params); - - initStopWatch.stop(); - } - } - - protected void initCompanion(Element companionsElem, AbstractWindow window) { - Element element = companionsElem.element(AppConfig.getClientType().toString().toLowerCase()); - if (element != null) { - String className = element.attributeValue("class"); - if (!StringUtils.isBlank(className)) { - Class aClass = scripting.loadClassNN(className); - Object companion; - try { - companion = aClass.newInstance(); - window.setCompanion(companion); - - CompanionDependencyInjector cdi = new CompanionDependencyInjector(window, companion); - cdi.inject(); - } catch (Exception e) { - throw new RuntimeException("Unable to init Companion", e); - } - } - } - } - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Show notification with {@link Frame.NotificationType#HUMANIZED}.
- * Supports line breaks ({@code \n}). - * - * @param caption text - */ - public abstract void showNotification(String caption); - - /** - * Show notification.
- * Supports line breaks ({@code \n}). - * - * @param caption text - * @param type defines how to display the notification. - * Don't forget to escape data from the database in case of {@code *_HTML} types! - */ - public abstract void showNotification(String caption, Frame.NotificationType type); - - /** - * Show notification with caption description.
- * Supports line breaks ({@code \n}). - * - * @param caption caption - * @param description text - * @param type defines how to display the notification. - * Don't forget to escape data from the database in case of {@code *_HTML} types! - */ - public abstract void showNotification(String caption, String description, Frame.NotificationType type); - - /** - * Show message dialog with title and message.
- * Supports line breaks ({@code \n}) for non HTML messageType. - * - * @param title dialog title - * @param message text - * @param messageType defines how to display the dialog. - * Don't forget to escape data from the database in case of {@code *_HTML} types! - */ - public abstract void showMessageDialog(String title, String message, Frame.MessageType messageType); - - /** - * Show options dialog with title and message.
- * Supports line breaks ({@code \n}) for non HTML messageType. - * - * @param title dialog title - * @param message text - * @param messageType defines how to display the dialog. - * Don't forget to escape data from the database in case of {@code *_HTML} types! - * @param actions available actions - */ - public abstract void showOptionDialog(String title, String message, Frame.MessageType messageType, Action[] actions); - - /** - * Shows exception dialog with default caption, message and displays stacktrace of given throwable. - * - * @param throwable throwable - */ - public abstract void showExceptionDialog(Throwable throwable); - - /** - * Shows exception dialog with given caption, message and displays stacktrace of given throwable. - * - * @param throwable throwable - * @param caption dialog caption - * @param message dialog message - */ - public abstract void showExceptionDialog(Throwable throwable, @Nullable String caption, @Nullable String message); - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /** - * Open a web page in browser. - * @param url URL of the page - * @param params optional parameters. - *
The following parameters are recognized by Web client: - *
    - *
  • {@code target} - String value used as the target name in a - * window.open call in the client. This means that special values such as - * "_blank", "_self", "_top", "_parent" have special meaning. If not specified, "_blank" is used.
  • - *
  • {@code width} - Integer value specifying the width of the browser window in pixels
  • - *
  • {@code height} - Integer value specifying the height of the browser window in pixels
  • - *
  • {@code border} - String value specifying the border style of the window of the browser window. - * Possible values are "DEFAULT", "MINIMAL", "NONE".
  • - *
- * Desktop client doesn't support any parameters and just ignores them. - */ - public abstract void showWebPage(String url, @Nullable Map params); +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui; + +import com.haulmont.bali.datastruct.Pair; +import com.haulmont.bali.util.Preconditions; +import com.haulmont.bali.util.ReflectionHelper; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.config.WindowInfo; +import com.haulmont.cuba.gui.data.DataSupplier; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.DsContext; +import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; +import com.haulmont.cuba.gui.data.impl.DsContextImplementation; +import com.haulmont.cuba.gui.data.impl.GenericDataSupplier; +import com.haulmont.cuba.gui.executors.BackgroundWorker; +import com.haulmont.cuba.gui.logging.UIPerformanceLogger; +import com.haulmont.cuba.gui.logging.UIPerformanceLogger.LifeCycle; +import com.haulmont.cuba.gui.logging.UserActionsLogger; +import com.haulmont.cuba.gui.settings.Settings; +import com.haulmont.cuba.gui.settings.SettingsImpl; +import com.haulmont.cuba.gui.xml.data.DsContextLoader; +import com.haulmont.cuba.gui.xml.layout.ComponentLoader; +import com.haulmont.cuba.gui.xml.layout.LayoutLoader; +import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig; +import com.haulmont.cuba.gui.xml.layout.ScreenXmlLoader; +import com.haulmont.cuba.gui.xml.layout.loaders.ComponentLoaderContext; +import com.haulmont.cuba.security.entity.PermissionType; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dom4j.Element; +import org.perf4j.StopWatch; +import org.perf4j.log4j.Log4JStopWatch; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.Callable; + +/** + * GenericUI class intended for creation and opening application screens. + */ +public abstract class WindowManager { + private org.slf4j.Logger userActionsLog = LoggerFactory.getLogger(UserActionsLogger.class); + + /** + * Constant that is passed to {@link Window#close(String)} and {@link Window#close(String, boolean)} methods when + * the screen is closed by window manager. Propagated to {@link Window.CloseListener#windowClosed}. + */ + public static final String MAIN_MENU_ACTION_ID = "mainMenu"; + + /** + * How to open a screen: {@link #NEW_TAB}, {@link #THIS_TAB}, {@link #DIALOG}, {@link #NEW_WINDOW}. + *
+ * You can set additional parameters for window using builder style methods: + *
+     * openEditor("sales$Customer.edit", customer,
+     *            OpenType.DIALOG.width(300).resizable(false), params);
+     * 
+ */ + public final static class OpenType { + /** + * Open a screen in new tab of the main window. + *
In Web Client with {@code AppWindow.Mode.SINGLE} the new screen replaces current screen. + */ + public static final OpenType NEW_TAB = new OpenType(OpenMode.NEW_TAB, false); + + /** + * Open a screen on top of the current tab screens stack. + */ + public static final OpenType THIS_TAB = new OpenType(OpenMode.THIS_TAB, false); + + /** + * Open a screen as modal dialog. + */ + public static final OpenType DIALOG = new OpenType(OpenMode.DIALOG, false); + + /** + * In Desktop Client open a screen in new main window, in Web Client the same as new {@link #NEW_TAB} + */ + public static final OpenType NEW_WINDOW = new OpenType(OpenMode.NEW_WINDOW, false); + + private OpenMode openMode; + private boolean mutable = true; + + private Float width; + private SizeUnit widthUnit; + private Float height; + private SizeUnit heightUnit; + + private Integer positionX; + private Integer positionY; + + private Boolean resizable; + private Boolean closeable; + private Boolean modal; + private Boolean closeOnClickOutside; + private Boolean maximized; + + public OpenType(OpenMode openMode) { + this.openMode = openMode; + } + + private OpenType(OpenMode openMode, boolean mutable) { + this.openMode = openMode; + this.mutable = mutable; + } + + public OpenMode getOpenMode() { + return openMode; + } + + public OpenType setOpenMode(OpenMode openMode) { + OpenType instance = getMutableInstance(); + + instance.openMode = openMode; + return instance; + } + + public SizeUnit getHeightUnit() { + return heightUnit; + } + + public OpenType setHeightUnit(SizeUnit heightUnit) { + OpenType instance = getMutableInstance(); + instance.heightUnit = heightUnit; + return instance; + } + + public Float getHeight() { + return height; + } + + /** + * @deprecated Use {@link #height(Float)} instead. + */ + @Deprecated + public OpenType height(Integer height) { + return height(height.floatValue()); + } + + /** + * @deprecated Use {@link #setHeight(Float)} instead. + */ + @Deprecated + public OpenType setHeight(Integer height) { + return setHeight(height.floatValue()); + } + + public OpenType height(Float height) { + OpenType instance = getMutableInstance(); + + instance.height = height; + return instance; + } + + public OpenType setHeight(Float height) { + OpenType instance = getMutableInstance(); + + instance.height = height; + return instance; + } + + public OpenType height(String height) { + return setHeight(height); + } + + public OpenType setHeight(String height) { + OpenType instance = getMutableInstance(); + + SizeWithUnit size = SizeWithUnit.parseStringSize(height); + + instance.height = size.getSize(); + instance.heightUnit = size.getUnit(); + return instance; + } + + public OpenType heightAuto() { + OpenType instance = getMutableInstance(); + + instance.height = -1.0f; + instance.heightUnit = SizeUnit.PIXELS; + return instance; + } + + public SizeUnit getWidthUnit() { + return widthUnit; + } + + public OpenType setWidthUnit(SizeUnit widthUnit) { + OpenType instance = getMutableInstance(); + instance.widthUnit = widthUnit; + return instance; + } + + public Float getWidth() { + return width; + } + + /** + * @deprecated Use {@link #width(Float)} instead. + */ + @Deprecated + public OpenType width(Integer width) { + return width(width.floatValue()); + } + + /** + * @deprecated Use {@link #setWidth(Float)} instead. + */ + @Deprecated + public OpenType setWidth(Integer width) { + return setWidth(width.floatValue()); + } + + public OpenType width(Float width) { + OpenType instance = getMutableInstance(); + + instance.width = width; + return instance; + } + + public OpenType setWidth(Float width) { + OpenType instance = getMutableInstance(); + + instance.width = width; + return instance; + } + + public OpenType width(String width) { + return setWidth(width); + } + + public OpenType setWidth(String width) { + OpenType instance = getMutableInstance(); + + SizeWithUnit size = SizeWithUnit.parseStringSize(width); + + instance.width = size.getSize(); + instance.widthUnit = size.getUnit(); + return instance; + } + + public OpenType widthAuto() { + OpenType instance = getMutableInstance(); + + instance.width = -1.0f; + instance.widthUnit = SizeUnit.PIXELS; + return instance; + } + + public Integer getPositionX() { + return positionX; + } + + public OpenType setPositionX(Integer positionX) { + OpenType instance = getMutableInstance(); + + instance.positionX = positionX; + return instance; + } + + public OpenType positionX(Integer positionX) { + OpenType instance = getMutableInstance(); + + instance.positionX = positionX; + return instance; + } + + public Integer getPositionY() { + return positionY; + } + + public OpenType setPositionY(Integer positionY) { + OpenType instance = getMutableInstance(); + + instance.positionY = positionY; + return instance; + } + + public OpenType positionY(Integer positionY) { + OpenType instance = getMutableInstance(); + + instance.positionY = positionY; + return instance; + } + + public OpenType center() { + OpenType instance = getMutableInstance(); + instance.positionX = null; + instance.positionY = null; + return instance; + } + + public Boolean getResizable() { + return resizable; + } + + public OpenType setResizable(Boolean resizable) { + OpenType instance = getMutableInstance(); + + instance.resizable = resizable; + return instance; + } + + public OpenType resizable(Boolean resizable) { + OpenType instance = getMutableInstance(); + + instance.resizable = resizable; + return instance; + } + + public Boolean getCloseable() { + return closeable; + } + + public OpenType closeable(Boolean closeable) { + OpenType instance = getMutableInstance(); + + instance.closeable = closeable; + return instance; + } + + public OpenType setCloseable(Boolean closeable) { + OpenType instance = getMutableInstance(); + + instance.closeable = closeable; + return instance; + } + + public Boolean getModal() { + return modal; + } + + public OpenType modal(Boolean modal) { + OpenType instance = getMutableInstance(); + + instance.modal = modal; + return instance; + } + + public OpenType setModal(Boolean modal) { + OpenType instance = getMutableInstance(); + + instance.modal = modal; + return instance; + } + + /** + * @return true if a window can be closed by click on outside window area + */ + public Boolean getCloseOnClickOutside() { + return closeOnClickOutside; + } + + /** + * Set closeOnClickOutside to true if a window should be closed by click on outside window area. + * It works when a window has a modal mode. + */ + public OpenType closeOnClickOutside(Boolean closeOnClickOutside) { + OpenType instance = getMutableInstance(); + + instance.closeOnClickOutside = closeOnClickOutside; + return instance; + } + + /** + * Set closeOnClickOutside to true if a window should be closed by click on outside window area. + * It works when a window has a modal mode. + */ + public OpenType setCloseOnClickOutside(Boolean closeOnClickOutside) { + OpenType instance = getMutableInstance(); + + instance.closeOnClickOutside = closeOnClickOutside; + return instance; + } + + /** + * @return true if a window is maximized across the screen. + */ + public Boolean getMaximized() { + return maximized; + } + + /** + * Set maximized to true if a window should be maximized across the screen. + */ + public OpenType maximized(Boolean maximized) { + OpenType instance = getMutableInstance(); + + instance.maximized = maximized; + return instance; + } + + /** + * Set maximized to true if a window should be maximized across the screen. + */ + public OpenType setMaximized(Boolean maximized) { + OpenType instance = getMutableInstance(); + + instance.maximized = maximized; + return instance; + } + + private OpenType getMutableInstance() { + if (!mutable) { + return copy(); + } + + return this; + } + + public static OpenType valueOf(String openTypeString) { + Preconditions.checkNotNullArgument(openTypeString, "openTypeString should not be null"); + + switch (openTypeString) { + case "NEW_TAB": + return NEW_TAB; + + case "THIS_TAB": + return THIS_TAB; + + case "DIALOG": + return DIALOG; + + case "NEW_WINDOW": + return NEW_WINDOW; + + default: + throw new IllegalArgumentException("Unable to parse OpenType"); + } + } + + public OpenType copy() { + OpenType openType = new OpenType(openMode); + + openType.setModal(modal); + openType.setResizable(resizable); + openType.setCloseable(closeable); + openType.setHeight(height); + openType.setHeightUnit(heightUnit); + openType.setWidth(width); + openType.setWidthUnit(widthUnit); + openType.setCloseOnClickOutside(closeOnClickOutside); + openType.setMaximized(maximized); + openType.setPositionX(positionX); + openType.setPositionY(positionY); + + return openType; + } + } + + public enum OpenMode { + /** + * Open a screen in new tab of the main window. + *
In Web Client with {@code AppWindow.Mode.SINGLE} the new screen replaces current screen. + */ + NEW_TAB, + /** + * Open a screen on top of the current tab screens stack. + */ + THIS_TAB, + /** + * Open a screen as modal dialog. + */ + DIALOG, + /** + * In Desktop Client open a screen in new main window, in Web Client the same as new {@link #NEW_TAB} + */ + NEW_WINDOW + } + + public interface WindowCloseListener { + void onWindowClose(Window window, boolean anyOpenWindowExist); + } + + protected DataSupplier defaultDataSupplier; + + protected Messages messages = AppBeans.get(Messages.NAME); + + protected Scripting scripting = AppBeans.get(Scripting.NAME); + + protected Resources resources = AppBeans.get(Resources.NAME); + + protected Security security = AppBeans.get(Security.NAME); + + protected Configuration configuration = AppBeans.get(Configuration.NAME); + + protected BackgroundWorker backgroundWorker = AppBeans.get(BackgroundWorker.NAME); + + protected UserSessionSource userSessionSource = AppBeans.get(UserSessionSource.NAME); + + protected ScreenXmlLoader screenXmlLoader = AppBeans.get(ScreenXmlLoader.NAME); + + protected ScreenViewsLoader screenViewsLoader = AppBeans.get(ScreenViewsLoader.NAME); + + private DialogParams dialogParams; + + protected List listeners = new ArrayList<>(); + + protected WindowManager() { + dialogParams = createDialogParams(); + defaultDataSupplier = new GenericDataSupplier(); + } + + public abstract Collection getOpenWindows(); + + /** + * Select tab with window in main tabsheet. + */ + public abstract void selectWindowTab(Window window); + + /** + * @deprecated Please use {@link Window#setCaption(String)} ()} and {@link Window#setDescription(String)} ()} methods. + */ + @Deprecated + public abstract void setWindowCaption(Window window, String caption, String description); + + protected Integer getHash(WindowInfo windowInfo, Map params) { + return windowInfo.hashCode() + params.hashCode(); + } + + protected Window createWindow(WindowInfo windowInfo, OpenType openType, Map params, + LayoutLoaderConfig layoutConfig, boolean topLevel) { + if (!topLevel) { + checkPermission(windowInfo); + } + + StopWatch loadDescriptorWatch = new Log4JStopWatch(windowInfo.getId() + "#" + + LifeCycle.LOAD, + Logger.getLogger(UIPerformanceLogger.class)); + + Element element = screenXmlLoader.load(windowInfo.getTemplate(), windowInfo.getId(), params); + + preloadMainScreenClass(element);//try to load main screen class to resolve dynamic compilation dependencies issues + + ComponentLoaderContext componentLoaderContext = new ComponentLoaderContext(params); + componentLoaderContext.setFullFrameId(windowInfo.getId()); + componentLoaderContext.setCurrentFrameId(windowInfo.getId()); + + ComponentLoader windowLoader = createLayout(windowInfo, element, componentLoaderContext, layoutConfig); + Window clientSpecificWindow = (Window) windowLoader.getResultComponent(); + Window windowWrapper = wrapByCustomClass(clientSpecificWindow, element); + + screenViewsLoader.deployViews(element); + + DsContext dsContext = loadDsContext(element); + initDatasources(clientSpecificWindow, dsContext, params); + + componentLoaderContext.setDsContext(dsContext); + + WindowContext windowContext = new WindowContextImpl(clientSpecificWindow, openType, params); + clientSpecificWindow.setContext(windowContext); + dsContext.setFrameContext(windowContext); + + //noinspection unchecked + windowLoader.loadComponent(); + + clientSpecificWindow.setWindowManager(this); + + loadDescriptorWatch.stop(); + + initWrapperFrame(windowWrapper, componentLoaderContext, element, params); + + componentLoaderContext.setFrame(windowWrapper); + componentLoaderContext.executePostInitTasks(); + + if (configuration.getConfig(GlobalConfig.class).getTestMode()) { + initDebugIds(clientSpecificWindow); + } + + StopWatch uiPermissionsWatch = new Log4JStopWatch(windowInfo.getId() + "#" + + LifeCycle.UI_PERMISSIONS, + Logger.getLogger(UIPerformanceLogger.class)); + + // apply ui permissions + WindowCreationHelper.applyUiPermissions(clientSpecificWindow); + + uiPermissionsWatch.stop(); + + return windowWrapper; + } + + protected void preloadMainScreenClass(Element element) { + String screenClass = element.attributeValue("class"); + if (!StringUtils.isBlank(screenClass)) { + scripting.loadClass(screenClass); + } + } + + protected void initDebugIds(Frame frame) { + } + + protected void checkPermission(WindowInfo windowInfo) { + boolean permitted = security.isScreenPermitted(windowInfo.getId()); + if (!permitted) { + throw new AccessDeniedException(PermissionType.SCREEN, windowInfo.getId()); + } + } + + protected void initDatasources(Window window, DsContext dsContext, Map params) { + window.setDsContext(dsContext); + + for (Datasource ds : dsContext.getAll()) { + if (Datasource.State.NOT_INITIALIZED.equals(ds.getState()) && ds instanceof DatasourceImplementation) { + ((DatasourceImplementation) ds).initialized(); + } + } + } + + protected ComponentLoader createLayout(WindowInfo windowInfo, Element rootElement, + ComponentLoader.Context context, LayoutLoaderConfig layoutConfig) { + String descriptorPath = windowInfo.getTemplate(); + + LayoutLoader layoutLoader = new LayoutLoader(context, AppConfig.getFactory(), layoutConfig); + layoutLoader.setLocale(getLocale()); + if (!StringUtils.isEmpty(descriptorPath)) { + if (descriptorPath.contains("/")) { + descriptorPath = StringUtils.substring(descriptorPath, 0, descriptorPath.lastIndexOf("/")); + } + + String path = descriptorPath.replaceAll("/", "."); + int start = path.startsWith(".") ? 1 : 0; + path = path.substring(start); + + layoutLoader.setMessagesPack(path); + } + //noinspection UnnecessaryLocalVariable + ComponentLoader windowLoader = layoutLoader.createWindow(rootElement, windowInfo.getId()); + return windowLoader; + } + + protected DsContext loadDsContext(Element element) { + DataSupplier dataSupplier; + + String dataSupplierClass = element.attributeValue("dataSupplier"); + if (StringUtils.isEmpty(dataSupplierClass)) { + dataSupplier = defaultDataSupplier; + } else { + Class aClass = ReflectionHelper.getClass(dataSupplierClass); + try { + dataSupplier = (DataSupplier) aClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Unable to create data supplier for screen", e); + } + } + + //noinspection UnnecessaryLocalVariable + DsContext dsContext = new DsContextLoader(dataSupplier).loadDatasources(element.element("dsContext"), null); + return dsContext; + } + + protected Window createWindow(WindowInfo windowInfo, Map params) { + Window window; + try { + window = (Window) windowInfo.getScreenClass().newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Unable to instantiate window class", e); + } + + window.setId(windowInfo.getId()); + window.setWindowManager(this); + + init(window, params); + + StopWatch uiPermissionsWatch = new Log4JStopWatch(windowInfo.getId() + "#" + + LifeCycle.UI_PERMISSIONS, + Logger.getLogger(UIPerformanceLogger.class)); + + // apply ui permissions + WindowCreationHelper.applyUiPermissions(window); + + uiPermissionsWatch.stop(); + + return window; + } + + protected Window createWindowByScreenClass(WindowInfo windowInfo, Map params) { + Class screenClass = windowInfo.getScreenClass(); + + Class[] paramTypes = ReflectionHelper.getParamTypes(params); + Constructor constructor = null; + try { + constructor = screenClass.getConstructor(paramTypes); + } catch (NoSuchMethodException e) { + // + } + + Object obj; + try { + if (constructor == null) { + obj = screenClass.newInstance(); + } else { + obj = constructor.newInstance(params); + } + } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException("Unable to instantiate window class", e); + } + + if (obj instanceof Callable) { + try { + Callable callable = (Callable) obj; + Window window = (Window) callable.call(); + return window; + } catch (Exception e) { + throw new RuntimeException("Unable to instantiate window class", e); + } + } else if (obj instanceof Runnable) { + ((Runnable) obj).run(); + return null; + } else + throw new IllegalStateException("Screen class must be an instance of Callable or Runnable"); + } + + public boolean windowExist(WindowInfo windowInfo, Map params) { + return (getWindow(getHash(windowInfo, params)) != null); + } + + public Window openWindow(WindowInfo windowInfo, OpenType openType, Map params) { + if (params == null) { + params = Collections.emptyMap(); + } + + checkCanOpenWindow(windowInfo, openType, params); + Integer hashCode = getHash(windowInfo, params); + params = createParametersMap(windowInfo, params); + String template = windowInfo.getTemplate(); + + Window window; + + if (template != null) { + window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getWindowLoaders(), false); + String caption = loadCaption(window, params); + String description = loadDescription(window, params); + if (isOpenAsNewTab(openType)) { + putToWindowMap(window, hashCode); + } + showWindow(window, caption, description, openType, windowInfo.getMultipleOpen()); + userActionsLog.trace("Window {} was opened", windowInfo.getId()); + return window; + } else { + Class screenClass = windowInfo.getScreenClass(); + if (screenClass != null) { + window = createWindowByScreenClass(windowInfo, params); + if (isOpenAsNewTab(openType)) { + putToWindowMap(window, hashCode); + } + userActionsLog.trace("Window {} was opened", windowInfo.getId()); + return window; + } else + return null; + } + } + + protected boolean isOpenAsNewTab(OpenType openType) { + return openType.getOpenMode() == OpenMode.NEW_TAB; + } + + public Window openWindow(WindowInfo windowInfo, OpenType openType) { + return openWindow(windowInfo, openType, Collections.emptyMap()); + } + + protected abstract void putToWindowMap(Window window, Integer hashCode); + + protected abstract Window getWindow(Integer hashCode); + + protected abstract void checkCanOpenWindow(WindowInfo windowInfo, OpenType openType, Map params); + + protected String loadCaption(Window window, Map params) { + String caption = window.getCaption(); + if (!StringUtils.isEmpty(caption)) { + caption = TemplateHelper.processTemplate(caption, params); + } else { + caption = WindowParams.CAPTION.getString(params); + if (StringUtils.isEmpty(caption)) { + String msgPack = window.getMessagesPack(); + if (msgPack != null) { + caption = messages.getMessage(msgPack, "caption"); + if (!"caption".equals(caption)) { + caption = TemplateHelper.processTemplate(caption, params); + } + } + } else { + caption = TemplateHelper.processTemplate(caption, params); + } + } + window.setCaption(caption); + + return caption; + } + + protected String loadDescription(Window window, Map params) { + String description = window.getDescription(); + if (!StringUtils.isEmpty(description)) { + return TemplateHelper.processTemplate(description, params); + } else { + description = WindowParams.DESCRIPTION.getString(params); + if (StringUtils.isEmpty(description)) { + description = null; + } else { + description = TemplateHelper.processTemplate(description, params); + } + } + window.setDescription(description); + + return description; + } + + public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType, + Datasource parentDs) { + return openEditor(windowInfo, item, openType, Collections.emptyMap(), parentDs); + } + + public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType) { + return openEditor(windowInfo, item, openType, Collections.emptyMap()); + } + + public Window.Editor openEditor(WindowInfo windowInfo, Entity item, OpenType openType, Map params) { + return openEditor(windowInfo, item, openType, params, null); + } + + public Window.Editor openEditor(WindowInfo windowInfo, Entity item, + OpenType openType, Map params, + Datasource parentDs) { + if (params == null) { + params = Collections.emptyMap(); + } + + checkCanOpenWindow(windowInfo, openType, params); + + Integer hashCode = getHash(windowInfo, params); + String template = windowInfo.getTemplate(); + + if (openType.getOpenMode() != OpenMode.DIALOG) { + Window existingWindow = getWindow(hashCode); + if (existingWindow != null) { + params = createParametersMap(windowInfo, params); + String caption = loadCaption(existingWindow, params); + String description = loadDescription(existingWindow, params); + + showWindow(existingWindow, caption, description, openType, false); + return (Window.Editor) existingWindow; + } + } + + params = createParametersMap(windowInfo, params); + WindowParams.ITEM.set(params, item instanceof Datasource ? ((Datasource) item).getItem() : item); + + Window window; + if (template != null) { + window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getEditorLoaders(), false); + } else { + Class windowClass = windowInfo.getScreenClass(); + if (windowClass != null) { + window = createWindow(windowInfo, params); + if (!(window instanceof Window.Editor)) { + throw new IllegalStateException( + String.format("Class %s does't implement Window.Editor interface", windowClass)); + } + } else { + throw new IllegalStateException("Invalid WindowInfo: " + windowInfo); + } + } + ((Window.Editor) window).setParentDs(parentDs); + + StopWatch setItemWatch = new Log4JStopWatch(windowInfo.getId() + "#" + + LifeCycle.SET_ITEM, + Logger.getLogger(UIPerformanceLogger.class)); + + ((Window.Editor) window).setItem(item); + + setItemWatch.stop(); + + String caption = loadCaption(window, params); + String description = loadDescription(window, params); + showWindow(window, caption, description, openType, false); + + userActionsLog.trace("Editor {} was opened", windowInfo.getId()); + + return (Window.Editor) window; + } + + public Window.Lookup openLookup(WindowInfo windowInfo, Window.Lookup.Handler handler, + OpenType openType, Map params) { + if (params == null) { + params = Collections.emptyMap(); + } + + checkCanOpenWindow(windowInfo, openType, params); + + params = createParametersMap(windowInfo, params); + + String template = windowInfo.getTemplate(); + Window window; + + if (template != null) { + window = createWindow(windowInfo, openType, params, LayoutLoaderConfig.getLookupLoaders(), false); + + ((Window.Lookup) window).initLookupLayout(); + + Element element = ((Component.HasXmlDescriptor) window).getXmlDescriptor(); + String lookupComponent = element.attributeValue("lookupComponent"); + if (!StringUtils.isEmpty(lookupComponent)) { + Component component = window.getComponent(lookupComponent); + ((Window.Lookup) window).setLookupComponent(component); + } + } else { + Class windowClass = windowInfo.getScreenClass(); + if (windowClass != null) { + window = createWindow(windowInfo, params); + if (!(window instanceof Window.Lookup)) { + throw new IllegalStateException( + String.format("Class %s does't implement Window.Lookup interface", windowClass)); + } + } else { + throw new IllegalStateException("Invalid WindowInfo: " + windowInfo); + } + } + + ((Window.Lookup) window).setLookupHandler(handler); + + String caption = loadCaption(window, params); + String description = loadDescription(window, params); + + showWindow(window, caption, description, openType, false); + + userActionsLog.trace("Lookup {} was opened", windowInfo.getId()); + + return (Window.Lookup) window; + } + + public Window.Lookup openLookup(WindowInfo windowInfo, Window.Lookup.Handler handler, OpenType openType) { + return openLookup(windowInfo, handler, openType, Collections.emptyMap()); + } + + public Frame openFrame(Frame parentFrame, Component parent, WindowInfo windowInfo) { + return openFrame(parentFrame, parent, windowInfo, Collections.emptyMap()); + } + + public Frame openFrame(Frame parentFrame, Component parent, WindowInfo windowInfo, Map params) { + return openFrame(parentFrame, parent, null, windowInfo, params); + } + + public Frame openFrame(Frame parentFrame, Component parent, @Nullable String id, + WindowInfo windowInfo, Map params) { + if (params == null) { + params = Collections.emptyMap(); + } + + // Parameters can be useful later + params = createParametersMap(windowInfo, params); + + String src = windowInfo.getTemplate(); + + ComponentLoaderContext context = new ComponentLoaderContext(params); + context.setDsContext(parentFrame.getDsContext()); + context.setFullFrameId(windowInfo.getId()); + context.setCurrentFrameId(windowInfo.getId()); + + LayoutLoader loader = new LayoutLoader(context, AppConfig.getFactory(), LayoutLoaderConfig.getFrameLoaders()); + loader.setLocale(getLocale()); + loader.setMessagesPack(parentFrame.getMessagesPack()); + + StopWatch loadDescriptorWatch = new Log4JStopWatch(windowInfo.getId() + "#" + + LifeCycle.LOAD, + Logger.getLogger(UIPerformanceLogger.class)); + + Frame component; + String frameId = id != null ? id : windowInfo.getId(); + + Pair loaderElementPair = loader.createFrameComponent(src, frameId, context.getParams()); + component = (Frame) loaderElementPair.getFirst().getResultComponent(); + + if (parent != null) { + showFrame(parent, component); + } else { + component.setFrame(parentFrame); + } + + loaderElementPair.getFirst().loadComponent(); + + if (component.getMessagesPack() == null) { + component.setMessagesPack(parentFrame.getMessagesPack()); + } + + context.executeInjectTasks(); + context.setFrame(component); + context.executePostWrapTasks(); + + // init of frame + context.executeInitTasks(); + + context.executePostInitTasks(); + + loadDescriptorWatch.stop(); + + initDebugIds(component); + + userActionsLog.trace("Frame {} was opened", windowInfo.getId()); + + return component; + } + + protected Map createParametersMap(WindowInfo windowInfo, Map params) { + Map map = new HashMap<>(params.size()); + + Element element = windowInfo.getDescriptor(); + if (element != null) { + Element paramsElement = element.element("params") != null ? element.element("params") : element; + if (paramsElement != null) { + @SuppressWarnings({"unchecked"}) + List paramElements = paramsElement.elements("param"); + for (Element paramElement : paramElements) { + String name = paramElement.attributeValue("name"); + String value = paramElement.attributeValue("value"); + if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) { + Boolean booleanValue = Boolean.valueOf(value); + map.put(name, booleanValue); + } else { + map.put(name, value); + } + } + } + } + map.putAll(params); + + return map; + } + + @Deprecated + protected DialogParams createDialogParams() { + return new DialogParams(); + } + + @Deprecated + public DialogParams getDialogParams() { + return dialogParams; + } + + protected void fireListeners(Window window, boolean anyOpenWindowExist) { + for (WindowCloseListener wcl : listeners) { + wcl.onWindowClose(window, anyOpenWindowExist); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + protected abstract void showWindow(Window window, String caption, OpenType openType, boolean multipleOpen); + + protected abstract void showWindow(Window window, String caption, String description, OpenType openType, boolean multipleOpen); + + protected abstract void showFrame(Component parent, Frame frame); + + @Deprecated + protected void copyDialogParamsToOpenType(OpenType mutableOpenType) { + DialogParams dialogParams = getDialogParams(); + if (dialogParams.getCloseable() != null && mutableOpenType.getCloseable() == null) { + mutableOpenType.closeable(dialogParams.getCloseable()); + } + if (dialogParams.getModal() != null && mutableOpenType.getModal() == null) { + mutableOpenType.setModal(dialogParams.getModal()); + } + if (dialogParams.getResizable() != null && mutableOpenType.getResizable() == null) { + mutableOpenType.setResizable(dialogParams.getResizable()); + } + if (dialogParams.getWidth() != null && mutableOpenType.getWidth() == null) { + mutableOpenType.setWidth(dialogParams.getWidth()); + } + if (dialogParams.getWidthUnit() != null && mutableOpenType.getWidthUnit() == null) { + mutableOpenType.setWidthUnit(dialogParams.getWidthUnit()); + } + if (dialogParams.getHeight() != null && mutableOpenType.getHeight() == null) { + mutableOpenType.setHeight(dialogParams.getHeight()); + } + if (dialogParams.getHeightUnit() != null && mutableOpenType.getHeightUnit() == null) { + mutableOpenType.setHeightUnit(dialogParams.getHeightUnit()); + } + } + + protected OpenType overrideOpenTypeParams(OpenType mutableOpenType, DialogOptions dialogOptions) { + if (BooleanUtils.isTrue(dialogOptions.getForceDialog())) { + mutableOpenType.setOpenMode(OpenMode.DIALOG); + } + + if (dialogOptions.getHeight() != null) { + mutableOpenType.setHeight(dialogOptions.getHeight()); + } + + if (dialogOptions.getHeightUnit() != null) { + mutableOpenType.setHeightUnit(dialogOptions.getHeightUnit()); + } + + if (dialogOptions.getWidth() != null) { + mutableOpenType.setWidth(dialogOptions.getWidth()); + } + + if (dialogOptions.getWidthUnit() != null) { + mutableOpenType.setWidthUnit(dialogOptions.getWidthUnit()); + } + + if (dialogOptions.getResizable() != null) { + mutableOpenType.setResizable(dialogOptions.getResizable()); + } + + if (dialogOptions.getCloseable() != null) { + mutableOpenType.setCloseable(dialogOptions.getCloseable()); + } + + if (dialogOptions.getModal() != null) { + mutableOpenType.setModal(dialogOptions.getModal()); + } + + if(dialogOptions.getCloseOnClickOutside() != null){ + mutableOpenType.setCloseOnClickOutside(dialogOptions.getCloseOnClickOutside()); + } + + if (dialogOptions.getMaximized() != null) { + mutableOpenType.setMaximized(dialogOptions.getMaximized()); + } + + if (dialogOptions.getPositionX() != null) { + mutableOpenType.setPositionX(dialogOptions.getPositionX()); + } + + if (dialogOptions.getPositionY() != null) { + mutableOpenType.setPositionY(dialogOptions.getPositionY()); + } + + return mutableOpenType; + } + + protected Settings getSettingsImpl(String id) { + return new SettingsImpl(id); + } + + protected void afterShowWindow(Window window) { + if (!WindowParams.DISABLE_APPLY_SETTINGS.getBool(window.getContext())) { + window.applySettings(getSettingsImpl(window.getId())); + } + if (!WindowParams.DISABLE_RESUME_SUSPENDED.getBool(window.getContext())) { + ((DsContextImplementation) window.getDsContext()).resumeSuspended(); + } + + if (window instanceof AbstractWindow) { + AbstractWindow abstractWindow = (AbstractWindow) window; + + if (abstractWindow.isAttributeAccessControlEnabled()) { + AttributeAccessSupport attributeAccessSupport = AppBeans.get(AttributeAccessSupport.NAME); + attributeAccessSupport.applyAttributeAccess(abstractWindow, false); + } + + StopWatch readyStopWatch = new Log4JStopWatch(window.getId() + "#" + + LifeCycle.READY, + Logger.getLogger(UIPerformanceLogger.class)); + + abstractWindow.ready(); + + readyStopWatch.stop(); + } + } + + public abstract void close(Window window); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + protected Locale getLocale() { + return userSessionSource.getUserSession().getLocale(); + } + + protected Window wrapByCustomClass(Frame window, Element element) { + String screenClass = element.attributeValue("class"); + if (StringUtils.isBlank(screenClass)) { + throw new GuiDevelopmentException("'class' attribute is not defined in XML descriptor", window.getId()); + } + + Class aClass = scripting.loadClass(screenClass); + if (aClass == null) { + throw new GuiDevelopmentException("Unable to load controller class", window.getId()); + } + //noinspection UnnecessaryLocalVariable + Window wrappingWindow = ((WrappedWindow) window).wrapBy(aClass); + return wrappingWindow; + } + + protected void initWrapperFrame(Window wrappingWindow, ComponentLoaderContext context, Element element, + Map params) { + if (wrappingWindow instanceof AbstractWindow) { + Element companionsElem = element.element("companions"); + if (companionsElem != null) { + StopWatch companionStopWatch = new Log4JStopWatch(wrappingWindow.getId() + "#" + + LifeCycle.COMPANION, + Logger.getLogger(UIPerformanceLogger.class)); + + initCompanion(companionsElem, (AbstractWindow) wrappingWindow); + + companionStopWatch.stop(); + } + } + + StopWatch injectStopWatch = new Log4JStopWatch(wrappingWindow.getId() + "#" + + LifeCycle.INJECTION, + Logger.getLogger(UIPerformanceLogger.class)); + + ControllerDependencyInjector dependencyInjector = new ControllerDependencyInjector(wrappingWindow, params); + dependencyInjector.inject(); + + injectStopWatch.stop(); + + context.executeInjectTasks(); + context.executePostWrapTasks(); + + init(wrappingWindow, params); + + context.executeInitTasks(); + } + + protected void init(Window window, Map params) { + if (window instanceof AbstractWindow) { + StopWatch initStopWatch = new Log4JStopWatch(window.getId() + + "#" + LifeCycle.INIT, + Logger.getLogger(UIPerformanceLogger.class)); + + ((AbstractWindow) window).init(params); + + initStopWatch.stop(); + } + } + + protected void initCompanion(Element companionsElem, AbstractWindow window) { + Element element = companionsElem.element(AppConfig.getClientType().toString().toLowerCase()); + if (element != null) { + String className = element.attributeValue("class"); + if (!StringUtils.isBlank(className)) { + Class aClass = scripting.loadClassNN(className); + Object companion; + try { + companion = aClass.newInstance(); + window.setCompanion(companion); + + CompanionDependencyInjector cdi = new CompanionDependencyInjector(window, companion); + cdi.inject(); + } catch (Exception e) { + throw new RuntimeException("Unable to init Companion", e); + } + } + } + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Show notification with {@link Frame.NotificationType#HUMANIZED}.
+ * Supports line breaks ({@code \n}). + * + * @param caption text + */ + public abstract void showNotification(String caption); + + /** + * Show notification.
+ * Supports line breaks ({@code \n}). + * + * @param caption text + * @param type defines how to display the notification. + * Don't forget to escape data from the database in case of {@code *_HTML} types! + */ + public abstract void showNotification(String caption, Frame.NotificationType type); + + /** + * Show notification with caption description.
+ * Supports line breaks ({@code \n}). + * + * @param caption caption + * @param description text + * @param type defines how to display the notification. + * Don't forget to escape data from the database in case of {@code *_HTML} types! + */ + public abstract void showNotification(String caption, String description, Frame.NotificationType type); + + /** + * Show message dialog with title and message.
+ * Supports line breaks ({@code \n}) for non HTML messageType. + * + * @param title dialog title + * @param message text + * @param messageType defines how to display the dialog. + * Don't forget to escape data from the database in case of {@code *_HTML} types! + */ + public abstract void showMessageDialog(String title, String message, Frame.MessageType messageType); + + /** + * Show options dialog with title and message.
+ * Supports line breaks ({@code \n}) for non HTML messageType. + * + * @param title dialog title + * @param message text + * @param messageType defines how to display the dialog. + * Don't forget to escape data from the database in case of {@code *_HTML} types! + * @param actions available actions + */ + public abstract void showOptionDialog(String title, String message, Frame.MessageType messageType, Action[] actions); + + /** + * Shows exception dialog with default caption, message and displays stacktrace of given throwable. + * + * @param throwable throwable + */ + public abstract void showExceptionDialog(Throwable throwable); + + /** + * Shows exception dialog with given caption, message and displays stacktrace of given throwable. + * + * @param throwable throwable + * @param caption dialog caption + * @param message dialog message + */ + public abstract void showExceptionDialog(Throwable throwable, @Nullable String caption, @Nullable String message); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Open a web page in browser. + * @param url URL of the page + * @param params optional parameters. + *
The following parameters are recognized by Web client: + *
    + *
  • {@code target} - String value used as the target name in a + * window.open call in the client. This means that special values such as + * "_blank", "_self", "_top", "_parent" have special meaning. If not specified, "_blank" is used.
  • + *
  • {@code width} - Integer value specifying the width of the browser window in pixels
  • + *
  • {@code height} - Integer value specifying the height of the browser window in pixels
  • + *
  • {@code border} - String value specifying the border style of the window of the browser window. + * Possible values are "DEFAULT", "MINIMAL", "NONE".
  • + *
+ * Desktop client doesn't support any parameters and just ignores them. + */ + public abstract void showWebPage(String url, @Nullable Map params); } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/WindowParam.java b/modules/gui/src/com/haulmont/cuba/gui/WindowParam.java index a89d377db0..c41b1fb17b 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/WindowParam.java +++ b/modules/gui/src/com/haulmont/cuba/gui/WindowParam.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Identifies injectable fields in screen controllers, value for field comes from screen parameters - * - */ -@Target(value = ElementType.FIELD) -@Retention(RUNTIME) -public @interface WindowParam { - String name() default ""; - boolean required() default false; -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Identifies injectable fields in screen controllers, value for field comes from screen parameters + * + */ +@Target(value = ElementType.FIELD) +@Retention(RUNTIME) +public @interface WindowParam { + String name() default ""; + boolean required() default false; +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/LinkColumnHelper.java b/modules/gui/src/com/haulmont/cuba/gui/app/LinkColumnHelper.java index d2ecdfa263..0abb8c1eff 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/LinkColumnHelper.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/LinkColumnHelper.java @@ -1,88 +1,88 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.haulmont.cuba.gui.app; - -import com.haulmont.chile.core.datatypes.Datatype; -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.Instance; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.UserSessionSource; -import com.haulmont.cuba.gui.components.AbstractAction; -import com.haulmont.cuba.gui.components.Button; -import com.haulmont.cuba.gui.components.Component; -import com.haulmont.cuba.gui.components.Table; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; - -public class LinkColumnHelper { - - public interface Handler { - void onClick(Entity entity); - } - - public static void initColumn(Table table, final String propertyName, final Handler handler) { - - final ComponentsFactory componentsFactory = AppBeans.get(ComponentsFactory.NAME); - - table.addGeneratedColumn(propertyName, new Table.ColumnGenerator() { - @Override - public Component generateCell(final Entity entity) { -// //process properties like building.house.room - String[] props = propertyName.split("\\."); - Instance nestedEntity = entity; - for (int i = 0; i < props.length - 1; i++) { - nestedEntity = nestedEntity.getValue(props[i]); - if (nestedEntity == null) { - break; - } - } - final Object value = (nestedEntity == null) ? null : nestedEntity.getValue(props[props.length - 1]); - if (value != null) { - Button button = componentsFactory.createComponent(Button.class); - button.setStyleName("link"); - button.setAction(new AbstractAction("open") { - @Override - public void actionPerform(Component component) { - handler.onClick(entity); - } - - @Override - public String getCaption() { - String str; - Datatype datatype = Datatypes.get(value.getClass()); - if (datatype != null) { - UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); - str = datatype.format(value, sessionSource.getLocale()); - } else { - str = value.toString(); - } - return str; - } - }); - - button.setStyleName("link"); - return button; - } - return null; - } - }); - } - - public static void removeColumn(Table table, final String propertyName) { - table.removeGeneratedColumn(propertyName); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.haulmont.cuba.gui.app; + +import com.haulmont.chile.core.datatypes.Datatype; +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.Instance; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.UserSessionSource; +import com.haulmont.cuba.gui.components.AbstractAction; +import com.haulmont.cuba.gui.components.Button; +import com.haulmont.cuba.gui.components.Component; +import com.haulmont.cuba.gui.components.Table; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; + +public class LinkColumnHelper { + + public interface Handler { + void onClick(Entity entity); + } + + public static void initColumn(Table table, final String propertyName, final Handler handler) { + + final ComponentsFactory componentsFactory = AppBeans.get(ComponentsFactory.NAME); + + table.addGeneratedColumn(propertyName, new Table.ColumnGenerator() { + @Override + public Component generateCell(final Entity entity) { +// //process properties like building.house.room + String[] props = propertyName.split("\\."); + Instance nestedEntity = entity; + for (int i = 0; i < props.length - 1; i++) { + nestedEntity = nestedEntity.getValue(props[i]); + if (nestedEntity == null) { + break; + } + } + final Object value = (nestedEntity == null) ? null : nestedEntity.getValue(props[props.length - 1]); + if (value != null) { + Button button = componentsFactory.createComponent(Button.class); + button.setStyleName("link"); + button.setAction(new AbstractAction("open") { + @Override + public void actionPerform(Component component) { + handler.onClick(entity); + } + + @Override + public String getCaption() { + String str; + Datatype datatype = Datatypes.get(value.getClass()); + if (datatype != null) { + UserSessionSource sessionSource = AppBeans.get(UserSessionSource.NAME); + str = datatype.format(value, sessionSource.getLocale()); + } else { + str = value.toString(); + } + return str; + } + }); + + button.setStyleName("link"); + return button; + } + return null; + } + }); + } + + public static void removeColumn(Table table, final String propertyName) { + table.removeGeneratedColumn(propertyName); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/AttributeEditor.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/AttributeEditor.java index 1c9bc9c663..0120d84b01 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/AttributeEditor.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/AttributeEditor.java @@ -1,645 +1,645 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.categories; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.base.Strings; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import com.haulmont.bali.util.Dom4j; -import com.haulmont.bali.util.ParamsMap; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.HasUuid; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.core.global.filter.SecurityJpqlGenerator; -import com.haulmont.cuba.gui.ScreensHelper; -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.actions.BaseAction; -import com.haulmont.cuba.gui.components.actions.RemoveAction; -import com.haulmont.cuba.gui.components.autocomplete.JpqlSuggestionFactory; -import com.haulmont.cuba.gui.components.autocomplete.Suggestion; -import com.haulmont.cuba.gui.components.filter.ConditionsTree; -import com.haulmont.cuba.gui.components.filter.FakeFilterSupport; -import com.haulmont.cuba.gui.components.filter.FilterParser; -import com.haulmont.cuba.gui.components.filter.Param; -import com.haulmont.cuba.gui.components.filter.edit.FilterEditor; -import com.haulmont.cuba.gui.data.CollectionDatasource; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.AbstractDatasource; -import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; -import com.haulmont.cuba.gui.dynamicattributes.DynamicAttributesGuiTools; -import com.haulmont.cuba.gui.theme.ThemeConstants; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; -import com.haulmont.cuba.security.entity.FilterEntity; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.dom4j.Element; - -import javax.inject.Inject; -import java.util.*; - -import static java.lang.String.format; - -/** - * Class that encapsulates editing of {@link CategoryAttribute} entities. - *

- */ -public class AttributeEditor extends AbstractEditor { - protected static final Multimap FIELDS_VISIBLE_FOR_DATATYPES = ArrayListMultimap.create(); - protected static final Set ALWAYS_VISIBLE_FIELDS = Sets.newHashSet("name", "code", "required", "dataType"); - protected static final String WHERE = " where "; - - static { - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.BOOLEAN, "defaultBoolean"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "defaultString"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "rowsCount"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "isCollection"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "defaultDouble"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "isCollection"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "defaultInt"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "isCollection"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "defaultDate"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "defaultDateIsCurrent"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "isCollection"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "enumeration"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "defaultString"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "entityClass"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "screen"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "lookup"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "defaultEntityId"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "width"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "joinClause"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "whereClause"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "constraintWizard"); - FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "isCollection"); - } - - protected CategoryAttribute attribute; - - @Inject - protected FieldGroup attributeFieldGroup; - protected LookupField dataTypeField; - protected LookupField screenField; - protected LookupField entityTypeField; - protected PickerField defaultEntityField; - protected PickerField.LookupAction entityLookupAction; - protected String fieldWidth; - - @Inject - protected Datasource attributeDs; - - @Inject - protected ComponentsFactory factory; - - @Inject - protected Metadata metadata; - - @Inject - protected MetadataTools metadataTools; - - @Inject - protected MessageTools messageTools; - - @Inject - protected DatatypeFormatter datatypeFormatter; - - @Inject - protected ThemeConstants themeConstants; - - @Inject - protected ScreensHelper screensHelper; - - @Inject - protected ComponentsFactory componentsFactory; - - @Inject - protected DynamicAttributesGuiTools dynamicAttributesGuiTools; - - @Inject - protected DataManager dataManager; - - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - - @Inject - protected Table targetScreensTable; - - @Inject - protected TabSheet tabsheet; - - @Inject - protected CollectionDatasource screensDs; - - @Inject - protected GlobalConfig globalConfig; - - protected LocalizedNameFrame localizedFrame; - - private ListEditor enumerationListEditor; - private SourceCodeEditor joinField; - private SourceCodeEditor whereField; - - @Override - public void init(Map params) { - getDialogOptions().setWidth(themeConstants.get("cuba.gui.AttributeEditor.width")); - - fieldWidth = themeConstants.get("cuba.gui.AttributeEditor.field.width"); - - initLocalizedFrame(); - initFieldGroup(); - - targetScreensTable.addAction(new AbstractAction("create") { - @Override - public void actionPerform(Component component) { - screensDs.addItem(new ScreenAndComponent()); - } - }); - targetScreensTable.addAction(new RemoveAction(targetScreensTable)); - } - - protected void initLocalizedFrame() { - if (globalConfig.getAvailableLocales().size() > 1) { - tabsheet.getTab("localization").setVisible(true); - localizedFrame = (LocalizedNameFrame) openFrame( - tabsheet.getTabComponent("localization"), "localizedNameFrame"); - localizedFrame.setWidth("100%"); - localizedFrame.setHeight("250px"); - } - } - - protected void initFieldGroup() { - attributeFieldGroup.addCustomField("defaultBoolean", new FieldGroup.CustomFieldGenerator() { - @Override - public Component generateField(Datasource datasource, String propertyId) { - LookupField lookupField = factory.createComponent(LookupField.class); - Map options = new TreeMap<>(); - options.put(datatypeFormatter.formatBoolean(true), true); - options.put(datatypeFormatter.formatBoolean(false), false); - lookupField.setOptionsMap(options); - lookupField.setDatasource(attributeDs, "defaultBoolean"); - return lookupField; - } - }); - - attributeFieldGroup.addCustomField("dataType", new FieldGroup.CustomFieldGenerator() { - @Override - public Component generateField(Datasource datasource, String propertyId) { - dataTypeField = factory.createComponent(LookupField.class); - Map options = new TreeMap<>(); - PropertyType[] types = PropertyType.values(); - for (PropertyType propertyType : types) { - options.put(getMessage(propertyType.toString()), propertyType); - } - dataTypeField.setWidth(fieldWidth); - - dataTypeField.setNewOptionAllowed(false); - dataTypeField.setRequired(true); - dataTypeField.setRequiredMessage(getMessage("dataTypeRequired")); - dataTypeField.setOptionsMap(options); - dataTypeField.setCaption(getMessage("dataType")); - dataTypeField.setFrame(frame); - dataTypeField.setDatasource(datasource, propertyId); - - return dataTypeField; - } - }); - - attributeFieldGroup.addCustomField("screen", new FieldGroup.CustomFieldGenerator() { - @Override - public Component generateField(Datasource datasource, String propertyId) { - screenField = factory.createComponent(LookupField.class); - screenField.setId("screenField"); - screenField.setCaption(getMessage("screen")); - screenField.setWidth(fieldWidth); - screenField.setRequired(true); - screenField.setRequiredMessage(getMessage("entityScreenRequired")); - screenField.setFrame(frame); - screenField.setDatasource(datasource, propertyId); - - return screenField; - } - }); - - attributeFieldGroup.addCustomField("entityClass", new FieldGroup.CustomFieldGenerator() { - @Override - public Component generateField(Datasource datasource, String propertyId) { - entityTypeField = factory.createComponent(LookupField.class); - entityTypeField.setId("entityClass"); - entityTypeField.setCaption(getMessage("entityType")); - entityTypeField.setRequired(true); - entityTypeField.setRequiredMessage(getMessage("entityTypeRequired")); - entityTypeField.setWidth(fieldWidth); - entityTypeField.setFrame(frame); - Map options = new TreeMap<>(); - MetaClass entityType = null; - for (MetaClass metaClass : metadataTools.getAllPersistentMetaClasses()) { - if (!metadataTools.isSystemLevel(metaClass)) { - if (metadata.getTools().hasCompositePrimaryKey(metaClass) && !HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { - continue; - } - options.put(messageTools.getDetailedEntityCaption(metaClass), metaClass.getJavaClass().getName()); - if (attribute != null && metaClass.getJavaClass().getName().equals(attribute.getEntityClass())) { - entityType = metaClass; - } - } - } - entityTypeField.setOptionsMap(options); - entityTypeField.setValue(entityType); - entityTypeField.setDatasource(datasource, propertyId); - - return entityTypeField; - } - }); - - attributeFieldGroup.addCustomField("defaultEntityId", (datasource, propertyId) -> { - defaultEntityField = factory.createComponent(PickerField.class); - defaultEntityField.setCaption(messages.getMessage(CategoryAttribute.class, "CategoryAttribute.defaultEntityId")); - defaultEntityField.addValueChangeListener(e -> { - Entity entity = (Entity) e.getValue(); - if (entity != null) { - attribute.setObjectDefaultEntityId(referenceToEntitySupport.getReferenceId(entity)); - } else { - attribute.setObjectDefaultEntityId(null); - } - ((AbstractDatasource) attributeDs).modified(attribute); - }); - entityLookupAction = defaultEntityField.addLookupAction(); - defaultEntityField.addClearAction(); - - return defaultEntityField; - }); - - attributeFieldGroup.addCustomField("enumeration", (datasource, propertyId) -> { - enumerationListEditor = factory.createComponent(ListEditor.class); - enumerationListEditor.setWidth("100%"); - enumerationListEditor.setItemType(ListEditor.ItemType.STRING); - enumerationListEditor.setRequired(true); - enumerationListEditor.setRequiredMessage(getMessage("enumRequired")); - enumerationListEditor.addValueChangeListener(e -> { - List value = (List) e.getValue(); - attribute.setEnumeration(Joiner.on(",").join(value)); - }); - if (localizedFrame != null) { - enumerationListEditor.setEditorWindowId("localizedEnumerationWindow"); - enumerationListEditor.setEditorParamsSupplier(() -> - ParamsMap.of("enumerationLocales", attribute.getEnumerationLocales())); - enumerationListEditor.addEditorCloseListener(closeEvent -> { - if (closeEvent.getActionId().equals(COMMIT_ACTION_ID)) { - LocalizedEnumerationWindow enumerationWindow = (LocalizedEnumerationWindow) closeEvent.getWindow(); - attribute.setEnumerationLocales(enumerationWindow.getLocalizedValues()); - } - }); - } - return enumerationListEditor; - }); - - attributeFieldGroup.addCustomField("whereClause", (datasource, propertyId) -> { - whereField = factory.createComponent(SourceCodeEditor.class); - whereField.setDatasource(attributeDs, "whereClause"); - whereField.setWidth("100%"); - whereField.setHeight(themeConstants.get("cuba.gui.customConditionFrame.whereField.height")); - whereField.setSuggester((source, text, cursorPosition) -> requestHint(whereField, text, cursorPosition)); - whereField.setHighlightActiveLine(false); - whereField.setShowGutter(false); - return whereField; - }); - - attributeFieldGroup.addCustomField("joinClause", (datasource, propertyId) -> { - joinField = factory.createComponent(SourceCodeEditor.class); - joinField.setDatasource(attributeDs, "joinClause"); - joinField.setWidth("100%"); - joinField.setHeight(themeConstants.get("cuba.gui.customConditionFrame.joinField.height")); - joinField.setSuggester((source, text, cursorPosition) -> requestHint(joinField, text, cursorPosition)); - joinField.setHighlightActiveLine(false); - joinField.setShowGutter(false); - return joinField; - }); - - attributeFieldGroup.addCustomField("constraintWizard", (datasource, propertyId) -> { - HBoxLayout hbox = factory.createComponent(HBoxLayout.class); - hbox.setWidth("100%"); - LinkButton linkButton = factory.createComponent(LinkButton.class); - linkButton.setAction(new BaseAction("constraintWizard") - .withHandler(event -> - openConstraintWizard() - )); - - linkButton.setCaption(getMessage("constraintWizard")); - linkButton.setAlignment(Alignment.MIDDLE_LEFT); - hbox.add(linkButton); - return hbox; - }); - - attributeDs.addItemPropertyChangeListener(e -> { - String property = e.getProperty(); - CategoryAttribute attribute = getItem(); - if ("dataType".equalsIgnoreCase(property) - || "lookup".equalsIgnoreCase(property) - || "defaultDateIsCurrent".equalsIgnoreCase(property) - || "entityClass".equalsIgnoreCase(property)) { - setupVisibility(); - } - if ("name".equalsIgnoreCase(property)) { - fillAttributeCode(); - } - if ("screen".equalsIgnoreCase(property) || "joinClause".equals(property) || "whereClause".equals(property)) { - dynamicAttributesGuiTools.initEntityPickerField(defaultEntityField, attribute); - } - }); - } - - public void openConstraintWizard() { - Class entityClass = attribute.getJavaClassForEntity(); - if (entityClass == null) { - showNotification(getMessage("selectEntityType")); - return; - } - MetaClass metaClass = metadata.getClassNN(entityClass); - FakeFilterSupport fakeFilterSupport = new FakeFilterSupport(this, metaClass); - - final Filter fakeFilter = fakeFilterSupport.createFakeFilter(); - final FilterEntity filterEntity = fakeFilterSupport.createFakeFilterEntity(attribute.getFilterXml()); - final ConditionsTree conditionsTree = fakeFilterSupport.createFakeConditionsTree(fakeFilter, filterEntity); - - Map params = new HashMap<>(); - params.put("filter", fakeFilter); - params.put("filterEntity", filterEntity); - params.put("conditions", conditionsTree); - params.put("useShortConditionForm", true); - - FilterEditor filterEditor = (FilterEditor) openWindow("filterEditor", WindowManager.OpenType.DIALOG, params); - filterEditor.addCloseListener(actionId -> { - if (!COMMIT_ACTION_ID.equals(actionId)) return; - FilterParser filterParser1 = AppBeans.get(FilterParser.class); - filterEntity.setXml(filterParser1.getXml(filterEditor.getConditions(), Param.ValueProperty.DEFAULT_VALUE)); - if (filterEntity.getXml() != null) { - Element element = Dom4j.readDocument(filterEntity.getXml()).getRootElement(); - com.haulmont.cuba.core.global.filter.FilterParser filterParser = new com.haulmont.cuba.core.global.filter.FilterParser(element); - String jpql = new SecurityJpqlGenerator().generateJpql(filterParser.getRoot()); - attribute.setWhereClause(jpql); - Set joins = filterParser.getRoot().getJoins(); - if (!joins.isEmpty()) { - String joinsStr = new StrBuilder().appendWithSeparators(joins, " ").toString(); - attribute.setJoinClause(joinsStr); - } - attribute.setFilterXml(filterEntity.getXml()); - } - }); - } - - private void setupVisibility() { - for (FieldGroup.FieldConfig fieldConfig : attributeFieldGroup.getFields()) { - if (!ALWAYS_VISIBLE_FIELDS.contains(fieldConfig.getId())) { - attributeFieldGroup.setVisible(fieldConfig.getId(), false); - } - } - - Collection componentIds = FIELDS_VISIBLE_FOR_DATATYPES.get(attribute.getDataType()); - if (componentIds != null) { - for (String componentId : componentIds) { - attributeFieldGroup.setVisible(componentId, true); - } - } - - if (attribute.getDataType() == PropertyType.ENTITY) { - if (StringUtils.isNotBlank(attribute.getEntityClass())) { - defaultEntityField.setEditable(true); - whereField.setEnabled(true); - joinField.setEnabled(true); - Class entityClass = attribute.getJavaClassForEntity(); - MetaClass metaClass = metadata.getClass(entityClass); - defaultEntityField.setMetaClass(metaClass); - fillDefaultEntities(entityClass); - fillSelectEntityScreens(entityClass); - - dynamicAttributesGuiTools.initEntityPickerField(defaultEntityField, attribute); - } else { - defaultEntityField.setEditable(false); - whereField.setEnabled(false); - joinField.setEnabled(false); - } - - if (Boolean.TRUE.equals(attribute.getLookup())) { - attributeFieldGroup.setVisible("screen", false); - } else { - attributeFieldGroup.setVisible("screen", true); - } - - getDialogOptions().center(); - } - - if (attribute.getDataType() == PropertyType.DATE) { - if (Boolean.TRUE.equals(attribute.getDefaultDateIsCurrent())) { - attributeFieldGroup.setVisible("defaultDate", false); - attributeFieldGroup.setFieldValue("defaultDate", null); - } else { - attributeFieldGroup.setVisible("defaultDate", true); - } - } - - if (attribute.getDataType() == PropertyType.BOOLEAN || - attribute.getDataType() == PropertyType.ENUMERATION) { - attributeFieldGroup.setFieldValue("isCollection", null); - } - } - - protected void fillSelectEntityScreens(Class entityClass) { - String value = attribute.getScreen(); - Map screensMap = screensHelper.getAvailableBrowserScreens(entityClass); - screenField.setValue(null); // While #PL-4731 unfixed - screenField.setOptionsMap(screensMap); - screenField.setValue(screensMap.containsValue(value) ? value : null); - } - - @SuppressWarnings("unchecked") - protected void fillDefaultEntities(Class entityClass) { - MetaClass metaClass = metadata.getClassNN(entityClass); - if (attribute.getObjectDefaultEntityId() != null) { - LoadContext lc = new LoadContext<>(entityClass).setView(View.MINIMAL); - String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); - lc.setQueryString(format("select e from %s e where e.%s = :entityId", metaClass.getName(), pkName)) - .setParameter("entityId", attribute.getObjectDefaultEntityId()); - Entity entity = dataManager.load(lc); - if (entity != null) { - defaultEntityField.setValue(entity); - } else { - defaultEntityField.setValue(null); - } - } - } - - protected void fillAttributeCode() { - CategoryAttribute attribute = getItem(); - if (StringUtils.isBlank(attribute.getCode()) && StringUtils.isNotBlank(attribute.getName())) { - String categoryName = StringUtils.EMPTY; - if (attribute.getCategory() != null) { - categoryName = StringUtils.defaultString(attribute.getCategory().getName()); - } - attribute.setCode(StringUtils.deleteWhitespace(categoryName + attribute.getName())); - } - } - - @Override - public boolean preCommit() { - Collection screens = screensDs.getItems(); - StringBuilder stringBuilder = new StringBuilder(); - for (ScreenAndComponent screenAndComponent : screens) { - if (StringUtils.isNotBlank(screenAndComponent.getScreen())) { - stringBuilder.append(screenAndComponent.getScreen()); - if (StringUtils.isNotBlank(screenAndComponent.getComponent())) { - stringBuilder.append("#"); - stringBuilder.append(screenAndComponent.getComponent()); - } - stringBuilder.append(","); - } - } - - if (stringBuilder.length() > 0) { - stringBuilder.deleteCharAt(stringBuilder.length() - 1); - } - attribute.setTargetScreens(stringBuilder.toString()); - - if (localizedFrame != null) { - attribute.setLocaleNames(localizedFrame.getValue()); - } - - return true; - } - - @Override - public void postValidate(ValidationErrors errors) { - @SuppressWarnings("unchecked") - CollectionDatasource parent - = (CollectionDatasource) ((DatasourceImplementation) attributeDs).getParent(); - if (parent != null) { - CategoryAttribute categoryAttribute = getItem(); - for (UUID id : parent.getItemIds()) { - CategoryAttribute ca = parent.getItemNN(id); - if (ca.getName().equals(categoryAttribute.getName()) - && (!ca.equals(categoryAttribute))) { - errors.add(getMessage("uniqueName")); - return; - } else if (ca.getCode() != null && ca.getCode().equals(categoryAttribute.getCode()) - && (!ca.equals(categoryAttribute))) { - errors.add(getMessage("uniqueCode")); - return; - } - } - } - } - - @Override - protected void postInit() { - attribute = getItem(); - Set targetScreens = attribute.targetScreensSet(); - for (String targetScreen : targetScreens) { - if (targetScreen.contains("#")) { - String[] split = targetScreen.split("#"); - screensDs.addItem(new ScreenAndComponent(split[0], split[1])); - } else { - screensDs.addItem(new ScreenAndComponent(targetScreen, null)); - } - } - - MetaClass categorizedEntityMetaClass = metadata.getClass(attribute.getCategory().getEntityType()); - final Map optionsMap = categorizedEntityMetaClass != null ? - new HashMap<>(screensHelper.getAvailableScreens(categorizedEntityMetaClass.getJavaClass())) : - Collections.emptyMap(); - - targetScreensTable.addGeneratedColumn( - "screen", - entity -> { - final LookupField lookupField = componentsFactory.createComponent(LookupField.class); - lookupField.setDatasource(targetScreensTable.getItemDatasource(entity), "screen"); - lookupField.setOptionsMap(optionsMap); - lookupField.setNewOptionAllowed(true); - lookupField.setNewOptionHandler(caption -> { - if (caption != null && !optionsMap.containsKey(caption)) { - optionsMap.put(caption, caption); - lookupField.setValue(caption); - } - }); - lookupField.setRequired(true); - lookupField.setWidth("100%"); - return lookupField; - } - ); - - String enumeration = attribute.getEnumeration(); - if (!Strings.isNullOrEmpty(enumeration)) { - Iterable items = Splitter.on(",").omitEmptyStrings().split(enumeration); - enumerationListEditor.setValue(Lists.newArrayList(items)); - } - - if (localizedFrame != null) { - localizedFrame.setValue(attribute.getLocaleNames()); - } - - setupVisibility(); - } - - protected List requestHint(SourceCodeEditor sender, String text, int senderCursorPosition) { - String joinStr = joinField.getValue(); - String whereStr = whereField.getValue(); - - // CAUTION: the magic entity name! The length is three character to match "{E}" length in query - String entityAlias = "a39"; - - int queryPosition = -1; - Class javaClassForEntity = attribute.getJavaClassForEntity(); - if (javaClassForEntity == null) return new ArrayList<>(); - - MetaClass metaClass = metadata.getClassNN(javaClassForEntity); - String queryStart = "select " + entityAlias + " from " + metaClass.getName() + " " + entityAlias + " "; - - StringBuilder queryBuilder = new StringBuilder(queryStart); - if (StringUtils.isNotEmpty(joinStr)) { - if (sender == joinField) { - queryPosition = queryBuilder.length() + senderCursorPosition - 1; - } - if (!StringUtils.containsIgnoreCase(joinStr, "join") && !StringUtils.contains(joinStr, ",")) { - queryBuilder.append("join ").append(joinStr); - queryPosition += "join ".length(); - } else { - queryBuilder.append(joinStr); - } - } - if (StringUtils.isNotEmpty(whereStr)) { - if (sender == whereField) { - queryPosition = queryBuilder.length() + WHERE.length() + senderCursorPosition - 1; - } - queryBuilder.append(WHERE).append(whereStr); - } - String query = queryBuilder.toString(); - query = query.replace("{E}", entityAlias); - - return JpqlSuggestionFactory.requestHint(query, queryPosition, sender.getAutoCompleteSupport(), senderCursorPosition); - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.categories; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.haulmont.bali.util.Dom4j; +import com.haulmont.bali.util.ParamsMap; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.HasUuid; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.core.global.filter.SecurityJpqlGenerator; +import com.haulmont.cuba.gui.ScreensHelper; +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.actions.BaseAction; +import com.haulmont.cuba.gui.components.actions.RemoveAction; +import com.haulmont.cuba.gui.components.autocomplete.JpqlSuggestionFactory; +import com.haulmont.cuba.gui.components.autocomplete.Suggestion; +import com.haulmont.cuba.gui.components.filter.ConditionsTree; +import com.haulmont.cuba.gui.components.filter.FakeFilterSupport; +import com.haulmont.cuba.gui.components.filter.FilterParser; +import com.haulmont.cuba.gui.components.filter.Param; +import com.haulmont.cuba.gui.components.filter.edit.FilterEditor; +import com.haulmont.cuba.gui.data.CollectionDatasource; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.AbstractDatasource; +import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; +import com.haulmont.cuba.gui.dynamicattributes.DynamicAttributesGuiTools; +import com.haulmont.cuba.gui.theme.ThemeConstants; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; +import com.haulmont.cuba.security.entity.FilterEntity; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.text.StrBuilder; +import org.dom4j.Element; + +import javax.inject.Inject; +import java.util.*; + +import static java.lang.String.format; + +/** + * Class that encapsulates editing of {@link CategoryAttribute} entities. + *

+ */ +public class AttributeEditor extends AbstractEditor { + protected static final Multimap FIELDS_VISIBLE_FOR_DATATYPES = ArrayListMultimap.create(); + protected static final Set ALWAYS_VISIBLE_FIELDS = Sets.newHashSet("name", "code", "required", "dataType"); + protected static final String WHERE = " where "; + + static { + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.BOOLEAN, "defaultBoolean"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "defaultString"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "rowsCount"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.STRING, "isCollection"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "defaultDouble"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DOUBLE, "isCollection"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "defaultInt"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.INTEGER, "isCollection"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "defaultDate"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "defaultDateIsCurrent"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.DATE, "isCollection"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "enumeration"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "defaultString"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENUMERATION, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "entityClass"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "screen"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "lookup"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "defaultEntityId"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "width"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "joinClause"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "whereClause"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "constraintWizard"); + FIELDS_VISIBLE_FOR_DATATYPES.put(PropertyType.ENTITY, "isCollection"); + } + + protected CategoryAttribute attribute; + + @Inject + protected FieldGroup attributeFieldGroup; + protected LookupField dataTypeField; + protected LookupField screenField; + protected LookupField entityTypeField; + protected PickerField defaultEntityField; + protected PickerField.LookupAction entityLookupAction; + protected String fieldWidth; + + @Inject + protected Datasource attributeDs; + + @Inject + protected ComponentsFactory factory; + + @Inject + protected Metadata metadata; + + @Inject + protected MetadataTools metadataTools; + + @Inject + protected MessageTools messageTools; + + @Inject + protected DatatypeFormatter datatypeFormatter; + + @Inject + protected ThemeConstants themeConstants; + + @Inject + protected ScreensHelper screensHelper; + + @Inject + protected ComponentsFactory componentsFactory; + + @Inject + protected DynamicAttributesGuiTools dynamicAttributesGuiTools; + + @Inject + protected DataManager dataManager; + + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + + @Inject + protected Table targetScreensTable; + + @Inject + protected TabSheet tabsheet; + + @Inject + protected CollectionDatasource screensDs; + + @Inject + protected GlobalConfig globalConfig; + + protected LocalizedNameFrame localizedFrame; + + private ListEditor enumerationListEditor; + private SourceCodeEditor joinField; + private SourceCodeEditor whereField; + + @Override + public void init(Map params) { + getDialogOptions().setWidth(themeConstants.get("cuba.gui.AttributeEditor.width")); + + fieldWidth = themeConstants.get("cuba.gui.AttributeEditor.field.width"); + + initLocalizedFrame(); + initFieldGroup(); + + targetScreensTable.addAction(new AbstractAction("create") { + @Override + public void actionPerform(Component component) { + screensDs.addItem(new ScreenAndComponent()); + } + }); + targetScreensTable.addAction(new RemoveAction(targetScreensTable)); + } + + protected void initLocalizedFrame() { + if (globalConfig.getAvailableLocales().size() > 1) { + tabsheet.getTab("localization").setVisible(true); + localizedFrame = (LocalizedNameFrame) openFrame( + tabsheet.getTabComponent("localization"), "localizedNameFrame"); + localizedFrame.setWidth("100%"); + localizedFrame.setHeight("250px"); + } + } + + protected void initFieldGroup() { + attributeFieldGroup.addCustomField("defaultBoolean", new FieldGroup.CustomFieldGenerator() { + @Override + public Component generateField(Datasource datasource, String propertyId) { + LookupField lookupField = factory.createComponent(LookupField.class); + Map options = new TreeMap<>(); + options.put(datatypeFormatter.formatBoolean(true), true); + options.put(datatypeFormatter.formatBoolean(false), false); + lookupField.setOptionsMap(options); + lookupField.setDatasource(attributeDs, "defaultBoolean"); + return lookupField; + } + }); + + attributeFieldGroup.addCustomField("dataType", new FieldGroup.CustomFieldGenerator() { + @Override + public Component generateField(Datasource datasource, String propertyId) { + dataTypeField = factory.createComponent(LookupField.class); + Map options = new TreeMap<>(); + PropertyType[] types = PropertyType.values(); + for (PropertyType propertyType : types) { + options.put(getMessage(propertyType.toString()), propertyType); + } + dataTypeField.setWidth(fieldWidth); + + dataTypeField.setNewOptionAllowed(false); + dataTypeField.setRequired(true); + dataTypeField.setRequiredMessage(getMessage("dataTypeRequired")); + dataTypeField.setOptionsMap(options); + dataTypeField.setCaption(getMessage("dataType")); + dataTypeField.setFrame(frame); + dataTypeField.setDatasource(datasource, propertyId); + + return dataTypeField; + } + }); + + attributeFieldGroup.addCustomField("screen", new FieldGroup.CustomFieldGenerator() { + @Override + public Component generateField(Datasource datasource, String propertyId) { + screenField = factory.createComponent(LookupField.class); + screenField.setId("screenField"); + screenField.setCaption(getMessage("screen")); + screenField.setWidth(fieldWidth); + screenField.setRequired(true); + screenField.setRequiredMessage(getMessage("entityScreenRequired")); + screenField.setFrame(frame); + screenField.setDatasource(datasource, propertyId); + + return screenField; + } + }); + + attributeFieldGroup.addCustomField("entityClass", new FieldGroup.CustomFieldGenerator() { + @Override + public Component generateField(Datasource datasource, String propertyId) { + entityTypeField = factory.createComponent(LookupField.class); + entityTypeField.setId("entityClass"); + entityTypeField.setCaption(getMessage("entityType")); + entityTypeField.setRequired(true); + entityTypeField.setRequiredMessage(getMessage("entityTypeRequired")); + entityTypeField.setWidth(fieldWidth); + entityTypeField.setFrame(frame); + Map options = new TreeMap<>(); + MetaClass entityType = null; + for (MetaClass metaClass : metadataTools.getAllPersistentMetaClasses()) { + if (!metadataTools.isSystemLevel(metaClass)) { + if (metadata.getTools().hasCompositePrimaryKey(metaClass) && !HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { + continue; + } + options.put(messageTools.getDetailedEntityCaption(metaClass), metaClass.getJavaClass().getName()); + if (attribute != null && metaClass.getJavaClass().getName().equals(attribute.getEntityClass())) { + entityType = metaClass; + } + } + } + entityTypeField.setOptionsMap(options); + entityTypeField.setValue(entityType); + entityTypeField.setDatasource(datasource, propertyId); + + return entityTypeField; + } + }); + + attributeFieldGroup.addCustomField("defaultEntityId", (datasource, propertyId) -> { + defaultEntityField = factory.createComponent(PickerField.class); + defaultEntityField.setCaption(messages.getMessage(CategoryAttribute.class, "CategoryAttribute.defaultEntityId")); + defaultEntityField.addValueChangeListener(e -> { + Entity entity = (Entity) e.getValue(); + if (entity != null) { + attribute.setObjectDefaultEntityId(referenceToEntitySupport.getReferenceId(entity)); + } else { + attribute.setObjectDefaultEntityId(null); + } + ((AbstractDatasource) attributeDs).modified(attribute); + }); + entityLookupAction = defaultEntityField.addLookupAction(); + defaultEntityField.addClearAction(); + + return defaultEntityField; + }); + + attributeFieldGroup.addCustomField("enumeration", (datasource, propertyId) -> { + enumerationListEditor = factory.createComponent(ListEditor.class); + enumerationListEditor.setWidth("100%"); + enumerationListEditor.setItemType(ListEditor.ItemType.STRING); + enumerationListEditor.setRequired(true); + enumerationListEditor.setRequiredMessage(getMessage("enumRequired")); + enumerationListEditor.addValueChangeListener(e -> { + List value = (List) e.getValue(); + attribute.setEnumeration(Joiner.on(",").join(value)); + }); + if (localizedFrame != null) { + enumerationListEditor.setEditorWindowId("localizedEnumerationWindow"); + enumerationListEditor.setEditorParamsSupplier(() -> + ParamsMap.of("enumerationLocales", attribute.getEnumerationLocales())); + enumerationListEditor.addEditorCloseListener(closeEvent -> { + if (closeEvent.getActionId().equals(COMMIT_ACTION_ID)) { + LocalizedEnumerationWindow enumerationWindow = (LocalizedEnumerationWindow) closeEvent.getWindow(); + attribute.setEnumerationLocales(enumerationWindow.getLocalizedValues()); + } + }); + } + return enumerationListEditor; + }); + + attributeFieldGroup.addCustomField("whereClause", (datasource, propertyId) -> { + whereField = factory.createComponent(SourceCodeEditor.class); + whereField.setDatasource(attributeDs, "whereClause"); + whereField.setWidth("100%"); + whereField.setHeight(themeConstants.get("cuba.gui.customConditionFrame.whereField.height")); + whereField.setSuggester((source, text, cursorPosition) -> requestHint(whereField, text, cursorPosition)); + whereField.setHighlightActiveLine(false); + whereField.setShowGutter(false); + return whereField; + }); + + attributeFieldGroup.addCustomField("joinClause", (datasource, propertyId) -> { + joinField = factory.createComponent(SourceCodeEditor.class); + joinField.setDatasource(attributeDs, "joinClause"); + joinField.setWidth("100%"); + joinField.setHeight(themeConstants.get("cuba.gui.customConditionFrame.joinField.height")); + joinField.setSuggester((source, text, cursorPosition) -> requestHint(joinField, text, cursorPosition)); + joinField.setHighlightActiveLine(false); + joinField.setShowGutter(false); + return joinField; + }); + + attributeFieldGroup.addCustomField("constraintWizard", (datasource, propertyId) -> { + HBoxLayout hbox = factory.createComponent(HBoxLayout.class); + hbox.setWidth("100%"); + LinkButton linkButton = factory.createComponent(LinkButton.class); + linkButton.setAction(new BaseAction("constraintWizard") + .withHandler(event -> + openConstraintWizard() + )); + + linkButton.setCaption(getMessage("constraintWizard")); + linkButton.setAlignment(Alignment.MIDDLE_LEFT); + hbox.add(linkButton); + return hbox; + }); + + attributeDs.addItemPropertyChangeListener(e -> { + String property = e.getProperty(); + CategoryAttribute attribute = getItem(); + if ("dataType".equalsIgnoreCase(property) + || "lookup".equalsIgnoreCase(property) + || "defaultDateIsCurrent".equalsIgnoreCase(property) + || "entityClass".equalsIgnoreCase(property)) { + setupVisibility(); + } + if ("name".equalsIgnoreCase(property)) { + fillAttributeCode(); + } + if ("screen".equalsIgnoreCase(property) || "joinClause".equals(property) || "whereClause".equals(property)) { + dynamicAttributesGuiTools.initEntityPickerField(defaultEntityField, attribute); + } + }); + } + + public void openConstraintWizard() { + Class entityClass = attribute.getJavaClassForEntity(); + if (entityClass == null) { + showNotification(getMessage("selectEntityType")); + return; + } + MetaClass metaClass = metadata.getClassNN(entityClass); + FakeFilterSupport fakeFilterSupport = new FakeFilterSupport(this, metaClass); + + final Filter fakeFilter = fakeFilterSupport.createFakeFilter(); + final FilterEntity filterEntity = fakeFilterSupport.createFakeFilterEntity(attribute.getFilterXml()); + final ConditionsTree conditionsTree = fakeFilterSupport.createFakeConditionsTree(fakeFilter, filterEntity); + + Map params = new HashMap<>(); + params.put("filter", fakeFilter); + params.put("filterEntity", filterEntity); + params.put("conditions", conditionsTree); + params.put("useShortConditionForm", true); + + FilterEditor filterEditor = (FilterEditor) openWindow("filterEditor", WindowManager.OpenType.DIALOG, params); + filterEditor.addCloseListener(actionId -> { + if (!COMMIT_ACTION_ID.equals(actionId)) return; + FilterParser filterParser1 = AppBeans.get(FilterParser.class); + filterEntity.setXml(filterParser1.getXml(filterEditor.getConditions(), Param.ValueProperty.DEFAULT_VALUE)); + if (filterEntity.getXml() != null) { + Element element = Dom4j.readDocument(filterEntity.getXml()).getRootElement(); + com.haulmont.cuba.core.global.filter.FilterParser filterParser = new com.haulmont.cuba.core.global.filter.FilterParser(element); + String jpql = new SecurityJpqlGenerator().generateJpql(filterParser.getRoot()); + attribute.setWhereClause(jpql); + Set joins = filterParser.getRoot().getJoins(); + if (!joins.isEmpty()) { + String joinsStr = new StrBuilder().appendWithSeparators(joins, " ").toString(); + attribute.setJoinClause(joinsStr); + } + attribute.setFilterXml(filterEntity.getXml()); + } + }); + } + + private void setupVisibility() { + for (FieldGroup.FieldConfig fieldConfig : attributeFieldGroup.getFields()) { + if (!ALWAYS_VISIBLE_FIELDS.contains(fieldConfig.getId())) { + attributeFieldGroup.setVisible(fieldConfig.getId(), false); + } + } + + Collection componentIds = FIELDS_VISIBLE_FOR_DATATYPES.get(attribute.getDataType()); + if (componentIds != null) { + for (String componentId : componentIds) { + attributeFieldGroup.setVisible(componentId, true); + } + } + + if (attribute.getDataType() == PropertyType.ENTITY) { + if (StringUtils.isNotBlank(attribute.getEntityClass())) { + defaultEntityField.setEditable(true); + whereField.setEnabled(true); + joinField.setEnabled(true); + Class entityClass = attribute.getJavaClassForEntity(); + MetaClass metaClass = metadata.getClass(entityClass); + defaultEntityField.setMetaClass(metaClass); + fillDefaultEntities(entityClass); + fillSelectEntityScreens(entityClass); + + dynamicAttributesGuiTools.initEntityPickerField(defaultEntityField, attribute); + } else { + defaultEntityField.setEditable(false); + whereField.setEnabled(false); + joinField.setEnabled(false); + } + + if (Boolean.TRUE.equals(attribute.getLookup())) { + attributeFieldGroup.setVisible("screen", false); + } else { + attributeFieldGroup.setVisible("screen", true); + } + + getDialogOptions().center(); + } + + if (attribute.getDataType() == PropertyType.DATE) { + if (Boolean.TRUE.equals(attribute.getDefaultDateIsCurrent())) { + attributeFieldGroup.setVisible("defaultDate", false); + attributeFieldGroup.setFieldValue("defaultDate", null); + } else { + attributeFieldGroup.setVisible("defaultDate", true); + } + } + + if (attribute.getDataType() == PropertyType.BOOLEAN || + attribute.getDataType() == PropertyType.ENUMERATION) { + attributeFieldGroup.setFieldValue("isCollection", null); + } + } + + protected void fillSelectEntityScreens(Class entityClass) { + String value = attribute.getScreen(); + Map screensMap = screensHelper.getAvailableBrowserScreens(entityClass); + screenField.setValue(null); // While #PL-4731 unfixed + screenField.setOptionsMap(screensMap); + screenField.setValue(screensMap.containsValue(value) ? value : null); + } + + @SuppressWarnings("unchecked") + protected void fillDefaultEntities(Class entityClass) { + MetaClass metaClass = metadata.getClassNN(entityClass); + if (attribute.getObjectDefaultEntityId() != null) { + LoadContext lc = new LoadContext<>(entityClass).setView(View.MINIMAL); + String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); + lc.setQueryString(format("select e from %s e where e.%s = :entityId", metaClass.getName(), pkName)) + .setParameter("entityId", attribute.getObjectDefaultEntityId()); + Entity entity = dataManager.load(lc); + if (entity != null) { + defaultEntityField.setValue(entity); + } else { + defaultEntityField.setValue(null); + } + } + } + + protected void fillAttributeCode() { + CategoryAttribute attribute = getItem(); + if (StringUtils.isBlank(attribute.getCode()) && StringUtils.isNotBlank(attribute.getName())) { + String categoryName = StringUtils.EMPTY; + if (attribute.getCategory() != null) { + categoryName = StringUtils.defaultString(attribute.getCategory().getName()); + } + attribute.setCode(StringUtils.deleteWhitespace(categoryName + attribute.getName())); + } + } + + @Override + public boolean preCommit() { + Collection screens = screensDs.getItems(); + StringBuilder stringBuilder = new StringBuilder(); + for (ScreenAndComponent screenAndComponent : screens) { + if (StringUtils.isNotBlank(screenAndComponent.getScreen())) { + stringBuilder.append(screenAndComponent.getScreen()); + if (StringUtils.isNotBlank(screenAndComponent.getComponent())) { + stringBuilder.append("#"); + stringBuilder.append(screenAndComponent.getComponent()); + } + stringBuilder.append(","); + } + } + + if (stringBuilder.length() > 0) { + stringBuilder.deleteCharAt(stringBuilder.length() - 1); + } + attribute.setTargetScreens(stringBuilder.toString()); + + if (localizedFrame != null) { + attribute.setLocaleNames(localizedFrame.getValue()); + } + + return true; + } + + @Override + public void postValidate(ValidationErrors errors) { + @SuppressWarnings("unchecked") + CollectionDatasource parent + = (CollectionDatasource) ((DatasourceImplementation) attributeDs).getParent(); + if (parent != null) { + CategoryAttribute categoryAttribute = getItem(); + for (UUID id : parent.getItemIds()) { + CategoryAttribute ca = parent.getItemNN(id); + if (ca.getName().equals(categoryAttribute.getName()) + && (!ca.equals(categoryAttribute))) { + errors.add(getMessage("uniqueName")); + return; + } else if (ca.getCode() != null && ca.getCode().equals(categoryAttribute.getCode()) + && (!ca.equals(categoryAttribute))) { + errors.add(getMessage("uniqueCode")); + return; + } + } + } + } + + @Override + protected void postInit() { + attribute = getItem(); + Set targetScreens = attribute.targetScreensSet(); + for (String targetScreen : targetScreens) { + if (targetScreen.contains("#")) { + String[] split = targetScreen.split("#"); + screensDs.addItem(new ScreenAndComponent(split[0], split[1])); + } else { + screensDs.addItem(new ScreenAndComponent(targetScreen, null)); + } + } + + MetaClass categorizedEntityMetaClass = metadata.getClass(attribute.getCategory().getEntityType()); + final Map optionsMap = categorizedEntityMetaClass != null ? + new HashMap<>(screensHelper.getAvailableScreens(categorizedEntityMetaClass.getJavaClass())) : + Collections.emptyMap(); + + targetScreensTable.addGeneratedColumn( + "screen", + entity -> { + final LookupField lookupField = componentsFactory.createComponent(LookupField.class); + lookupField.setDatasource(targetScreensTable.getItemDatasource(entity), "screen"); + lookupField.setOptionsMap(optionsMap); + lookupField.setNewOptionAllowed(true); + lookupField.setNewOptionHandler(caption -> { + if (caption != null && !optionsMap.containsKey(caption)) { + optionsMap.put(caption, caption); + lookupField.setValue(caption); + } + }); + lookupField.setRequired(true); + lookupField.setWidth("100%"); + return lookupField; + } + ); + + String enumeration = attribute.getEnumeration(); + if (!Strings.isNullOrEmpty(enumeration)) { + Iterable items = Splitter.on(",").omitEmptyStrings().split(enumeration); + enumerationListEditor.setValue(Lists.newArrayList(items)); + } + + if (localizedFrame != null) { + localizedFrame.setValue(attribute.getLocaleNames()); + } + + setupVisibility(); + } + + protected List requestHint(SourceCodeEditor sender, String text, int senderCursorPosition) { + String joinStr = joinField.getValue(); + String whereStr = whereField.getValue(); + + // CAUTION: the magic entity name! The length is three character to match "{E}" length in query + String entityAlias = "a39"; + + int queryPosition = -1; + Class javaClassForEntity = attribute.getJavaClassForEntity(); + if (javaClassForEntity == null) return new ArrayList<>(); + + MetaClass metaClass = metadata.getClassNN(javaClassForEntity); + String queryStart = "select " + entityAlias + " from " + metaClass.getName() + " " + entityAlias + " "; + + StringBuilder queryBuilder = new StringBuilder(queryStart); + if (StringUtils.isNotEmpty(joinStr)) { + if (sender == joinField) { + queryPosition = queryBuilder.length() + senderCursorPosition - 1; + } + if (!StringUtils.containsIgnoreCase(joinStr, "join") && !StringUtils.contains(joinStr, ",")) { + queryBuilder.append("join ").append(joinStr); + queryPosition += "join ".length(); + } else { + queryBuilder.append(joinStr); + } + } + if (StringUtils.isNotEmpty(whereStr)) { + if (sender == whereField) { + queryPosition = queryBuilder.length() + WHERE.length() + senderCursorPosition - 1; + } + queryBuilder.append(WHERE).append(whereStr); + } + String query = queryBuilder.toString(); + query = query.replace("{E}", entityAlias); + + return JpqlSuggestionFactory.requestHint(query, queryPosition, sender.getAutoCompleteSupport(), senderCursorPosition); + } +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryAttrsFrame.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryAttrsFrame.java index 4664ca4a54..46e5540c29 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryAttrsFrame.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryAttrsFrame.java @@ -1,300 +1,300 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.categories; - -import com.haulmont.chile.core.datatypes.Datatypes; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.chile.core.model.utils.InstanceUtils; -import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.CategoryAttribute; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.gui.WindowManager.OpenType; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.actions.ItemTrackingAction; -import com.haulmont.cuba.gui.components.actions.RefreshAction; -import com.haulmont.cuba.gui.components.actions.RemoveAction; -import com.haulmont.cuba.gui.data.Datasource; -import com.haulmont.cuba.gui.data.impl.CollectionPropertyDatasourceImpl; -import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; -import org.apache.commons.lang.BooleanUtils; - -import javax.inject.Inject; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static java.lang.String.format; - -public class CategoryAttrsFrame extends AbstractFrame { - - @Inject - protected Metadata metadata; - - @Inject - protected MessageTools messageTools; - - @Inject - protected UserSessionSource userSessionSource; - - @Inject - protected ComponentsFactory factory; - - @Inject - protected DataManager dataManager; - - @Inject - protected ReferenceToEntitySupport referenceToEntitySupport; - - @Inject - protected Table categoryAttrsTable; - - @Inject - protected Datasource categoryDs; - - @Inject - protected CollectionPropertyDatasourceImpl categoryAttrsDs; - - @Override - public void init(Map params) { - super.init(params); - categoryAttrsTable.addAction(new CategoryAttributeCreateAction()); - categoryAttrsTable.addAction(new CategoryAttributeEditAction()); - categoryAttrsTable.addAction(new RemoveAction(categoryAttrsTable, false)); - categoryAttrsTable.addAction(new RefreshAction(categoryAttrsTable)); - - categoryAttrsDs.addStateChangeListener(e -> { - if (e.getState() != Datasource.State.VALID) { - return; - } - initDataTypeColumn(); - initDefaultValueColumn(); - }); - - initMoveButtons(); - } - - protected void initMoveButtons() { - Action moveUpAction = new ItemTrackingAction("moveUp") - .withCaption("") - .withHandler(event -> { - Set selected = categoryAttrsTable.getSelected(); - if (selected.isEmpty()) - return; - - CategoryAttribute currentAttr = selected.iterator().next(); - UUID prevId = categoryAttrsDs.prevItemId(currentAttr.getId()); - if (prevId == null) - return; - - Integer tmp = currentAttr.getOrderNo(); - CategoryAttribute prevAttr = categoryAttrsDs.getItemNN(prevId); - currentAttr.setOrderNo(prevAttr.getOrderNo()); - prevAttr.setOrderNo(tmp); - - sortTableByOrderNo(); - }); - ((Button) getComponentNN("moveUp")).setAction(moveUpAction); - - Action moveDownAction = new ItemTrackingAction("moveDown") - .withCaption("") - .withHandler(event -> { - Set selected = categoryAttrsTable.getSelected(); - if (selected.isEmpty()) - return; - - CategoryAttribute currentAttr = selected.iterator().next(); - UUID nextId = categoryAttrsDs.nextItemId(currentAttr.getId()); - if (nextId == null) - return; - - Integer tmp = currentAttr.getOrderNo(); - CategoryAttribute nextAttr = categoryAttrsDs.getItemNN(nextId); - currentAttr.setOrderNo(nextAttr.getOrderNo()); - nextAttr.setOrderNo(tmp); - - sortTableByOrderNo(); - }); - ((Button) getComponentNN("moveDown")).setAction(moveDownAction); - - categoryAttrsTable.addAction(moveUpAction); - categoryAttrsTable.addAction(moveDownAction); - } - - protected void sortTableByOrderNo() { - categoryAttrsTable.sortBy(categoryAttrsDs.getMetaClass().getPropertyPath("orderNo"), true); - } - - protected void initDataTypeColumn() { - categoryAttrsTable.removeGeneratedColumn("dataType"); - categoryAttrsTable.addGeneratedColumn("dataType", new Table.ColumnGenerator() { - @Override - public Component generateCell(CategoryAttribute attribute) { - Label dataTypeLabel = factory.createComponent(Label.class); - String labelContent; - if (BooleanUtils.isTrue(attribute.getIsEntity())) { - Class clazz = attribute.getJavaClassForEntity(); - - if (clazz != null) { - MetaClass metaClass = metadata.getSession().getClass(clazz); - labelContent = messageTools.getEntityCaption(metaClass); - } else { - labelContent = "classNotFound"; - } - } else { - labelContent = getMessage(attribute.getDataType().name()); - } - - dataTypeLabel.setValue(labelContent); - return dataTypeLabel; - } - }); - } - - protected void initDefaultValueColumn() { - categoryAttrsTable.addGeneratedColumn("defaultValue", new Table.ColumnGenerator() { - @Override - public Component generateCell(CategoryAttribute attribute) { - String defaultValue = ""; - - if (BooleanUtils.isNotTrue(attribute.getIsEntity())) { - PropertyType dataType = attribute.getDataType(); - switch (dataType) { - case DATE: - Date date = attribute.getDefaultDate(); - if (date != null) { - String dateTimeFormat = Datatypes.getFormatStringsNN(userSessionSource.getLocale()).getDateTimeFormat(); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); - defaultValue = simpleDateFormat.format(date); - } else if (BooleanUtils.isTrue(attribute.getDefaultDateIsCurrent())) { - defaultValue = getMessage("currentDate"); - } - break; - case BOOLEAN: - Boolean b = attribute.getDefaultBoolean(); - if (b != null) - defaultValue = BooleanUtils.isTrue(b) ? getMessage("msgTrue") : getMessage("msgFalse"); - break; - default: - if (attribute.getDefaultValue() != null) - defaultValue = attribute.getDefaultValue().toString(); - } - } else { - Class entityClass = attribute.getJavaClassForEntity(); - if (entityClass != null) { - defaultValue = ""; - if (attribute.getObjectDefaultEntityId() != null) { - MetaClass metaClass = metadata.getClassNN(entityClass); - LoadContext lc = new LoadContext<>(entityClass).setView(View.MINIMAL); - String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); - lc.setQueryString(format("select e from %s e where e.%s = :entityId", metaClass.getName(), pkName)) - .setParameter("entityId", attribute.getObjectDefaultEntityId()); - Entity entity = dataManager.load(lc); - if (entity != null) { - defaultValue = InstanceUtils.getInstanceName(entity); - } - } - } else { - defaultValue = getMessage("entityNotFound"); - } - } - - Label defaultValueLabel = factory.createComponent(Label.class); - defaultValueLabel.setValue(defaultValue); - return defaultValueLabel; - } - }); - } - - protected void assignNextOrderNo(CategoryAttribute attr) { - UUID lastId = categoryAttrsDs.lastItemId(); - if (lastId == null) - attr.setOrderNo(1); - else { - CategoryAttribute lastItem = categoryAttrsDs.getItemNN(lastId); - if (lastItem.getOrderNo() == null) - attr.setOrderNo(1); - else - attr.setOrderNo(categoryAttrsDs.getItemNN(lastId).getOrderNo() + 1); - - } - } - - protected class CategoryAttributeEditAction extends ItemTrackingAction { - - protected CategoryAttributeEditAction() { - super("edit"); - } - - @Override - public String getCaption() { - return getMessage("categoryAttrsTable.edit"); - } - - @Override - public void actionPerform(Component component) { - Set selected = categoryAttrsTable.getSelected(); - if (!selected.isEmpty()) { - AttributeEditor editor = (AttributeEditor) openEditor( - "sys$CategoryAttribute.edit", - selected.iterator().next(), - OpenType.DIALOG, - categoryAttrsTable.getDatasource()); - editor.addCloseListener(actionId -> { - categoryAttrsTable.getDatasource().refresh(); - categoryAttrsTable.requestFocus(); - // restore selection from ds - categoryAttrsTable.setSelected(categoryAttrsDs.getItem()); - }); - } - } - } - - protected class CategoryAttributeCreateAction extends AbstractAction { - - protected CategoryAttributeCreateAction() { - super("create"); - } - - @Override - public String getCaption() { - return getMessage("categoryAttrsTable.create"); - } - - @Override - public void actionPerform(Component component) { - final CategoryAttribute attribute = metadata.create(CategoryAttribute.class); - attribute.setCategory((Category) categoryDs.getItem()); - assignNextOrderNo(attribute); - AttributeEditor editor = (AttributeEditor) openEditor( - "sys$CategoryAttribute.edit", - attribute, - OpenType.DIALOG, - categoryAttrsTable.getDatasource()); - editor.addCloseListener(actionId -> { - categoryAttrsTable.getDatasource().refresh(); - categoryAttrsTable.requestFocus(); - // restore selection from ds - categoryAttrsTable.setSelected(categoryAttrsDs.getItem()); - }); - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.categories; + +import com.haulmont.chile.core.datatypes.Datatypes; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.chile.core.model.utils.InstanceUtils; +import com.haulmont.cuba.core.app.dynamicattributes.PropertyType; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.CategoryAttribute; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.gui.WindowManager.OpenType; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.actions.ItemTrackingAction; +import com.haulmont.cuba.gui.components.actions.RefreshAction; +import com.haulmont.cuba.gui.components.actions.RemoveAction; +import com.haulmont.cuba.gui.data.Datasource; +import com.haulmont.cuba.gui.data.impl.CollectionPropertyDatasourceImpl; +import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; +import org.apache.commons.lang.BooleanUtils; + +import javax.inject.Inject; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import static java.lang.String.format; + +public class CategoryAttrsFrame extends AbstractFrame { + + @Inject + protected Metadata metadata; + + @Inject + protected MessageTools messageTools; + + @Inject + protected UserSessionSource userSessionSource; + + @Inject + protected ComponentsFactory factory; + + @Inject + protected DataManager dataManager; + + @Inject + protected ReferenceToEntitySupport referenceToEntitySupport; + + @Inject + protected Table categoryAttrsTable; + + @Inject + protected Datasource categoryDs; + + @Inject + protected CollectionPropertyDatasourceImpl categoryAttrsDs; + + @Override + public void init(Map params) { + super.init(params); + categoryAttrsTable.addAction(new CategoryAttributeCreateAction()); + categoryAttrsTable.addAction(new CategoryAttributeEditAction()); + categoryAttrsTable.addAction(new RemoveAction(categoryAttrsTable, false)); + categoryAttrsTable.addAction(new RefreshAction(categoryAttrsTable)); + + categoryAttrsDs.addStateChangeListener(e -> { + if (e.getState() != Datasource.State.VALID) { + return; + } + initDataTypeColumn(); + initDefaultValueColumn(); + }); + + initMoveButtons(); + } + + protected void initMoveButtons() { + Action moveUpAction = new ItemTrackingAction("moveUp") + .withCaption("") + .withHandler(event -> { + Set selected = categoryAttrsTable.getSelected(); + if (selected.isEmpty()) + return; + + CategoryAttribute currentAttr = selected.iterator().next(); + UUID prevId = categoryAttrsDs.prevItemId(currentAttr.getId()); + if (prevId == null) + return; + + Integer tmp = currentAttr.getOrderNo(); + CategoryAttribute prevAttr = categoryAttrsDs.getItemNN(prevId); + currentAttr.setOrderNo(prevAttr.getOrderNo()); + prevAttr.setOrderNo(tmp); + + sortTableByOrderNo(); + }); + ((Button) getComponentNN("moveUp")).setAction(moveUpAction); + + Action moveDownAction = new ItemTrackingAction("moveDown") + .withCaption("") + .withHandler(event -> { + Set selected = categoryAttrsTable.getSelected(); + if (selected.isEmpty()) + return; + + CategoryAttribute currentAttr = selected.iterator().next(); + UUID nextId = categoryAttrsDs.nextItemId(currentAttr.getId()); + if (nextId == null) + return; + + Integer tmp = currentAttr.getOrderNo(); + CategoryAttribute nextAttr = categoryAttrsDs.getItemNN(nextId); + currentAttr.setOrderNo(nextAttr.getOrderNo()); + nextAttr.setOrderNo(tmp); + + sortTableByOrderNo(); + }); + ((Button) getComponentNN("moveDown")).setAction(moveDownAction); + + categoryAttrsTable.addAction(moveUpAction); + categoryAttrsTable.addAction(moveDownAction); + } + + protected void sortTableByOrderNo() { + categoryAttrsTable.sortBy(categoryAttrsDs.getMetaClass().getPropertyPath("orderNo"), true); + } + + protected void initDataTypeColumn() { + categoryAttrsTable.removeGeneratedColumn("dataType"); + categoryAttrsTable.addGeneratedColumn("dataType", new Table.ColumnGenerator() { + @Override + public Component generateCell(CategoryAttribute attribute) { + Label dataTypeLabel = factory.createComponent(Label.class); + String labelContent; + if (BooleanUtils.isTrue(attribute.getIsEntity())) { + Class clazz = attribute.getJavaClassForEntity(); + + if (clazz != null) { + MetaClass metaClass = metadata.getSession().getClass(clazz); + labelContent = messageTools.getEntityCaption(metaClass); + } else { + labelContent = "classNotFound"; + } + } else { + labelContent = getMessage(attribute.getDataType().name()); + } + + dataTypeLabel.setValue(labelContent); + return dataTypeLabel; + } + }); + } + + protected void initDefaultValueColumn() { + categoryAttrsTable.addGeneratedColumn("defaultValue", new Table.ColumnGenerator() { + @Override + public Component generateCell(CategoryAttribute attribute) { + String defaultValue = ""; + + if (BooleanUtils.isNotTrue(attribute.getIsEntity())) { + PropertyType dataType = attribute.getDataType(); + switch (dataType) { + case DATE: + Date date = attribute.getDefaultDate(); + if (date != null) { + String dateTimeFormat = Datatypes.getFormatStringsNN(userSessionSource.getLocale()).getDateTimeFormat(); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); + defaultValue = simpleDateFormat.format(date); + } else if (BooleanUtils.isTrue(attribute.getDefaultDateIsCurrent())) { + defaultValue = getMessage("currentDate"); + } + break; + case BOOLEAN: + Boolean b = attribute.getDefaultBoolean(); + if (b != null) + defaultValue = BooleanUtils.isTrue(b) ? getMessage("msgTrue") : getMessage("msgFalse"); + break; + default: + if (attribute.getDefaultValue() != null) + defaultValue = attribute.getDefaultValue().toString(); + } + } else { + Class entityClass = attribute.getJavaClassForEntity(); + if (entityClass != null) { + defaultValue = ""; + if (attribute.getObjectDefaultEntityId() != null) { + MetaClass metaClass = metadata.getClassNN(entityClass); + LoadContext lc = new LoadContext<>(entityClass).setView(View.MINIMAL); + String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(metaClass); + lc.setQueryString(format("select e from %s e where e.%s = :entityId", metaClass.getName(), pkName)) + .setParameter("entityId", attribute.getObjectDefaultEntityId()); + Entity entity = dataManager.load(lc); + if (entity != null) { + defaultValue = InstanceUtils.getInstanceName(entity); + } + } + } else { + defaultValue = getMessage("entityNotFound"); + } + } + + Label defaultValueLabel = factory.createComponent(Label.class); + defaultValueLabel.setValue(defaultValue); + return defaultValueLabel; + } + }); + } + + protected void assignNextOrderNo(CategoryAttribute attr) { + UUID lastId = categoryAttrsDs.lastItemId(); + if (lastId == null) + attr.setOrderNo(1); + else { + CategoryAttribute lastItem = categoryAttrsDs.getItemNN(lastId); + if (lastItem.getOrderNo() == null) + attr.setOrderNo(1); + else + attr.setOrderNo(categoryAttrsDs.getItemNN(lastId).getOrderNo() + 1); + + } + } + + protected class CategoryAttributeEditAction extends ItemTrackingAction { + + protected CategoryAttributeEditAction() { + super("edit"); + } + + @Override + public String getCaption() { + return getMessage("categoryAttrsTable.edit"); + } + + @Override + public void actionPerform(Component component) { + Set selected = categoryAttrsTable.getSelected(); + if (!selected.isEmpty()) { + AttributeEditor editor = (AttributeEditor) openEditor( + "sys$CategoryAttribute.edit", + selected.iterator().next(), + OpenType.DIALOG, + categoryAttrsTable.getDatasource()); + editor.addCloseListener(actionId -> { + categoryAttrsTable.getDatasource().refresh(); + categoryAttrsTable.requestFocus(); + // restore selection from ds + categoryAttrsTable.setSelected(categoryAttrsDs.getItem()); + }); + } + } + } + + protected class CategoryAttributeCreateAction extends AbstractAction { + + protected CategoryAttributeCreateAction() { + super("create"); + } + + @Override + public String getCaption() { + return getMessage("categoryAttrsTable.create"); + } + + @Override + public void actionPerform(Component component) { + final CategoryAttribute attribute = metadata.create(CategoryAttribute.class); + attribute.setCategory((Category) categoryDs.getItem()); + assignNextOrderNo(attribute); + AttributeEditor editor = (AttributeEditor) openEditor( + "sys$CategoryAttribute.edit", + attribute, + OpenType.DIALOG, + categoryAttrsTable.getDatasource()); + editor.addCloseListener(actionId -> { + categoryAttrsTable.getDatasource().refresh(); + categoryAttrsTable.requestFocus(); + // restore selection from ds + categoryAttrsTable.setSelected(categoryAttrsDs.getItem()); + }); + } + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryBrowser.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryBrowser.java index 795f13b5d0..977617e599 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryBrowser.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryBrowser.java @@ -1,138 +1,138 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.categories; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.client.sys.cache.ClientCacheManager; -import com.haulmont.cuba.client.sys.cache.DynamicAttributesCacheStrategy; -import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCacheService; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.global.MessageTools; -import com.haulmont.cuba.core.global.Metadata; -import com.haulmont.cuba.gui.AppConfig; -import com.haulmont.cuba.gui.WindowManager; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.components.actions.ItemTrackingAction; -import com.haulmont.cuba.gui.components.actions.RemoveAction; -import com.haulmont.cuba.gui.config.PermissionConfig; -import com.haulmont.cuba.gui.data.CollectionDatasource; - -import javax.inject.Inject; -import java.util.Map; -import java.util.Set; - -public class CategoryBrowser extends AbstractLookup { - - @Inject - protected Metadata metadata; - - @Inject - protected MessageTools messageTools; - - @Inject - protected Table categoryTable; - - @Inject - protected CollectionDatasource categoriesDs; - - @Inject - protected DynamicAttributesCacheService dynamicAttributesCacheService; - - @Inject - protected PermissionConfig permissionConfig; - - @Inject - protected ClientCacheManager clientCacheManager; - - @Override - public void init(Map params) { - categoriesDs = (CollectionDatasource) getDsContext().get("categoriesDs"); - categoryTable.addAction(new CreateAction()); - categoryTable.addAction(new EditAction()); - categoryTable.addAction(new RemoveAction(categoryTable)); - categoryTable.addAction(new AbstractAction("applyChanges") { - @Override - public void actionPerform(Component component) { - dynamicAttributesCacheService.loadCache(); - clientCacheManager.refreshCached(DynamicAttributesCacheStrategy.NAME); - permissionConfig.clearConfigCache(); - showNotification(getMessage("notification.changesApplied"), NotificationType.HUMANIZED); - } - }); - - categoryTable.removeGeneratedColumn("entityType"); - - categoryTable.addGeneratedColumn("entityType", new Table.ColumnGenerator() { - @Override - public Component generateCell(Category entity) { - Label dataTypeLabel = AppConfig.getFactory().createComponent(Label.class); - MetaClass meta = metadata.getSession().getClassNN(entity.getEntityType()); - dataTypeLabel.setValue(messageTools.getEntityCaption(meta)); - return dataTypeLabel; - } - }); - } - - - protected class CreateAction extends AbstractAction { - - public CreateAction() { - super("create"); - } - - @Override - public String getCaption() { - return getMessage("categoryTable.create"); - } - - @Override - public void actionPerform(Component component) { - Category category = metadata.create(Category.class); - Editor editor = openEditor("sys$Category.edit", category, WindowManager.OpenType.THIS_TAB); - editor.addCloseListener(actionId -> { - categoriesDs.refresh(); - categoryTable.requestFocus(); - }); - } - } - - protected class EditAction extends ItemTrackingAction { - - public EditAction() { - super("edit"); - } - - @Override - public String getCaption() { - return getMessage("categoryTable.edit"); - } - - @Override - public void actionPerform(Component component) { - Set selected = categoryTable.getSelected(); - if (!selected.isEmpty()) { - Category category = selected.iterator().next(); - Editor editor = openEditor("sys$Category.edit", category, WindowManager.OpenType.THIS_TAB); - editor.addCloseListener(actionId -> { - categoriesDs.refresh(); - categoryTable.requestFocus(); - }); - } - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.categories; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.client.sys.cache.ClientCacheManager; +import com.haulmont.cuba.client.sys.cache.DynamicAttributesCacheStrategy; +import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesCacheService; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.global.MessageTools; +import com.haulmont.cuba.core.global.Metadata; +import com.haulmont.cuba.gui.AppConfig; +import com.haulmont.cuba.gui.WindowManager; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.components.actions.ItemTrackingAction; +import com.haulmont.cuba.gui.components.actions.RemoveAction; +import com.haulmont.cuba.gui.config.PermissionConfig; +import com.haulmont.cuba.gui.data.CollectionDatasource; + +import javax.inject.Inject; +import java.util.Map; +import java.util.Set; + +public class CategoryBrowser extends AbstractLookup { + + @Inject + protected Metadata metadata; + + @Inject + protected MessageTools messageTools; + + @Inject + protected Table categoryTable; + + @Inject + protected CollectionDatasource categoriesDs; + + @Inject + protected DynamicAttributesCacheService dynamicAttributesCacheService; + + @Inject + protected PermissionConfig permissionConfig; + + @Inject + protected ClientCacheManager clientCacheManager; + + @Override + public void init(Map params) { + categoriesDs = (CollectionDatasource) getDsContext().get("categoriesDs"); + categoryTable.addAction(new CreateAction()); + categoryTable.addAction(new EditAction()); + categoryTable.addAction(new RemoveAction(categoryTable)); + categoryTable.addAction(new AbstractAction("applyChanges") { + @Override + public void actionPerform(Component component) { + dynamicAttributesCacheService.loadCache(); + clientCacheManager.refreshCached(DynamicAttributesCacheStrategy.NAME); + permissionConfig.clearConfigCache(); + showNotification(getMessage("notification.changesApplied"), NotificationType.HUMANIZED); + } + }); + + categoryTable.removeGeneratedColumn("entityType"); + + categoryTable.addGeneratedColumn("entityType", new Table.ColumnGenerator() { + @Override + public Component generateCell(Category entity) { + Label dataTypeLabel = AppConfig.getFactory().createComponent(Label.class); + MetaClass meta = metadata.getSession().getClassNN(entity.getEntityType()); + dataTypeLabel.setValue(messageTools.getEntityCaption(meta)); + return dataTypeLabel; + } + }); + } + + + protected class CreateAction extends AbstractAction { + + public CreateAction() { + super("create"); + } + + @Override + public String getCaption() { + return getMessage("categoryTable.create"); + } + + @Override + public void actionPerform(Component component) { + Category category = metadata.create(Category.class); + Editor editor = openEditor("sys$Category.edit", category, WindowManager.OpenType.THIS_TAB); + editor.addCloseListener(actionId -> { + categoriesDs.refresh(); + categoryTable.requestFocus(); + }); + } + } + + protected class EditAction extends ItemTrackingAction { + + public EditAction() { + super("edit"); + } + + @Override + public String getCaption() { + return getMessage("categoryTable.edit"); + } + + @Override + public void actionPerform(Component component) { + Set selected = categoryTable.getSelected(); + if (!selected.isEmpty()) { + Category category = selected.iterator().next(); + Editor editor = openEditor("sys$Category.edit", category, WindowManager.OpenType.THIS_TAB); + editor.addCloseListener(actionId -> { + categoriesDs.refresh(); + categoryTable.requestFocus(); + }); + } + } + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryEditor.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryEditor.java index 29a56c2753..fba9f99fb1 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryEditor.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/CategoryEditor.java @@ -1,129 +1,129 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.categories; - -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.entity.Category; -import com.haulmont.cuba.core.entity.HasUuid; -import com.haulmont.cuba.core.global.*; -import com.haulmont.cuba.gui.components.AbstractEditor; -import com.haulmont.cuba.gui.components.CheckBox; -import com.haulmont.cuba.gui.components.GroupBoxLayout; -import com.haulmont.cuba.gui.components.LookupField; -import org.apache.commons.lang.BooleanUtils; - -import javax.inject.Inject; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -public class CategoryEditor extends AbstractEditor { - @Inject - protected DataManager dataManager; - @Inject - protected Metadata metadata; - @Inject - protected MessageTools messageTools; - - @Inject - protected GroupBoxLayout localizedGroupBox; - - protected LocalizedNameFrame localizedFrame; - - @Inject - protected GlobalConfig globalConfig; - - @Inject - protected LookupField entityType; - @Inject - protected CheckBox isDefault; - - protected Category category; - - @Override - protected void postInit() { - category = getItem(); - initEntityTypeField(); - initIsDefaultCheckbox(); - initLocalizedFrame(); - } - - protected void initLocalizedFrame() { - if (globalConfig.getAvailableLocales().size() > 1) { - localizedGroupBox.setVisible(true); - localizedFrame = (LocalizedNameFrame) openFrame(localizedGroupBox, "localizedNameFrame"); - localizedFrame.setWidth("100%"); - localizedFrame.setHeight(AUTO_SIZE); - localizedFrame.setValue(category.getLocaleNames()); - } - } - - protected void initEntityTypeField() { - final ExtendedEntities extendedEntities = metadata.getExtendedEntities(); - - Map options = new TreeMap<>();//the map sorts meta classes by the string key - for (MetaClass metaClass : metadata.getTools().getAllPersistentMetaClasses()) { - if (metadata.getTools().hasCompositePrimaryKey(metaClass) && !HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { - continue; - } - options.put(messageTools.getDetailedEntityCaption(metaClass), metaClass); - } - entityType.setOptionsMap(options); - - if (category.getEntityType() != null) { - entityType.setValue(extendedEntities.getEffectiveMetaClass( - extendedEntities.getEffectiveClass(category.getEntityType()))); - } - - entityType.addValueChangeListener(e -> { - MetaClass metaClass = (MetaClass) e.getValue(); - MetaClass originalClass = extendedEntities.getOriginalMetaClass(metaClass); - category.setEntityType(originalClass == null ? metaClass.getName() : originalClass.getName()); - }); - } - - protected void initIsDefaultCheckbox() { - isDefault.setValue(BooleanUtils.isTrue(category.getIsDefault())); - isDefault.addValueChangeListener(e -> { - if (Boolean.TRUE.equals(e.getValue())) { - LoadContext lc = new LoadContext<>(Category.class) - .setView("category.defaultEdit"); - lc.setQueryString("select c from sys$Category c where c.entityType = :entityType and not c.id = :id") - .setParameter("entityType", category.getEntityType()) - .setParameter("id", category.getId()); - List result = dataManager.loadList(lc); - for (Category cat : result) { - cat.setIsDefault(false); - } - CommitContext commitCtx = new CommitContext(result); - dataManager.commit(commitCtx); - category.setIsDefault(true); - } else if (Boolean.FALSE.equals(e.getValue())) { - category.setIsDefault(false); - } - }); - } - - @Override - protected boolean preCommit() { - if (localizedFrame != null) { - category.setLocaleNames(localizedFrame.getValue()); - } - return super.preCommit(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.categories; + +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.entity.Category; +import com.haulmont.cuba.core.entity.HasUuid; +import com.haulmont.cuba.core.global.*; +import com.haulmont.cuba.gui.components.AbstractEditor; +import com.haulmont.cuba.gui.components.CheckBox; +import com.haulmont.cuba.gui.components.GroupBoxLayout; +import com.haulmont.cuba.gui.components.LookupField; +import org.apache.commons.lang.BooleanUtils; + +import javax.inject.Inject; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class CategoryEditor extends AbstractEditor { + @Inject + protected DataManager dataManager; + @Inject + protected Metadata metadata; + @Inject + protected MessageTools messageTools; + + @Inject + protected GroupBoxLayout localizedGroupBox; + + protected LocalizedNameFrame localizedFrame; + + @Inject + protected GlobalConfig globalConfig; + + @Inject + protected LookupField entityType; + @Inject + protected CheckBox isDefault; + + protected Category category; + + @Override + protected void postInit() { + category = getItem(); + initEntityTypeField(); + initIsDefaultCheckbox(); + initLocalizedFrame(); + } + + protected void initLocalizedFrame() { + if (globalConfig.getAvailableLocales().size() > 1) { + localizedGroupBox.setVisible(true); + localizedFrame = (LocalizedNameFrame) openFrame(localizedGroupBox, "localizedNameFrame"); + localizedFrame.setWidth("100%"); + localizedFrame.setHeight(AUTO_SIZE); + localizedFrame.setValue(category.getLocaleNames()); + } + } + + protected void initEntityTypeField() { + final ExtendedEntities extendedEntities = metadata.getExtendedEntities(); + + Map options = new TreeMap<>();//the map sorts meta classes by the string key + for (MetaClass metaClass : metadata.getTools().getAllPersistentMetaClasses()) { + if (metadata.getTools().hasCompositePrimaryKey(metaClass) && !HasUuid.class.isAssignableFrom(metaClass.getJavaClass())) { + continue; + } + options.put(messageTools.getDetailedEntityCaption(metaClass), metaClass); + } + entityType.setOptionsMap(options); + + if (category.getEntityType() != null) { + entityType.setValue(extendedEntities.getEffectiveMetaClass( + extendedEntities.getEffectiveClass(category.getEntityType()))); + } + + entityType.addValueChangeListener(e -> { + MetaClass metaClass = (MetaClass) e.getValue(); + MetaClass originalClass = extendedEntities.getOriginalMetaClass(metaClass); + category.setEntityType(originalClass == null ? metaClass.getName() : originalClass.getName()); + }); + } + + protected void initIsDefaultCheckbox() { + isDefault.setValue(BooleanUtils.isTrue(category.getIsDefault())); + isDefault.addValueChangeListener(e -> { + if (Boolean.TRUE.equals(e.getValue())) { + LoadContext lc = new LoadContext<>(Category.class) + .setView("category.defaultEdit"); + lc.setQueryString("select c from sys$Category c where c.entityType = :entityType and not c.id = :id") + .setParameter("entityType", category.getEntityType()) + .setParameter("id", category.getId()); + List result = dataManager.loadList(lc); + for (Category cat : result) { + cat.setIsDefault(false); + } + CommitContext commitCtx = new CommitContext(result); + dataManager.commit(commitCtx); + category.setIsDefault(true); + } else if (Boolean.FALSE.equals(e.getValue())) { + category.setIsDefault(false); + } + }); + } + + @Override + protected boolean preCommit() { + if (localizedFrame != null) { + category.setLocaleNames(localizedFrame.getValue()); + } + return super.preCommit(); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/ScreenAndComponent.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/ScreenAndComponent.java index d7a6df7417..ec217f56b3 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/ScreenAndComponent.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/ScreenAndComponent.java @@ -1,60 +1,60 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.categories; - -import com.haulmont.chile.core.annotations.MetaClass; -import com.haulmont.chile.core.annotations.MetaProperty; -import com.haulmont.cuba.core.entity.BaseUuidEntity; -import com.haulmont.cuba.core.entity.annotation.SystemLevel; - -@MetaClass(name = "sys$ScreenAndComponent") -@SystemLevel -public class ScreenAndComponent extends BaseUuidEntity { - - private static final long serialVersionUID = -6064270441563369464L; - - @MetaProperty - protected String screen; - - @MetaProperty - protected String component; - - public ScreenAndComponent() { - } - - public ScreenAndComponent(String screen, String component) { - this.screen = screen; - this.component = component; - } - - public String getScreen() { - return screen; - } - - public void setScreen(String screen) { - this.screen = screen; - } - - public String getComponent() { - return component; - } - - public void setComponent(String component) { - this.component = component; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.categories; + +import com.haulmont.chile.core.annotations.MetaClass; +import com.haulmont.chile.core.annotations.MetaProperty; +import com.haulmont.cuba.core.entity.BaseUuidEntity; +import com.haulmont.cuba.core.entity.annotation.SystemLevel; + +@MetaClass(name = "sys$ScreenAndComponent") +@SystemLevel +public class ScreenAndComponent extends BaseUuidEntity { + + private static final long serialVersionUID = -6064270441563369464L; + + @MetaProperty + protected String screen; + + @MetaProperty + protected String component; + + public ScreenAndComponent() { + } + + public ScreenAndComponent(String screen, String component) { + this.screen = screen; + this.component = component; + } + + public String getScreen() { + return screen; + } + + public void setScreen(String screen) { + this.screen = screen; + } + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/attribute-edit.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/attribute-edit.xml index 96c3898eb4..de53c8db5f 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/attribute-edit.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/attribute-edit.xml @@ -1,90 +1,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
\ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-attrs-frame.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-attrs-frame.xml index 3f6922b5cb..680f78488b 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-attrs-frame.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-attrs-frame.xml @@ -1,41 +1,41 @@ - - - - - - - -
-
+ + + + + + + +
+
\ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-browse.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-browse.xml index 3bf6ff640a..cb1062ed3f 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-browse.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-browse.xml @@ -1,58 +1,58 @@ - - - - - - - select c from sys$Category c where c.special is null order by c.createTs - - - - - - - - - - - - - -
-
+ + + + + + + select c from sys$Category c where c.special is null order by c.createTs + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-edit.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-edit.xml index dab78a7373..d85865471d 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-edit.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/category-edit.xml @@ -1,50 +1,50 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages.properties b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages.properties index 12c130177b..bd85a62404 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages.properties +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages.properties @@ -1,89 +1,89 @@ -selectEntityType# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# -categories=Dynamic Attributes -attributes=Attributes -editorCaption=Category editor -localizedEnumerationWindow.caption = Enumeration editor -isDefault=Default -code=Code - -localeGroupBox.caption = Name localization - -filter=Filter - -categoryTable.create=Create category -categoryTable.edit=Edit category -categoryTable.remove=Remove category - -categoryTable.applyChanges=Apply changes -categoryAttrsTable.create=Create -categoryAttrsTable.edit=Edit -categoryAttrsTable.remove=Remove - -AttributeEditor.caption=Attribute editor - -STRING=String -INTEGER=Integer -DOUBLE=Double -BOOLEAN=Boolean -ENTITY=Entity -DATE=Date -ENUMERATION=Enumeration - -true=Yes -false=No - -dataType=Attribute type -defaultValue=Default value -currentDate=Current date -entityType=Entity type - -entityNotFound=Entity not found -screen=Entity selection screen -required=Required attribute - -nameRequired=Name required -dataTypeRequired=Attribute type required -codeRequired=Code required -entityTypeRequired=Entity type required -entityScreenRequired=Entity screen required -enumRequired=Enumeration required -uniqueName=Attribute with same name already exists -uniqueCode=Attribute with same code already exists -widthValidationMsg=Width is incorrect -rowsCountValidationMsg=Rows count should be a number between 1 and 40 - -msgTrue=True -msgFalse=False - -lookup = Drop list -targetScreens=Target screens - -ScreenAndComponent.screen=Screen -ScreenAndComponent.component=Component ID -sys$ScreenAndComponent.screen=Screen -sys$ScreenAndComponent.component=Component ID - -targetScreensTable.create=Add target screen -targetScreensTable.remove=Remove target screen - -caption.mainTab=General -caption.localizedNameTab=Localization -caption.targetScreensTab=Visibility -notification.changesApplied=Changes have been applied -constraintWizard=Constraint Wizard +selectEntityType# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# +categories=Dynamic Attributes +attributes=Attributes +editorCaption=Category editor +localizedEnumerationWindow.caption = Enumeration editor +isDefault=Default +code=Code + +localeGroupBox.caption = Name localization + +filter=Filter + +categoryTable.create=Create category +categoryTable.edit=Edit category +categoryTable.remove=Remove category + +categoryTable.applyChanges=Apply changes +categoryAttrsTable.create=Create +categoryAttrsTable.edit=Edit +categoryAttrsTable.remove=Remove + +AttributeEditor.caption=Attribute editor + +STRING=String +INTEGER=Integer +DOUBLE=Double +BOOLEAN=Boolean +ENTITY=Entity +DATE=Date +ENUMERATION=Enumeration + +true=Yes +false=No + +dataType=Attribute type +defaultValue=Default value +currentDate=Current date +entityType=Entity type + +entityNotFound=Entity not found +screen=Entity selection screen +required=Required attribute + +nameRequired=Name required +dataTypeRequired=Attribute type required +codeRequired=Code required +entityTypeRequired=Entity type required +entityScreenRequired=Entity screen required +enumRequired=Enumeration required +uniqueName=Attribute with same name already exists +uniqueCode=Attribute with same code already exists +widthValidationMsg=Width is incorrect +rowsCountValidationMsg=Rows count should be a number between 1 and 40 + +msgTrue=True +msgFalse=False + +lookup = Drop list +targetScreens=Target screens + +ScreenAndComponent.screen=Screen +ScreenAndComponent.component=Component ID +sys$ScreenAndComponent.screen=Screen +sys$ScreenAndComponent.component=Component ID + +targetScreensTable.create=Add target screen +targetScreensTable.remove=Remove target screen + +caption.mainTab=General +caption.localizedNameTab=Localization +caption.targetScreensTab=Visibility +notification.changesApplied=Changes have been applied +constraintWizard=Constraint Wizard selectEntityType=Select entity type \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages_ru.properties b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages_ru.properties index 6f044c6e22..68c55fa263 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages_ru.properties +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/categories/messages_ru.properties @@ -1,91 +1,91 @@ -# -# Copyright (c) 2008-2016 Haulmont. -# -# 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. -# -# -categories=Динамические атрибуты -attributes=Атрибуты -editorCaption=Редактирование категории -localizedEnumerationWindow.caption = Редактирование перечисления -isDefault=По умолчанию -code=Код - -localeGroupBox.caption = Локализация названия - -filter=Фильтр - -categoryTable.create=Создать категорию -categoryTable.edit=Изменить категорию -categoryTable.remove=Удалить категорию - -categoryTable.applyChanges=Применить изменения -categoryAttrsTable.create=Создать -categoryAttrsTable.edit=Изменить -categoryAttrsTable.remove=Удалить - -AttributeEditor.caption=Редактирование атрибута - -STRING=Строка -INTEGER=Целое число -DOUBLE=Вещественное число -BOOLEAN=Логическое -ENTITY=Сущность -DATE=Дата -ENUMERATION=Перечисление - -true=Да -false=Нет - -dataType=Тип атрибута -defaultValue=Значение по умолчанию -currentDate=Текущая дата -entityType=Тип сущности -screen=Экран выбора сущности -required=Обязательный атрибут - -entityNotFound=Сущность не найдена - -nameRequired=Заполните поле "Название" -dataTypeRequired=Заполните поле "Тип атрибута" -entityTypeRequired=Заполните поле "Тип сущности" -entityScreenRequired=Заполните поле "Экран выбора сущности" -widthValidationMsg=Поле "Ширина" указано в некорректном формате -rowsCountValidationMsg=Поле "Количество строк" должно быть числом от 1 до 40 -enumRequired=Заполните поле "Перечисление" - -msgTrue=Да -msgFalse=Нет - -uniqueName=Атрибут с таким названием уже существует -uniqueCode=Атрибут с таким кодом уже существует - -lookup = Выпадающий список -targetScreens=Экраны для показа - -ScreenAndComponent.screen=Экран -ScreenAndComponent.component=Идентификатор компонента -sys$ScreenAndComponent.screen=Экран -sys$ScreenAndComponent.component=Идентификатор компонента - -caption.mainTab=Общее -caption.localizedNameTab=Локализация -caption.targetScreensTab=Видимость - -targetScreensTable.create=Добавить экран -targetScreensTable.remove=Удалить экран -codeRequired=Заполните поле "Код" - -notification.changesApplied=Изменения применены -constraintWizard=Мастер создания ограничения +# +# Copyright (c) 2008-2016 Haulmont. +# +# 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. +# +# +categories=Динамические атрибуты +attributes=Атрибуты +editorCaption=Редактирование категории +localizedEnumerationWindow.caption = Редактирование перечисления +isDefault=По умолчанию +code=Код + +localeGroupBox.caption = Локализация названия + +filter=Фильтр + +categoryTable.create=Создать категорию +categoryTable.edit=Изменить категорию +categoryTable.remove=Удалить категорию + +categoryTable.applyChanges=Применить изменения +categoryAttrsTable.create=Создать +categoryAttrsTable.edit=Изменить +categoryAttrsTable.remove=Удалить + +AttributeEditor.caption=Редактирование атрибута + +STRING=Строка +INTEGER=Целое число +DOUBLE=Вещественное число +BOOLEAN=Логическое +ENTITY=Сущность +DATE=Дата +ENUMERATION=Перечисление + +true=Да +false=Нет + +dataType=Тип атрибута +defaultValue=Значение по умолчанию +currentDate=Текущая дата +entityType=Тип сущности +screen=Экран выбора сущности +required=Обязательный атрибут + +entityNotFound=Сущность не найдена + +nameRequired=Заполните поле "Название" +dataTypeRequired=Заполните поле "Тип атрибута" +entityTypeRequired=Заполните поле "Тип сущности" +entityScreenRequired=Заполните поле "Экран выбора сущности" +widthValidationMsg=Поле "Ширина" указано в некорректном формате +rowsCountValidationMsg=Поле "Количество строк" должно быть числом от 1 до 40 +enumRequired=Заполните поле "Перечисление" + +msgTrue=Да +msgFalse=Нет + +uniqueName=Атрибут с таким названием уже существует +uniqueCode=Атрибут с таким кодом уже существует + +lookup = Выпадающий список +targetScreens=Экраны для показа + +ScreenAndComponent.screen=Экран +ScreenAndComponent.component=Идентификатор компонента +sys$ScreenAndComponent.screen=Экран +sys$ScreenAndComponent.component=Идентификатор компонента + +caption.mainTab=Общее +caption.localizedNameTab=Локализация +caption.targetScreensTab=Видимость + +targetScreensTable.create=Добавить экран +targetScreensTable.remove=Удалить экран +codeRequired=Заполните поле "Код" + +notification.changesApplied=Изменения применены +constraintWizard=Мастер создания ограничения selectEntityType=Выберите тип сущности \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/dynamicattributes/runtime-properties-frame.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/dynamicattributes/runtime-properties-frame.xml index fe2503d6a3..c4e8729d85 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/dynamicattributes/runtime-properties-frame.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/dynamicattributes/runtime-properties-frame.xml @@ -1,28 +1,28 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffStyleProvider.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffStyleProvider.java index b1e207371b..b8bd969d76 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffStyleProvider.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffStyleProvider.java @@ -1,62 +1,62 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.entitydiff; - -import com.haulmont.cuba.core.entity.diff.EntityBasicPropertyDiff; -import com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff; -import com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff; -import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; -import com.haulmont.cuba.gui.components.Table; - -/** - * Set icons and colors for EntityDiff UI - * - */ -public class DiffStyleProvider implements Table.StyleProvider { - - @Override - public String getStyleName(EntityPropertyDiff entity, String property) { - if (property != null) { - if ("name".equals(property)) { - if (entity instanceof EntityClassPropertyDiff) { - switch (entity.getItemState()) { - case Added: - return "addedItem"; - - case Modified: - return "modifiedItem"; - - case Normal: - if (((EntityClassPropertyDiff) entity).isLinkChange()) - return "chainItem"; - else - return "modifiedItem"; - - case Removed: - return "removedItem"; - } - } else if (entity instanceof EntityCollectionPropertyDiff) { - return "categoryItem"; - } else if (entity instanceof EntityBasicPropertyDiff) { - //return "modifiedItem"; - } - } - } - return null; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.entitydiff; + +import com.haulmont.cuba.core.entity.diff.EntityBasicPropertyDiff; +import com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff; +import com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff; +import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; +import com.haulmont.cuba.gui.components.Table; + +/** + * Set icons and colors for EntityDiff UI + * + */ +public class DiffStyleProvider implements Table.StyleProvider { + + @Override + public String getStyleName(EntityPropertyDiff entity, String property) { + if (property != null) { + if ("name".equals(property)) { + if (entity instanceof EntityClassPropertyDiff) { + switch (entity.getItemState()) { + case Added: + return "addedItem"; + + case Modified: + return "modifiedItem"; + + case Normal: + if (((EntityClassPropertyDiff) entity).isLinkChange()) + return "chainItem"; + else + return "modifiedItem"; + + case Removed: + return "removedItem"; + } + } else if (entity instanceof EntityCollectionPropertyDiff) { + return "categoryItem"; + } else if (entity instanceof EntityBasicPropertyDiff) { + //return "modifiedItem"; + } + } + } + return null; + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffTreeDatasource.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffTreeDatasource.java index 3fa672df81..79dbf3a89d 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffTreeDatasource.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/DiffTreeDatasource.java @@ -1,114 +1,114 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.entitydiff; - -import com.haulmont.bali.datastruct.Node; -import com.haulmont.bali.datastruct.Tree; -import com.haulmont.chile.core.model.MetaClass; -import com.haulmont.cuba.core.app.EntitySnapshotService; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff; -import com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.core.global.Security; -import com.haulmont.cuba.gui.data.impl.AbstractTreeDatasource; -import com.haulmont.cuba.security.entity.EntityAttrAccess; -import com.haulmont.cuba.security.entity.EntityOp; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -public class DiffTreeDatasource extends AbstractTreeDatasource { - - protected EntityDiff entityDiff; - - @Override - protected Tree loadTree(Map params) { - Tree diffTree = new Tree<>(); - List> rootNodes = new ArrayList<>(); - if (entityDiff != null) { - for (EntityPropertyDiff childPropertyDiff : entityDiff.getPropertyDiffs()) { - Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); - - if (childPropDiffNode != null) - rootNodes.add(childPropDiffNode); - } - } - diffTree.setRootNodes(rootNodes); - return diffTree; - } - - protected Node loadPropertyDiff(EntityPropertyDiff propertyDiff) { - Node diffNode = null; - if (propertyDiff != null) { - // check security - String propName = propertyDiff.getViewProperty().getName(); - MetaClass propMetaClass = metadata.getSession().getClass(propertyDiff.getMetaClassName()); - - Security security = AppBeans.get(Security.NAME); - if (!security.isEntityOpPermitted(propMetaClass, EntityOp.READ) - || !security.isEntityAttrPermitted(propMetaClass, propName, EntityAttrAccess.VIEW)) { - return null; - } - - diffNode = new Node<>(propertyDiff); - if (propertyDiff instanceof EntityClassPropertyDiff) { - - EntityClassPropertyDiff classPropertyDiff = (EntityClassPropertyDiff) propertyDiff; - for (EntityPropertyDiff childPropertyDiff : classPropertyDiff.getPropertyDiffs()) { - Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); - if (childPropDiffNode != null) - diffNode.addChild(childPropDiffNode); - } - } else if (propertyDiff instanceof EntityCollectionPropertyDiff) { - EntityCollectionPropertyDiff collectionPropertyDiff = (EntityCollectionPropertyDiff) propertyDiff; - for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getAddedEntities()) { - Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); - if (childPropDiffNode != null) - diffNode.addChild(childPropDiffNode); - } - - for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getModifiedEntities()) { - Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); - if (childPropDiffNode != null) - diffNode.addChild(childPropDiffNode); - } - - for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getRemovedEntities()) { - Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); - if (childPropDiffNode != null) - diffNode.addChild(childPropDiffNode); - } - } - } - return diffNode; - } - - public EntityDiff loadDiff(EntitySnapshot firstSnap, EntitySnapshot secondSnap) { - EntitySnapshotService snapshotService = AppBeans.get(EntitySnapshotService.NAME); - entityDiff = snapshotService.getDifference(firstSnap, secondSnap); - - this.refresh(); - - return entityDiff; - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.entitydiff; + +import com.haulmont.bali.datastruct.Node; +import com.haulmont.bali.datastruct.Tree; +import com.haulmont.chile.core.model.MetaClass; +import com.haulmont.cuba.core.app.EntitySnapshotService; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.EntityClassPropertyDiff; +import com.haulmont.cuba.core.entity.diff.EntityCollectionPropertyDiff; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.core.global.Security; +import com.haulmont.cuba.gui.data.impl.AbstractTreeDatasource; +import com.haulmont.cuba.security.entity.EntityAttrAccess; +import com.haulmont.cuba.security.entity.EntityOp; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class DiffTreeDatasource extends AbstractTreeDatasource { + + protected EntityDiff entityDiff; + + @Override + protected Tree loadTree(Map params) { + Tree diffTree = new Tree<>(); + List> rootNodes = new ArrayList<>(); + if (entityDiff != null) { + for (EntityPropertyDiff childPropertyDiff : entityDiff.getPropertyDiffs()) { + Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); + + if (childPropDiffNode != null) + rootNodes.add(childPropDiffNode); + } + } + diffTree.setRootNodes(rootNodes); + return diffTree; + } + + protected Node loadPropertyDiff(EntityPropertyDiff propertyDiff) { + Node diffNode = null; + if (propertyDiff != null) { + // check security + String propName = propertyDiff.getViewProperty().getName(); + MetaClass propMetaClass = metadata.getSession().getClass(propertyDiff.getMetaClassName()); + + Security security = AppBeans.get(Security.NAME); + if (!security.isEntityOpPermitted(propMetaClass, EntityOp.READ) + || !security.isEntityAttrPermitted(propMetaClass, propName, EntityAttrAccess.VIEW)) { + return null; + } + + diffNode = new Node<>(propertyDiff); + if (propertyDiff instanceof EntityClassPropertyDiff) { + + EntityClassPropertyDiff classPropertyDiff = (EntityClassPropertyDiff) propertyDiff; + for (EntityPropertyDiff childPropertyDiff : classPropertyDiff.getPropertyDiffs()) { + Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); + if (childPropDiffNode != null) + diffNode.addChild(childPropDiffNode); + } + } else if (propertyDiff instanceof EntityCollectionPropertyDiff) { + EntityCollectionPropertyDiff collectionPropertyDiff = (EntityCollectionPropertyDiff) propertyDiff; + for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getAddedEntities()) { + Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); + if (childPropDiffNode != null) + diffNode.addChild(childPropDiffNode); + } + + for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getModifiedEntities()) { + Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); + if (childPropDiffNode != null) + diffNode.addChild(childPropDiffNode); + } + + for (EntityPropertyDiff childPropertyDiff : collectionPropertyDiff.getRemovedEntities()) { + Node childPropDiffNode = loadPropertyDiff(childPropertyDiff); + if (childPropDiffNode != null) + diffNode.addChild(childPropDiffNode); + } + } + } + return diffNode; + } + + public EntityDiff loadDiff(EntitySnapshot firstSnap, EntitySnapshot secondSnap) { + EntitySnapshotService snapshotService = AppBeans.get(EntitySnapshotService.NAME); + entityDiff = snapshotService.getDifference(firstSnap, secondSnap); + + this.refresh(); + + return entityDiff; + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffDatasource.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffDatasource.java index 20a7f65288..e7ce93c70a 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffDatasource.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffDatasource.java @@ -1,32 +1,32 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.entitydiff; - -import com.haulmont.cuba.gui.data.impl.DatasourceImpl; - -/** - * Fake datasource for non-persistent entity EntityDiff - * - */ -public class EntityDiffDatasource extends DatasourceImpl { - - @Override - public boolean isModified() { - return false; - } -} +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.entitydiff; + +import com.haulmont.cuba.gui.data.impl.DatasourceImpl; + +/** + * Fake datasource for non-persistent entity EntityDiff + * + */ +public class EntityDiffDatasource extends DatasourceImpl { + + @Override + public boolean isModified() { + return false; + } +} diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffViewer.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffViewer.java index 8378794834..7997613a96 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffViewer.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntityDiffViewer.java @@ -1,122 +1,122 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.entitydiff; - -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.diff.EntityDiff; -import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; -import com.haulmont.cuba.gui.components.*; -import com.haulmont.cuba.gui.data.Datasource; - -import javax.inject.Inject; -import java.util.Map; -import java.util.Set; - -public class EntityDiffViewer extends AbstractFrame { - - @Inject - private EntitySnapshotsDatasource snapshotsDs; - - @Inject - private Datasource entityDiffDs; - - @Inject - private DiffTreeDatasource diffDs; - - @Inject - private Table snapshotsTable; - - @Inject - private TreeTable diffTable; - - @Inject - private Label itemStateLabel; - - @Inject - private Label valuesHeader; - - @Inject - private Component itemStateField; - - @Inject - private Component diffValuesField; - - @Override - public void init(Map params) { - super.init(params); - - diffTable.setStyleProvider(new DiffStyleProvider()); - diffTable.setIconProvider(new DiffIconProvider()); - - diffDs.addItemChangeListener(e -> { - boolean valuesVisible = (e.getItem() != null) && (e.getItem().hasStateValues()); - boolean stateVisible = (e.getItem() != null) && (e.getItem().hasStateValues() && e.getItem().itemStateVisible()); - - valuesHeader.setVisible(stateVisible || valuesVisible); - itemStateField.setVisible(stateVisible); - diffValuesField.setVisible(valuesVisible); - - if (e.getItem() != null) { - EntityPropertyDiff.ItemState itemState = e.getItem().getItemState(); - if (itemState != EntityPropertyDiff.ItemState.Normal) { - String messageCode = "ItemState." + itemState.toString(); - itemStateLabel.setValue(getMessage(messageCode)); - itemStateLabel.setVisible(true); - } else { - itemStateField.setVisible(false); - } - } - }); - } - - @SuppressWarnings("unused") - public void compareSnapshots() { - entityDiffDs.setItem(null); - - EntitySnapshot firstSnap = null; - EntitySnapshot secondSnap = null; - - Set selected = snapshotsTable.getSelected(); - Object[] selectedItems = selected.toArray(); - if ((selected.size() == 2)) { - firstSnap = (EntitySnapshot) selectedItems[0]; - secondSnap = (EntitySnapshot) selectedItems[1]; - } else if (selected.size() == 1) { - secondSnap = (EntitySnapshot) selectedItems[0]; - firstSnap = snapshotsDs.getLatestSnapshot(); - if (firstSnap == secondSnap) - firstSnap = null; - } - - if ((secondSnap != null) || (firstSnap != null)) { - EntityDiff diff = diffDs.loadDiff(firstSnap, secondSnap); - entityDiffDs.setItem(diff); - } - - diffTable.refresh(); - diffTable.expandAll(); - } - - public void loadVersions(Entity entity) { - snapshotsDs.setEntity(entity); - snapshotsDs.refresh(); - - snapshotsTable.repaint(); - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.entitydiff; + +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.diff.EntityDiff; +import com.haulmont.cuba.core.entity.diff.EntityPropertyDiff; +import com.haulmont.cuba.gui.components.*; +import com.haulmont.cuba.gui.data.Datasource; + +import javax.inject.Inject; +import java.util.Map; +import java.util.Set; + +public class EntityDiffViewer extends AbstractFrame { + + @Inject + private EntitySnapshotsDatasource snapshotsDs; + + @Inject + private Datasource entityDiffDs; + + @Inject + private DiffTreeDatasource diffDs; + + @Inject + private Table snapshotsTable; + + @Inject + private TreeTable diffTable; + + @Inject + private Label itemStateLabel; + + @Inject + private Label valuesHeader; + + @Inject + private Component itemStateField; + + @Inject + private Component diffValuesField; + + @Override + public void init(Map params) { + super.init(params); + + diffTable.setStyleProvider(new DiffStyleProvider()); + diffTable.setIconProvider(new DiffIconProvider()); + + diffDs.addItemChangeListener(e -> { + boolean valuesVisible = (e.getItem() != null) && (e.getItem().hasStateValues()); + boolean stateVisible = (e.getItem() != null) && (e.getItem().hasStateValues() && e.getItem().itemStateVisible()); + + valuesHeader.setVisible(stateVisible || valuesVisible); + itemStateField.setVisible(stateVisible); + diffValuesField.setVisible(valuesVisible); + + if (e.getItem() != null) { + EntityPropertyDiff.ItemState itemState = e.getItem().getItemState(); + if (itemState != EntityPropertyDiff.ItemState.Normal) { + String messageCode = "ItemState." + itemState.toString(); + itemStateLabel.setValue(getMessage(messageCode)); + itemStateLabel.setVisible(true); + } else { + itemStateField.setVisible(false); + } + } + }); + } + + @SuppressWarnings("unused") + public void compareSnapshots() { + entityDiffDs.setItem(null); + + EntitySnapshot firstSnap = null; + EntitySnapshot secondSnap = null; + + Set selected = snapshotsTable.getSelected(); + Object[] selectedItems = selected.toArray(); + if ((selected.size() == 2)) { + firstSnap = (EntitySnapshot) selectedItems[0]; + secondSnap = (EntitySnapshot) selectedItems[1]; + } else if (selected.size() == 1) { + secondSnap = (EntitySnapshot) selectedItems[0]; + firstSnap = snapshotsDs.getLatestSnapshot(); + if (firstSnap == secondSnap) + firstSnap = null; + } + + if ((secondSnap != null) || (firstSnap != null)) { + EntityDiff diff = diffDs.loadDiff(firstSnap, secondSnap); + entityDiffDs.setItem(diff); + } + + diffTable.refresh(); + diffTable.expandAll(); + } + + public void loadVersions(Entity entity) { + snapshotsDs.setEntity(entity); + snapshotsDs.refresh(); + + snapshotsTable.repaint(); + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntitySnapshotsDatasource.java b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntitySnapshotsDatasource.java index 50cfcc86c0..0c00b12e3c 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntitySnapshotsDatasource.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/EntitySnapshotsDatasource.java @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2008-2016 Haulmont. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.haulmont.cuba.gui.app.core.entitydiff; - -import com.haulmont.cuba.core.app.EntitySnapshotService; -import com.haulmont.cuba.core.entity.Entity; -import com.haulmont.cuba.core.entity.EntitySnapshot; -import com.haulmont.cuba.core.entity.HasUuid; -import com.haulmont.cuba.core.global.AppBeans; -import com.haulmont.cuba.gui.data.impl.CustomCollectionDatasource; - -import java.util.*; - -public class EntitySnapshotsDatasource extends CustomCollectionDatasource { - - protected Entity entity; - protected List snapshots; - - @Override - public boolean isModified() { - return false; - } - - public Entity getEntity() { - return entity; - } - - public void setEntity(Entity entity) { - this.entity = entity; - } - - @Override - protected Collection getEntities(Map params) { - if (entity != null) { - EntitySnapshotService snapshotService = AppBeans.get(EntitySnapshotService.NAME); - snapshots = snapshotService.getSnapshots(entity.getMetaClass(), entity.getId()); - return snapshots; - } - return Collections.emptyList(); - } - - public EntitySnapshot getLatestSnapshot() { - if (snapshots != null && snapshots.size() > 0) { - return snapshots.get(snapshots.size() - 1); - } else { - return null; - } - } +/* + * Copyright (c) 2008-2016 Haulmont. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.haulmont.cuba.gui.app.core.entitydiff; + +import com.haulmont.cuba.core.app.EntitySnapshotService; +import com.haulmont.cuba.core.entity.Entity; +import com.haulmont.cuba.core.entity.EntitySnapshot; +import com.haulmont.cuba.core.entity.HasUuid; +import com.haulmont.cuba.core.global.AppBeans; +import com.haulmont.cuba.gui.data.impl.CustomCollectionDatasource; + +import java.util.*; + +public class EntitySnapshotsDatasource extends CustomCollectionDatasource { + + protected Entity entity; + protected List snapshots; + + @Override + public boolean isModified() { + return false; + } + + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + } + + @Override + protected Collection getEntities(Map params) { + if (entity != null) { + EntitySnapshotService snapshotService = AppBeans.get(EntitySnapshotService.NAME); + snapshots = snapshotService.getSnapshots(entity.getMetaClass(), entity.getId()); + return snapshots; + } + return Collections.emptyList(); + } + + public EntitySnapshot getLatestSnapshot() { + if (snapshots != null && snapshots.size() > 0) { + return snapshots.get(snapshots.size() - 1); + } else { + return null; + } + } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/diff-view.xml b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/diff-view.xml index 66a8601707..d222241063 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/diff-view.xml +++ b/modules/gui/src/com/haulmont/cuba/gui/app/core/entitydiff/diff-view.xml @@ -1,87 +1,87 @@ - - - - - - - - - - - - - - - -